diff --git a/.gitignore b/.gitignore index cab742a2313..8bbd8c40c7c 100644 --- a/.gitignore +++ b/.gitignore @@ -20,4 +20,15 @@ test_output.txt plotly/api/v2/spectacle_presentations.py -plotly/presentation_objs/ \ No newline at end of file +plotly/presentation_objs/ + +plotly/datatypes + +plotly/validators + +.idea + +js/node_modules/ + +# Compiled javascript +plotlywidget/static/ diff --git a/codegen/__init__.py b/codegen/__init__.py new file mode 100644 index 00000000000..52bcb8a8cf7 --- /dev/null +++ b/codegen/__init__.py @@ -0,0 +1,78 @@ +import json +import os.path as opath +import os +import shutil + +import time + +from codegen.datatypes import build_datatypes_py, write_datatypes_py, append_figure_class +from codegen.utils import TraceNode, PlotlyNode, LayoutNode, FrameNode +from codegen.validators import write_validator_py, append_traces_validator_py + + +def perform_codegen(): + outdir = 'plotly/' + # outdir = 'codegen/output' + # Load plotly schema + # ------------------ + with open('plotly/package_data/default-schema.json', 'r') as f: + plotly_schema = json.load(f) + + # Compute property paths + # ---------------------- + base_traces_node = TraceNode(plotly_schema) + compound_trace_nodes = PlotlyNode.get_all_compound_datatype_nodes(plotly_schema, TraceNode) + compound_layout_nodes = PlotlyNode.get_all_compound_datatype_nodes(plotly_schema, LayoutNode) + compound_frame_nodes = PlotlyNode.get_all_compound_datatype_nodes(plotly_schema, FrameNode) + + extra_layout_nodes = PlotlyNode.get_all_trace_layout_nodes(plotly_schema) + + # Write out validators + # -------------------- + validators_pkgdir = opath.join(outdir, 'validators') + if opath.exists(validators_pkgdir): + shutil.rmtree(validators_pkgdir) + + # ### Layout ### + for node in compound_layout_nodes: + write_validator_py(outdir, node, extra_layout_nodes) + + # ### Trace ### + for node in compound_trace_nodes: + write_validator_py(outdir, node) + + # Write out datatypes + # ------------------- + datatypes_pkgdir = opath.join(outdir, 'datatypes') + if opath.exists(datatypes_pkgdir): + shutil.rmtree(datatypes_pkgdir) + + # ### Layout ### + for node in compound_layout_nodes: + write_datatypes_py(outdir, node, extra_layout_nodes) + + # ### Trace ### + for node in compound_trace_nodes: + write_datatypes_py(outdir, node) + + # Append traces validator class + # ----------------------------- + append_traces_validator_py(validators_pkgdir, base_traces_node) + + # Add Frames + # ---------- + # ### Validator ### + for node in compound_frame_nodes: + write_validator_py(outdir, node) + + # ### Datatypes ### + for node in compound_frame_nodes: + write_datatypes_py(outdir, node) + + # Append figure class to datatypes + # -------------------------------- + append_figure_class(datatypes_pkgdir, base_traces_node) + + +if __name__ == '__main__': + perform_codegen() diff --git a/codegen/datatypes.py b/codegen/datatypes.py new file mode 100644 index 00000000000..0073e792649 --- /dev/null +++ b/codegen/datatypes.py @@ -0,0 +1,360 @@ +from io import StringIO +import os +import os.path as opath +import textwrap +import importlib +from typing import List, Dict + +from codegen.utils import TraceNode, format_source, PlotlyNode + + +def get_typing_type(plotly_type, array_ok=False): + if plotly_type in ('data_array', 'info_array', 'colorlist'): + pytype = 'List' + elif plotly_type in ('string', 'color', 'colorscale', 'subplotid'): + pytype = 'str' + elif plotly_type in ('enumerated', 'flaglist', 'any'): + pytype = 'Any' + elif plotly_type in ('number', 'angle'): + pytype = 'Number' + elif plotly_type == 'integer': + pytype = 'int' + elif plotly_type == 'boolean': + pytype = 'bool' + else: + raise ValueError('Unknown plotly type: %s' % plotly_type) + + if array_ok: + return f'Union[{pytype}, List[{pytype}]]' + else: + return pytype + + +def build_datatypes_py(parent_node: PlotlyNode, + extra_nodes: Dict[str, 'PlotlyNode'] = {}): + + compound_nodes = parent_node.child_compound_datatypes + if not compound_nodes: + return None + + buffer = StringIO() + + # Imports + # ------- + buffer.write('from typing import *\n') + buffer.write('from numbers import Number\n') + buffer.write(f'from plotly.basedatatypes import {parent_node.base_datatype_class}\n') + + # ### Validators ### + validators_csv = ', '.join([f'{n.plotly_name} as v_{n.plotly_name}' for n in compound_nodes]) + buffer.write(f'from plotly.validators{parent_node.pkg_str} import ({validators_csv})\n') + + # ### Datatypes ### + datatypes_csv = ', '.join([f'{n.plotly_name} as d_{n.plotly_name}' for n in compound_nodes if n.child_compound_datatypes]) + if datatypes_csv: + buffer.write(f'from plotly.datatypes{parent_node.pkg_str} import ({datatypes_csv})\n') + + # Compound datatypes loop + # ----------------------- + for compound_node in compound_nodes: + + # grab literals + literal_nodes = [n for n in compound_node.child_literals if n.plotly_name in ['type']] + + # ### Class definition ### + buffer.write(f""" + +class {compound_node.name_class}({parent_node.base_datatype_class}):\n""") + + # ### Property definitions ### + child_datatype_nodes = compound_node.child_datatypes + extra_subtype_nodes = [node for node_name, node in + extra_nodes.items() if + node_name.startswith(compound_node.dir_str)] + + subtype_nodes = child_datatype_nodes + extra_subtype_nodes + for subtype_node in subtype_nodes: + if subtype_node.is_array_element: + prop_type = f'Tuple[d_{compound_node.plotly_name}.{subtype_node.name_class}]' + elif subtype_node.is_compound: + prop_type = f'd_{compound_node.plotly_name}.{subtype_node.name_class}' + else: + prop_type = get_typing_type(subtype_node.datatype) + + + # #### Get property description #### + raw_description = subtype_node.description + property_description = '\n'.join(textwrap.wrap(raw_description, + subsequent_indent=' ' * 8, + width=80 - 8)) + + # #### Get validator description #### + validator = subtype_node.validator_instance + validator_description = reindent_validator_description(validator, 4) + + # #### Combine to form property docstring #### + if property_description.strip(): + property_docstring = f"""{property_description} + + {validator_description}""" + else: + property_docstring = validator_description + + # #### Write property ### + buffer.write(f"""\ + + # {subtype_node.name_property} + # {'-' * len(subtype_node.name_property)} + @property + def {subtype_node.name_property}(self) -> {prop_type}: + \"\"\" + {property_docstring} + \"\"\" + return self['{subtype_node.name_property}']""") + + # #### Set property ### + buffer.write(f""" + + @{subtype_node.name_property}.setter + def {subtype_node.name_property}(self, val): + self['{subtype_node.name_property}'] = val\n""") + + # ### Literals ### + for literal_node in literal_nodes: + buffer.write(f"""\ + + # {literal_node.name_property} + # {'-' * len(literal_node.name_property)} + @property + def {literal_node.name_property}(self) -> {prop_type}: + return self._props['{literal_node.name_property}']\n""") + + # ### Self properties description ### + buffer.write(f""" + + # property parent name + # -------------------- + @property + def _parent_path(self) -> str: + return '{compound_node.parent_dir_str}' + + # Self properties description + # --------------------------- + @property + def _prop_descriptions(self) -> str: + return \"\"\"\\""") + + buffer.write(compound_node.get_constructor_params_docstring( + indent=8, + extra_nodes=extra_subtype_nodes)) + + buffer.write(f""" + \"\"\"""") + + # ### Constructor ### + buffer.write(f""" + def __init__(self""") + + add_constructor_params(buffer, subtype_nodes) + add_docstring(buffer, compound_node, extra_subtype_nodes) + + buffer.write(f""" + super().__init__('{compound_node.name_property}', **kwargs) + + # Initialize validators + # ---------------------""") + for subtype_node in subtype_nodes: + + buffer.write(f""" + self._validators['{subtype_node.name_property}'] = v_{compound_node.plotly_name}.{subtype_node.name_validator}()""") + + buffer.write(f""" + + # Populate data dict with properties + # ----------------------------------""") + for subtype_node in subtype_nodes: + buffer.write(f""" + self.{subtype_node.name_property} = {subtype_node.name_property}""") + + # ### Literals ### + literal_nodes = [n for n in compound_node.child_literals if n.plotly_name in ['type']] + if literal_nodes: + buffer.write(f""" + + # Read-only literals + # ------------------""") + for literal_node in literal_nodes: + buffer.write(f""" + self._props['{literal_node.name_property}'] = '{literal_node.node_data}'""") + + return buffer.getvalue() + + +def reindent_validator_description(validator, extra_indent): + # Remove leading indent and add extra spaces to subsequent indent + return ('\n' + ' ' * extra_indent).join(validator.description().strip().split('\n')) + + +def add_constructor_params(buffer, subtype_nodes, colon=True): + for i, subtype_node in enumerate(subtype_nodes): + dflt = None + buffer.write(f""", + {subtype_node.name_property}={repr(dflt)}""") + + buffer.write(""", + **kwargs""") + buffer.write(f""" + ){':' if colon else ''}""") + + +def add_docstring(buffer, compound_node, extra_subtype_nodes=[]): + # ### Docstring ### + buffer.write(f""" + \"\"\" + Construct a new {compound_node.name_pascal_case} object + + Parameters + ----------""") + buffer.write(compound_node.get_constructor_params_docstring( + indent=8, + extra_nodes=extra_subtype_nodes )) + + # #### close docstring #### + buffer.write(f""" + + Returns + ------- + {compound_node.name_pascal_case} + \"\"\"""") + + +def write_datatypes_py(outdir, node: PlotlyNode, + extra_nodes: Dict[str, 'PlotlyNode']={}): + + # Generate source code + # -------------------- + datatype_source = build_datatypes_py(node, extra_nodes) + if datatype_source: + try: + formatted_source = format_source(datatype_source) + except Exception as e: + print(datatype_source) + raise e + + # Write file + # ---------- + filedir = opath.join(outdir, 'datatypes', *node.dir_path) + os.makedirs(filedir, exist_ok=True) + filepath = opath.join(filedir, '__init__.py') + + mode = 'at' if os.path.exists(filepath) else 'wt' + with open(filepath, mode) as f: + if mode == 'at': + f.write("\n\n") + f.write(formatted_source) + f.flush() + os.fsync(f.fileno()) + + +def build_figure_py(trace_node, base_package, base_classname, fig_classname): + buffer = StringIO() + trace_nodes = trace_node.child_compound_datatypes + + # Imports + # ------- + buffer.write(f'from plotly.{base_package} import {base_classname}\n') + + trace_types_csv = ', '.join([n.name_pascal_case for n in trace_nodes]) + buffer.write(f'from plotly.datatypes.trace import ({trace_types_csv})\n') + + buffer.write(f""" + +class {fig_classname}({base_classname}):\n""") + + # Reload validators and datatypes modules since we're appending + # Classes to them as we go + validators_module = importlib.import_module('plotly.validators') + importlib.reload(validators_module) + datatypes_module = importlib.import_module('plotly.datatypes') + importlib.reload(datatypes_module) + + # Build constructor description strings + data_validator = validators_module.DataValidator() + data_description = reindent_validator_description(data_validator, 8) + + layout_validator = validators_module.LayoutValidator() + layout_description = reindent_validator_description(layout_validator, 8) + + frames_validator = validators_module.FramesValidator() + frames_description = reindent_validator_description(frames_validator, 8) + + buffer.write(f""" + def __init__(self, data=None, layout=None, frames=None): + \"\"\" + Create a new {fig_classname} instance + + Parameters + ---------- + data + {data_description} + layout + {layout_description} + frames + {frames_description} + \"\"\" + super().__init__(data, layout, frames) + """) + + # add_trace methods + for trace_node in trace_nodes: + + # Function signature + # ------------------ + buffer.write(f""" + def add_{trace_node.plotly_name}(self""") + + add_constructor_params(buffer, trace_node.child_datatypes) + add_docstring(buffer, trace_node) + + # Function body + # ------------- + buffer.write(f""" + new_trace = {trace_node.name_pascal_case}( + """) + + for i, subtype_node in enumerate(trace_node.child_datatypes): + is_last = i == len(trace_node.child_datatypes) - 1 + buffer.write(f""" + {subtype_node.name_property}={subtype_node.name_property}{'' if is_last else ','}""") + + buffer.write(f""", + **kwargs)""") + + buffer.write(f""" + return self.add_traces(new_trace)[0]""") + + buffer.write('\n') + return buffer.getvalue() + + +def append_figure_class(outdir, trace_node): + + if trace_node.node_path: + raise ValueError('Expected root trace node. Received node with path "%s"' % trace_node.dir_str) + + base_figures = [('basewidget', 'BaseFigureWidget', 'FigureWidget'), + ('basedatatypes', 'BaseFigure', 'Figure')] + + for base_package, base_classname, fig_classname in base_figures: + figure_source = build_figure_py(trace_node, base_package, base_classname, fig_classname) + formatted_source = format_source(figure_source) + + # Append to file + # -------------- + filepath = opath.join(outdir, '__init__.py') + + with open(filepath, 'a') as f: + f.write('\n\n') + f.write(formatted_source) + f.flush() + os.fsync(f.fileno()) diff --git a/codegen/utils.py b/codegen/utils.py new file mode 100644 index 00000000000..044817575a3 --- /dev/null +++ b/codegen/utils.py @@ -0,0 +1,525 @@ +import importlib +import inspect +import textwrap +from typing import List, Dict + +from io import StringIO +from yapf.yapflib.yapf_api import FormatCode + +from plotly.basevalidators import BaseValidator, CompoundValidator, CompoundArrayValidator +from plotly.graph_reference import OBJECT_NAME_TO_CLASS_NAME + + +def format_source(validator_source): + formatted_source, _ = FormatCode(validator_source, + style_config={'based_on_style': 'google', + 'DEDENT_CLOSING_BRACKETS': True, + 'COLUMN_LIMIT': 119}) + return formatted_source + + +custom_validator_datatypes = { + 'layout.image.source': 'plotly.basevalidators.ImageUriValidator', + 'frame.data': 'plotly.validators.DataValidator', + 'frame.layout': 'plotly.validators.LayoutValidator' +} + +class PlotlyNode: + + # Constructor + # ----------- + def __init__(self, plotly_schema, node_path=(), parent=None): + self.plotly_schema = plotly_schema + if isinstance(node_path, str): + node_path = (node_path,) + self.node_path = node_path + + # Compute children + if isinstance(self.node_data, dict): + self._children = [self.__class__(self.plotly_schema, + node_path=self.node_path + (c,), + parent=self) + for c in self.node_data if c and c[0] != '_'] + else: + self._children = [] + + # Parent + self._parent = parent + + def __repr__(self): + return self.dir_str + + # Abstract methods + # ---------------- + @property + def node_data(self) -> dict: + raise NotImplementedError() + + @property + def description(self) -> str: + raise NotImplementedError() + + @property + def base_datatype_class(self): + raise NotImplementedError + + # Names + # ----- + @property + def base_name(self): + raise NotImplementedError() + + @property + def plotly_name(self) -> str: + if len(self.node_path) == 0: + return self.base_name + else: + return self.node_path[-1] + + @property + def name_pascal_case(self) -> str: + if self.plotly_name in OBJECT_NAME_TO_CLASS_NAME: + return OBJECT_NAME_TO_CLASS_NAME[self.plotly_name] + else: + return self.plotly_name.title().replace('_', '') + + @property + def name_undercase(self) -> str: + if not self.plotly_name: + # Empty plotly_name + return self.plotly_name + + # Lowercase leading char + # ---------------------- + name1 = self.plotly_name[0].lower() + self.plotly_name[1:] + + # Replace capital chars by underscore-lower + # ----------------------------------------- + name2 = ''.join([('' if not c.isupper() else '_') + c.lower() for c in name1]) + + return name2 + + @property + def name_property(self) -> str: + return self.plotly_name + ('s' if self.is_array_element else '') + + @property + def name_validator(self) -> str: + return self.name_pascal_case + ('s' if self.is_array_element else '') + 'Validator' + + @property + def name_base_validator(self) -> str: + if self.dir_str in custom_validator_datatypes: + validator_base = f"{custom_validator_datatypes[self.dir_str]}" + else: + validator_base = f"plotly.basevalidators.{self.datatype_pascal_case}Validator" + + return validator_base + + def get_constructor_params_docstring(self, indent=12, extra_nodes=[]): + assert self.is_compound + + buffer = StringIO() + + subtype_nodes = self.child_datatypes + extra_nodes + for subtype_node in subtype_nodes: + raw_description = subtype_node.description + subtype_description = '\n'.join(textwrap.wrap(raw_description, + subsequent_indent=' ' * (indent + 4), + width=80 - (indent + 4))) + + buffer.write('\n' + ' ' * indent + subtype_node.name_property) + buffer.write('\n' + ' ' * (indent + 4) + subtype_description) + + return buffer.getvalue() + + @property + def validator_instance(self) -> BaseValidator: + + module_parts = self.name_base_validator.split('.') + module_path = '.'.join(module_parts[:-1]) + cls_name = module_parts[-1] + + validators_module = importlib.import_module(module_path) + + validator_class_list = [cls + for _, cls in inspect.getmembers(validators_module, inspect.isclass) + if cls.__name__ == cls_name] + if not validator_class_list: + raise ValueError(f"Unknown base validator '{self.name_base_validator}'") + + validator_class = validator_class_list[0] + + args = dict(plotly_name=self.name_property, parent_name=self.parent_dir_str) + + if validator_class == CompoundValidator: + data_class_str = f"" + extra_args = {'data_class': data_class_str, 'data_docs': self.get_constructor_params_docstring()} + elif validator_class == CompoundArrayValidator: + element_class_str = f"" + extra_args = {'element_class': element_class_str, 'element_docs': self.get_constructor_params_docstring()} + else: + extra_args = {n.name_undercase: n.node_data for n in self.simple_attrs} + + # Add extra properties + if self.datatype == 'color': + # Check for colorscale sibling + colorscale_node_list = [node for node in self.parent.child_datatypes + if node.datatype == 'colorscale'] + if colorscale_node_list: + colorscale_path = colorscale_node_list[0].dir_str + extra_args['colorscale_path'] = repr(colorscale_path) + + return validator_class(**args, **extra_args) + + @property + def name_class(self) -> str: + return self.name_pascal_case + + # Datatypes + # --------- + @property + def datatype(self) -> str: + if self.is_array_element: + return 'compound_array' + elif self.is_compound: + return 'compound' + elif self.is_simple: + return self.node_data.get('valType') + else: + return 'literal' + + @property + def datatype_pascal_case(self) -> str: + return self.datatype.title().replace('_', '') + + @property + def is_compound(self) -> bool: + return isinstance(self.node_data, dict) and not self.is_simple and self.plotly_name != 'impliedEdits' + + @property + def is_literal(self) -> bool: + return isinstance(self.node_data, str) + + @property + def is_simple(self) -> bool: + return isinstance(self.node_data, dict) and 'valType' in self.node_data + + @property + def is_array(self) -> bool: + return isinstance(self.node_data, dict) and \ + self.node_data.get('role', '') == 'object' and \ + 'items' in self.node_data + + @property + def is_array_element(self): + if self.parent and self.parent.parent: + return self.parent.parent.is_array + else: + return False + + @property + def is_datatype(self) -> bool: + return self.is_simple or self.is_compound + + # Node path + # --------- + def tidy_dir_path(self, p): + return p + + @property + def dir_path(self) -> List[str]: + res = [self.base_name] if self.base_name else [] + for i, p in enumerate(self.node_path): + if p == 'items' or \ + (i < len(self.node_path) - 1 and self.node_path[i+1] == 'items'): + # e.g. [parcoords, dimensions, items, dimension] -> [parcoords, dimension] + pass + else: + res.append(self.tidy_dir_path(p)) + return res + + # Node path strings + # ----------------- + @property + def dir_str(self) -> str: + return '.'.join(self.dir_path) + + @property + def parent_dir_str(self) -> str: + return '.'.join(self.dir_path[:-1]) + + @property + def pkg_str(self) -> str: + path_str = '' + for p in self.dir_path: + path_str += '.' + p + return path_str + + # Children + # -------- + @property + def children(self) -> List['PlotlyNode']: + return self._children + + @property + def simple_attrs(self) -> List['PlotlyNode']: + if not self.is_simple: + raise ValueError(f"Cannot get simple attributes of the simple object '{self.dir_str}'") + + return [n for n in self.children if n.plotly_name not in ['valType', 'description', 'role']] + + @property + def parent(self) -> 'PlotlyNode': + return self._parent + + @property + def child_datatypes(self) -> List['PlotlyNode']: + """ + Returns + ------- + children: list of TraceNode + """ + # if self.is_array: + # items_child = [c for c in self.children if c.plotly_name == 'items'][0] + # return items_child.children + # else: + nodes = [] + for n in self.children: + if n.is_array: + nodes.append(n.children[0].children[0]) + elif n.is_datatype: + nodes.append(n) + + return nodes + + @property + def child_compound_datatypes(self) -> List['PlotlyNode']: + return [n for n in self.child_datatypes if n.is_compound] + + @property + def child_simple_datatypes(self) -> List['PlotlyNode']: + return [n for n in self.child_datatypes if n.is_simple] + + @property + def child_literals(self) -> List['PlotlyNode']: + return [n for n in self.children if n.is_literal] + + # Static helpers + # -------------- + @staticmethod + def get_all_compound_datatype_nodes(plotly_schema, node_class) -> List['PlotlyNode']: + nodes = [] + nodes_to_process = [node_class(plotly_schema)] + + while nodes_to_process: + node = nodes_to_process.pop() + + if not node.is_array: + nodes.append(node) + + nodes_to_process.extend(node.child_compound_datatypes) + + return nodes + + @staticmethod + def get_all_trace_layout_nodes(plotly_schema) -> Dict[str, 'LayoutNode']: + trace_names = plotly_schema['traces'].keys() + + datatype_nodes = {} + nodes_to_process = [TraceLayoutNode(plotly_schema, trace_name) + for trace_name in trace_names] + + while nodes_to_process: + parent_node = nodes_to_process.pop() + for node in parent_node.child_simple_datatypes: + datatype_nodes[node.dir_str] = node + + return datatype_nodes + + +class TraceNode(PlotlyNode): + + # Constructor + # ----------- + def __init__(self, plotly_schema, node_path=(), parent=None): + super().__init__(plotly_schema, node_path, parent) + + @property + def base_datatype_class(self): + if len(self.node_path) == 0: + return 'BaseTraceType' + else: + return 'BaseTraceHierarchyType' + + @property + def base_name(self): + return 'trace' + + # Raw data + # -------- + @property + def node_data(self) -> dict: + if not self.node_path: + node_data = self.plotly_schema['traces'] + else: + node_data = self.plotly_schema['traces'][self.node_path[0]]['attributes'] + for prop_name in self.node_path[1:]: + node_data = node_data[prop_name] + + return node_data + + # Description + # ----------- + @property + def description(self) -> str: + if len(self.node_path) == 0: + desc = "" + elif len(self.node_path) == 1: + desc = self.plotly_schema['traces'][self.node_path[0]]['meta'].get('description', '') + else: + desc = self.node_data.get('description', '') + + if isinstance(desc, list): + desc = ''.join(desc) + + return desc + + +class LayoutNode(PlotlyNode): + + # Constructor + # ----------- + def __init__(self, plotly_schema, node_path=(), parent=None): + super().__init__(plotly_schema, node_path, parent) + + @property + def base_datatype_class(self): + if len(self.node_path) == 0: + return 'BaseLayoutType' + else: + return 'BaseLayoutHierarchyType' + + @property + def base_name(self): + return '' + + @property + def plotly_name(self) -> str: + if len(self.node_path) == 0: + return self.base_name + elif len(self.node_path) == 1: + return 'layout' # override 'layoutAttributes' + else: + return self.node_path[-1] + + def tidy_dir_path(self, p): + return 'layout' if p == 'layoutAttributes' else p + + # Description + # ----------- + @property + def description(self) -> str: + desc = self.node_data.get('description', '') + if isinstance(desc, list): + desc = ''.join(desc) + return desc + + # Raw data + # -------- + @property + def node_data(self) -> dict: + node_data = self.plotly_schema['layout'] + for prop_name in self.node_path: + node_data = node_data[prop_name] + + return node_data + + +class TraceLayoutNode(LayoutNode): + + # Constructor + # ----------- + def __init__(self, plotly_schema, trace_name=None, node_path=(), parent=None): + + # Handle trace name + assert parent is not None or trace_name is not None + if parent is not None: + trace_name = parent.trace_name + + self.trace_name = trace_name + super().__init__(plotly_schema, node_path, parent) + + @property + def base_name(self): + return 'layout' + + @property + def plotly_name(self) -> str: + if len(self.node_path) == 0: + return self.base_name + else: + return self.node_path[-1] + + # Raw data + # -------- + @property + def node_data(self) -> dict: + try: + node_data = (self.plotly_schema['traces'] + [self.trace_name]['layoutAttributes']) + + for prop_name in self.node_path: + node_data = node_data[prop_name] + + except KeyError: + node_data = [] + + return node_data + + +class FrameNode(PlotlyNode): + + # Constructor + # ----------- + def __init__(self, plotly_schema, node_path=(), parent=None): + super().__init__(plotly_schema, node_path, parent) + + @property + def base_datatype_class(self): + return 'BaseFrameHierarchyType' + + @property + def base_name(self): + return '' + + @property + def plotly_name(self) -> str: + if len(self.node_path) < 2: + return self.base_name + elif len(self.node_path) == 2: + return 'frame' # override 'frames_entry' + else: + return self.node_path[-1] + + def tidy_dir_path(self, p): + return 'frame' if p == 'frames_entry' else p + + # Description + # ----------- + @property + def description(self) -> str: + desc = self.node_data.get('description', '') + if isinstance(desc, list): + desc = ''.join(desc) + return desc + + # Raw data + # -------- + @property + def node_data(self) -> dict: + node_data = self.plotly_schema['frames'] + for prop_name in self.node_path: + node_data = node_data[prop_name] + + return node_data diff --git a/codegen/validators.py b/codegen/validators.py new file mode 100644 index 00000000000..996e33cca9e --- /dev/null +++ b/codegen/validators.py @@ -0,0 +1,169 @@ +import os +import os.path as opath +import shutil +from io import StringIO +from typing import Dict + +from codegen.utils import format_source, PlotlyNode, TraceNode + +def build_validators_py(parent_node: PlotlyNode, + extra_nodes: Dict[str, 'PlotlyNode'] = {}): + + extra_subtype_nodes = [node for node_name, node in + extra_nodes.items() if + parent_node.dir_str and node_name.startswith(parent_node.dir_str)] + + datatype_nodes = parent_node.child_datatypes + extra_subtype_nodes + + if not datatype_nodes: + return None + + buffer = StringIO() + + # Imports + # ------- + # Compute needed imports + import_strs = set() + for datatype_node in datatype_nodes: + module_str = '.'.join(datatype_node.name_base_validator.split('.')[:-1]) + import_strs.add(module_str) + + for import_str in import_strs: + buffer.write(f'import {import_str}\n') + + # Check for colorscale node + # ------------------------- + colorscale_node_list = [node for node in datatype_nodes if node.datatype == 'colorscale'] + if colorscale_node_list: + colorscale_path = colorscale_node_list[0].dir_str + else: + colorscale_path = None + + # Compound datatypes loop + # ----------------------- + for datatype_node in datatype_nodes: + + parent_dir_str = datatype_node.parent_dir_str if datatype_node.parent_dir_str else 'figure' + buffer.write(f""" + +class {datatype_node.name_validator}({datatype_node.name_base_validator}): + def __init__(self, plotly_name='{datatype_node.name_property}', parent_name='{parent_dir_str}'):""") + + # Add import + if datatype_node.is_compound: + buffer.write(f""" + from plotly.datatypes{parent_node.pkg_str} import {datatype_node.name_pascal_case}""") + + buffer.write(f""" + super().__init__(plotly_name=plotly_name, + parent_name=parent_name""") + + if datatype_node.is_array_element: + buffer.write(f""", + element_class={datatype_node.name_class}, + element_docs=\"\"\"{datatype_node.get_constructor_params_docstring()}\"\"\"""") + elif datatype_node.is_compound: + buffer.write(f""", + data_class={datatype_node.name_class}, + data_docs=\"\"\"{datatype_node.get_constructor_params_docstring()}\"\"\"""") + else: + assert datatype_node.is_simple + + # Exclude general properties + excluded_props = ['valType', 'description', 'role', 'dflt'] + if datatype_node.datatype == 'subplotid': + # Default is required for subplotid validator + excluded_props.remove('dflt') + + attr_nodes = [n for n in datatype_node.simple_attrs + if n.plotly_name not in excluded_props] + + attr_dict = {node.name_undercase: repr(node.node_data) for node in attr_nodes} + + # Add special properties + if datatype_node.datatype == 'color' and colorscale_path: + attr_dict['colorscale_path'] = repr(colorscale_path) + + for attr_name, attr_val in attr_dict.items(): + buffer.write(f""", + {attr_name}={attr_val}""") + + buffer.write(')') + + return buffer.getvalue() + + +def write_validator_py(outdir, + node: PlotlyNode, + extra_nodes: Dict[str, 'PlotlyNode'] = {}): + + # Generate source code + # -------------------- + validator_source = build_validators_py(node, extra_nodes) + if validator_source: + try: + formatted_source = format_source(validator_source) + except Exception as e: + print(validator_source) + raise e + + # Write file + # ---------- + filedir = opath.join(outdir, 'validators', *node.dir_path) + os.makedirs(filedir, exist_ok=True) + filepath = opath.join(filedir, '__init__.py') + + mode = 'at' if os.path.exists(filepath) else 'wt' + with open(filepath, mode) as f: + if mode == 'at': + f.write("\n\n") + f.write(formatted_source) + f.flush() + os.fsync(f.fileno()) + + +def build_traces_validator_py(base_node: TraceNode): + tracetype_nodes = base_node.child_compound_datatypes + buffer = StringIO() + + import_csv = ', '.join([tracetype_node.name_class for tracetype_node in tracetype_nodes]) + + buffer.write(f""" +class DataValidator(plotly.basevalidators.BaseDataValidator): + + def __init__(self, plotly_name='data', parent_name='figure'): + from plotly.datatypes.trace import ({import_csv}) + super().__init__(class_map={{ + """) + + for i, tracetype_node in enumerate(tracetype_nodes): + sfx = ',' if i < len(tracetype_nodes) else '' + + buffer.write(f""" + '{tracetype_node.name_property}': {tracetype_node.name_class}{sfx}""") + + buffer.write(""" + }, + plotly_name=plotly_name, + parent_name=parent_name)""") + + return buffer.getvalue() + + +def append_traces_validator_py(outdir, base_node: TraceNode): + + if base_node.node_path: + raise ValueError('Expected root trace node. Received node with path "%s"' % base_node.dir_str) + + source = build_traces_validator_py(base_node) + formatted_source = format_source(source) + + # Append to file + # -------------- + filepath = opath.join(outdir, '__init__.py') + + with open(filepath, 'a') as f: + f.write('\n\n') + f.write(formatted_source) + f.flush() + os.fsync(f.fileno()) diff --git a/contributing.md b/contributing.md index 7faae060837..554d04fdd5e 100644 --- a/contributing.md +++ b/contributing.md @@ -112,6 +112,11 @@ To install the optional dependencies: pip install -r optional-requirements.txt ``` +## ipywidget development install + $ jupyter nbextension enable --py widgetsnbextension + $ jupyter nbextension install --py --symlink --sys-prefix plotlywidget + $ jupyter nbextension enable --py --sys-prefix plotlywidget + ## Testing We take advantage of two tools to run tests: diff --git a/ipyplotly/.gitignore b/ipyplotly/.gitignore new file mode 100644 index 00000000000..d6e625da134 --- /dev/null +++ b/ipyplotly/.gitignore @@ -0,0 +1,27 @@ +*.egg-info/ +.ipynb_checkpoints/ +dist/ +build/ +*.py[cod] +js/node_modules/ + +# Compiled javascript +ipyplotly/static/ + +# OS X +.DS_Store + +# PyCharm project +.idea/ + +# Generated code +ipyplotly/validators +ipyplotly/datatypes + +# General scratch directories +**/scratch + +# Examples +/examples/overviews/exports/ +!/examples/overviews/exports/README.md + diff --git a/ipyplotly/LICENSE.txt b/ipyplotly/LICENSE.txt new file mode 100644 index 00000000000..953596a84d5 --- /dev/null +++ b/ipyplotly/LICENSE.txt @@ -0,0 +1,21 @@ +The MIT License (MIT) + +Copyright (c) 2017 Johns Hopkins Applied Physics Laboratory + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/ipyplotly/MANIFEST.in b/ipyplotly/MANIFEST.in new file mode 100644 index 00000000000..a2a4a36ebfc --- /dev/null +++ b/ipyplotly/MANIFEST.in @@ -0,0 +1 @@ +recursive-exclude codegen * diff --git a/ipyplotly/README.md b/ipyplotly/README.md new file mode 100644 index 00000000000..0f307cbb74c --- /dev/null +++ b/ipyplotly/README.md @@ -0,0 +1,51 @@ +ipyplotly +========= + +Experiments towards a Pythonic [Plotly](https://plot.ly/) API +and [ipywidget](http://ipywidgets.readthedocs.io/en/latest/index.html) for use in the Jupyter Notebook. + +Features +-------- + - Plots may be displayed in the notebook, and then updated in-place using property assignment syntax. + - The entire plotting API is now discoverable using tab completion and documented with descriptive docstrings. + - Property validation is performed in the Python library and informative error messages are raised on validation + failures. + - Arbitrary Python callbacks may be executed upon zoom, pan, click, hover, and data selection events. + - Multiple views of the same plot may be displayed across different notebook output cells. + - Static PNG and SVG images may be exported programmatically with no external dependencies or network connection + required. + - Plot transitions may be animated with custom duration and easing properties. + - Numpy arrays are transferred between the Python and JavaScript libraries using the binary serialization protocol + introduced in ipywidgets 7.0. + - Plots may be combined with built-in + [ipywidgets](http://ipywidgets.readthedocs.io/en/latest/examples/Widget%20List.html) + to create rich dashboard layouts in the notebook + + +Development Installation +------------------------ + +For a development installation (requires npm), + + $ git clone https://github.com/jmmease/ipyplotly.git + $ cd ipyplotly + $ pip install -e . + $ pip install yapf + $ python setup.py codegen + $ jupyter nbextension enable --py widgetsnbextension + $ jupyter nbextension install --py --symlink --sys-prefix ipyplotly + $ jupyter nbextension enable --py --sys-prefix ipyplotly + +Python Version Requirements +--------------------------- + - Usage requires Python >= 3.5 + - Code generation requires Python >= 3.6 + +Future +------ +This project was a successful experiment to test the feasibility of creating a +Plotly ipywidget library. This approach has been embraced by the official +[plotly.py](https://github.com/plotly/plotly.py) project and will be integrated into +a new major version of plotly.py in the not-too-distant future. + +See [plotly/plotly.py#942](https://github.com/plotly/plotly.py/pull/942) for current status. diff --git a/ipyplotly/RELEASE.md b/ipyplotly/RELEASE.md new file mode 100644 index 00000000000..977ea29ef11 --- /dev/null +++ b/ipyplotly/RELEASE.md @@ -0,0 +1,18 @@ +- To release a new version of ipyplotly on PyPI: + +Update _version.py (set release version, remove 'dev') +git add and git commit +python setup.py sdist upload +python setup.py bdist_wheel upload +git tag -a X.X.X -m 'comment' +Update _version.py (add 'dev' and increment minor) +git add and git commit +git push +git push --tags + +- To release a new version of ipyplotly on NPM: + +# nuke the `dist` and `node_modules` +git clean -fdx +npm install +npm publish diff --git a/ipyplotly/codegen/References.md b/ipyplotly/codegen/References.md new file mode 100644 index 00000000000..70bba4edad2 --- /dev/null +++ b/ipyplotly/codegen/References.md @@ -0,0 +1,3 @@ +Documentation of json schema + +https://api.plot.ly/v2/plot-schema?sha1 \ No newline at end of file diff --git a/ipyplotly/codegen/__init__.py b/ipyplotly/codegen/__init__.py new file mode 100644 index 00000000000..3260fb28305 --- /dev/null +++ b/ipyplotly/codegen/__init__.py @@ -0,0 +1,78 @@ +import json +import os.path as opath +import os +import shutil + +import time + +from codegen.datatypes import build_datatypes_py, write_datatypes_py, append_figure_class +from codegen.utils import TraceNode, PlotlyNode, LayoutNode, FrameNode +from codegen.validators import write_validator_py, append_traces_validator_py + + +def perform_codegen(): + outdir = 'ipyplotly/' + # outdir = 'codegen/output' + # Load plotly schema + # ------------------ + with open('codegen/resources/plot-schema.json', 'r') as f: + plotly_schema = json.load(f) + + # Compute property paths + # ---------------------- + base_traces_node = TraceNode(plotly_schema) + compound_trace_nodes = PlotlyNode.get_all_compound_datatype_nodes(plotly_schema, TraceNode) + compound_layout_nodes = PlotlyNode.get_all_compound_datatype_nodes(plotly_schema, LayoutNode) + compound_frame_nodes = PlotlyNode.get_all_compound_datatype_nodes(plotly_schema, FrameNode) + + extra_layout_nodes = PlotlyNode.get_all_trace_layout_nodes(plotly_schema) + + # Write out validators + # -------------------- + validators_pkgdir = opath.join(outdir, 'validators') + if opath.exists(validators_pkgdir): + shutil.rmtree(validators_pkgdir) + + # ### Layout ### + for node in compound_layout_nodes: + write_validator_py(outdir, node, extra_layout_nodes) + + # ### Trace ### + for node in compound_trace_nodes: + write_validator_py(outdir, node) + + # Write out datatypes + # ------------------- + datatypes_pkgdir = opath.join(outdir, 'datatypes') + if opath.exists(datatypes_pkgdir): + shutil.rmtree(datatypes_pkgdir) + + # ### Layout ### + for node in compound_layout_nodes: + write_datatypes_py(outdir, node, extra_layout_nodes) + + # ### Trace ### + for node in compound_trace_nodes: + write_datatypes_py(outdir, node) + + # Append traces validator class + # ----------------------------- + append_traces_validator_py(validators_pkgdir, base_traces_node) + + # Add Frames + # ---------- + # ### Validator ### + for node in compound_frame_nodes: + write_validator_py(outdir, node) + + # ### Datatypes ### + for node in compound_frame_nodes: + write_datatypes_py(outdir, node) + + # Append figure class to datatypes + # -------------------------------- + append_figure_class(datatypes_pkgdir, base_traces_node) + + +if __name__ == '__main__': + perform_codegen() diff --git a/ipyplotly/codegen/datatypes.py b/ipyplotly/codegen/datatypes.py new file mode 100644 index 00000000000..f000828ab46 --- /dev/null +++ b/ipyplotly/codegen/datatypes.py @@ -0,0 +1,360 @@ +from io import StringIO +import os +import os.path as opath +import textwrap +import importlib +from typing import List, Dict + +from codegen.utils import TraceNode, format_source, PlotlyNode + + +def get_typing_type(plotly_type, array_ok=False): + if plotly_type in ('data_array', 'info_array', 'colorlist'): + pytype = 'List' + elif plotly_type in ('string', 'color', 'colorscale', 'subplotid'): + pytype = 'str' + elif plotly_type in ('enumerated', 'flaglist', 'any'): + pytype = 'Any' + elif plotly_type in ('number', 'angle'): + pytype = 'Number' + elif plotly_type == 'integer': + pytype = 'int' + elif plotly_type == 'boolean': + pytype = 'bool' + else: + raise ValueError('Unknown plotly type: %s' % plotly_type) + + if array_ok: + return f'Union[{pytype}, List[{pytype}]]' + else: + return pytype + + +def build_datatypes_py(parent_node: PlotlyNode, + extra_nodes: Dict[str, 'PlotlyNode'] = {}): + + compound_nodes = parent_node.child_compound_datatypes + if not compound_nodes: + return None + + buffer = StringIO() + + # Imports + # ------- + buffer.write('from typing import *\n') + buffer.write('from numbers import Number\n') + buffer.write(f'from ipyplotly.basedatatypes import {parent_node.base_datatype_class}\n') + + # ### Validators ### + validators_csv = ', '.join([f'{n.plotly_name} as v_{n.plotly_name}' for n in compound_nodes]) + buffer.write(f'from ipyplotly.validators{parent_node.pkg_str} import ({validators_csv})\n') + + # ### Datatypes ### + datatypes_csv = ', '.join([f'{n.plotly_name} as d_{n.plotly_name}' for n in compound_nodes if n.child_compound_datatypes]) + if datatypes_csv: + buffer.write(f'from ipyplotly.datatypes{parent_node.pkg_str} import ({datatypes_csv})\n') + + # Compound datatypes loop + # ----------------------- + for compound_node in compound_nodes: + + # grab literals + literal_nodes = [n for n in compound_node.child_literals if n.plotly_name in ['type']] + + # ### Class definition ### + buffer.write(f""" + +class {compound_node.name_class}({parent_node.base_datatype_class}):\n""") + + # ### Property definitions ### + child_datatype_nodes = compound_node.child_datatypes + extra_subtype_nodes = [node for node_name, node in + extra_nodes.items() if + node_name.startswith(compound_node.dir_str)] + + subtype_nodes = child_datatype_nodes + extra_subtype_nodes + for subtype_node in subtype_nodes: + if subtype_node.is_array_element: + prop_type = f'Tuple[d_{compound_node.plotly_name}.{subtype_node.name_class}]' + elif subtype_node.is_compound: + prop_type = f'd_{compound_node.plotly_name}.{subtype_node.name_class}' + else: + prop_type = get_typing_type(subtype_node.datatype) + + + # #### Get property description #### + raw_description = subtype_node.description + property_description = '\n'.join(textwrap.wrap(raw_description, + subsequent_indent=' ' * 8, + width=80 - 8)) + + # #### Get validator description #### + validator = subtype_node.validator_instance + validator_description = reindent_validator_description(validator, 4) + + # #### Combine to form property docstring #### + if property_description.strip(): + property_docstring = f"""{property_description} + + {validator_description}""" + else: + property_docstring = validator_description + + # #### Write property ### + buffer.write(f"""\ + + # {subtype_node.name_property} + # {'-' * len(subtype_node.name_property)} + @property + def {subtype_node.name_property}(self) -> {prop_type}: + \"\"\" + {property_docstring} + \"\"\" + return self['{subtype_node.name_property}']""") + + # #### Set property ### + buffer.write(f""" + + @{subtype_node.name_property}.setter + def {subtype_node.name_property}(self, val): + self['{subtype_node.name_property}'] = val\n""") + + # ### Literals ### + for literal_node in literal_nodes: + buffer.write(f"""\ + + # {literal_node.name_property} + # {'-' * len(literal_node.name_property)} + @property + def {literal_node.name_property}(self) -> {prop_type}: + return self._props['{literal_node.name_property}']\n""") + + # ### Self properties description ### + buffer.write(f""" + + # property parent name + # -------------------- + @property + def _parent_path(self) -> str: + return '{compound_node.parent_dir_str}' + + # Self properties description + # --------------------------- + @property + def _prop_descriptions(self) -> str: + return \"\"\"\\""") + + buffer.write(compound_node.get_constructor_params_docstring( + indent=8, + extra_nodes=extra_subtype_nodes)) + + buffer.write(f""" + \"\"\"""") + + # ### Constructor ### + buffer.write(f""" + def __init__(self""") + + add_constructor_params(buffer, subtype_nodes) + add_docstring(buffer, compound_node, extra_subtype_nodes) + + buffer.write(f""" + super().__init__('{compound_node.name_property}', **kwargs) + + # Initialize validators + # ---------------------""") + for subtype_node in subtype_nodes: + + buffer.write(f""" + self._validators['{subtype_node.name_property}'] = v_{compound_node.plotly_name}.{subtype_node.name_validator}()""") + + buffer.write(f""" + + # Populate data dict with properties + # ----------------------------------""") + for subtype_node in subtype_nodes: + buffer.write(f""" + self.{subtype_node.name_property} = {subtype_node.name_property}""") + + # ### Literals ### + literal_nodes = [n for n in compound_node.child_literals if n.plotly_name in ['type']] + if literal_nodes: + buffer.write(f""" + + # Read-only literals + # ------------------""") + for literal_node in literal_nodes: + buffer.write(f""" + self._props['{literal_node.name_property}'] = '{literal_node.node_data}'""") + + return buffer.getvalue() + + +def reindent_validator_description(validator, extra_indent): + # Remove leading indent and add extra spaces to subsequent indent + return ('\n' + ' ' * extra_indent).join(validator.description().strip().split('\n')) + + +def add_constructor_params(buffer, subtype_nodes, colon=True): + for i, subtype_node in enumerate(subtype_nodes): + dflt = None + buffer.write(f""", + {subtype_node.name_property}={repr(dflt)}""") + + buffer.write(""", + **kwargs""") + buffer.write(f""" + ){':' if colon else ''}""") + + +def add_docstring(buffer, compound_node, extra_subtype_nodes=[]): + # ### Docstring ### + buffer.write(f""" + \"\"\" + Construct a new {compound_node.name_pascal_case} object + + Parameters + ----------""") + buffer.write(compound_node.get_constructor_params_docstring( + indent=8, + extra_nodes=extra_subtype_nodes )) + + # #### close docstring #### + buffer.write(f""" + + Returns + ------- + {compound_node.name_pascal_case} + \"\"\"""") + + +def write_datatypes_py(outdir, node: PlotlyNode, + extra_nodes: Dict[str, 'PlotlyNode']={}): + + # Generate source code + # -------------------- + datatype_source = build_datatypes_py(node, extra_nodes) + if datatype_source: + try: + formatted_source = format_source(datatype_source) + except Exception as e: + print(datatype_source) + raise e + + # Write file + # ---------- + filedir = opath.join(outdir, 'datatypes', *node.dir_path) + os.makedirs(filedir, exist_ok=True) + filepath = opath.join(filedir, '__init__.py') + + mode = 'at' if os.path.exists(filepath) else 'wt' + with open(filepath, mode) as f: + if mode == 'at': + f.write("\n\n") + f.write(formatted_source) + f.flush() + os.fsync(f.fileno()) + + +def build_figure_py(trace_node, base_package, base_classname, fig_classname): + buffer = StringIO() + trace_nodes = trace_node.child_compound_datatypes + + # Imports + # ------- + buffer.write(f'from ipyplotly.{base_package} import {base_classname}\n') + + trace_types_csv = ', '.join([n.name_pascal_case for n in trace_nodes]) + buffer.write(f'from ipyplotly.datatypes.trace import ({trace_types_csv})\n') + + buffer.write(f""" + +class {fig_classname}({base_classname}):\n""") + + # Reload validators and datatypes modules since we're appending + # Classes to them as we go + validators_module = importlib.import_module('ipyplotly.validators') + importlib.reload(validators_module) + datatypes_module = importlib.import_module('ipyplotly.datatypes') + importlib.reload(datatypes_module) + + # Build constructor description strings + data_validator = validators_module.DataValidator() + data_description = reindent_validator_description(data_validator, 8) + + layout_validator = validators_module.LayoutValidator() + layout_description = reindent_validator_description(layout_validator, 8) + + frames_validator = validators_module.FramesValidator() + frames_description = reindent_validator_description(frames_validator, 8) + + buffer.write(f""" + def __init__(self, data=None, layout=None, frames=None): + \"\"\" + Create a new {fig_classname} instance + + Parameters + ---------- + data + {data_description} + layout + {layout_description} + frames + {frames_description} + \"\"\" + super().__init__(data, layout, frames) + """) + + # add_trace methods + for trace_node in trace_nodes: + + # Function signature + # ------------------ + buffer.write(f""" + def add_{trace_node.plotly_name}(self""") + + add_constructor_params(buffer, trace_node.child_datatypes) + add_docstring(buffer, trace_node) + + # Function body + # ------------- + buffer.write(f""" + new_trace = {trace_node.name_pascal_case}( + """) + + for i, subtype_node in enumerate(trace_node.child_datatypes): + is_last = i == len(trace_node.child_datatypes) - 1 + buffer.write(f""" + {subtype_node.name_property}={subtype_node.name_property}{'' if is_last else ','}""") + + buffer.write(f""", + **kwargs)""") + + buffer.write(f""" + return self.add_traces(new_trace)[0]""") + + buffer.write('\n') + return buffer.getvalue() + + +def append_figure_class(outdir, trace_node): + + if trace_node.node_path: + raise ValueError('Expected root trace node. Received node with path "%s"' % trace_node.dir_str) + + base_figures = [('basewidget', 'BaseFigureWidget', 'FigureWidget'), + ('basedatatypes', 'BaseFigure', 'Figure')] + + for base_package, base_classname, fig_classname in base_figures: + figure_source = build_figure_py(trace_node, base_package, base_classname, fig_classname) + formatted_source = format_source(figure_source) + + # Append to file + # -------------- + filepath = opath.join(outdir, '__init__.py') + + with open(filepath, 'a') as f: + f.write('\n\n') + f.write(formatted_source) + f.flush() + os.fsync(f.fileno()) diff --git a/ipyplotly/codegen/download_plotly_schema.py b/ipyplotly/codegen/download_plotly_schema.py new file mode 100644 index 00000000000..66db3b2ddcb --- /dev/null +++ b/ipyplotly/codegen/download_plotly_schema.py @@ -0,0 +1,7 @@ +import urllib.request +import json + +if __name__ == '__main__': + with urllib.request.urlopen('https://api.plot.ly/v2/plot-schema?sha1') as response: + with open('resources/plotly-schema-v2.json', 'w') as f: + f.write(json.dumps(json.load(response), indent=4)) diff --git a/ipyplotly/codegen/resources/plot-schema.json b/ipyplotly/codegen/resources/plot-schema.json new file mode 100644 index 00000000000..494832acb4b --- /dev/null +++ b/ipyplotly/codegen/resources/plot-schema.json @@ -0,0 +1,39615 @@ +{ + "defs": { + "valObjects": { + "data_array": { + "description": "An {array} of data. The value MUST be an {array}, or we ignore it.", + "requiredOpts": [], + "otherOpts": [ + "dflt" + ] + }, + "enumerated": { + "description": "Enumerated value type. The available values are listed in `values`.", + "requiredOpts": [ + "values" + ], + "otherOpts": [ + "dflt", + "coerceNumber", + "arrayOk" + ] + }, + "boolean": { + "description": "A boolean (true/false) value.", + "requiredOpts": [], + "otherOpts": [ + "dflt" + ] + }, + "number": { + "description": "A number or a numeric value (e.g. a number inside a string). When applicable, values greater (less) than `max` (`min`) are coerced to the `dflt`.", + "requiredOpts": [], + "otherOpts": [ + "dflt", + "min", + "max", + "arrayOk" + ] + }, + "integer": { + "description": "An integer or an integer inside a string. When applicable, values greater (less) than `max` (`min`) are coerced to the `dflt`.", + "requiredOpts": [], + "otherOpts": [ + "dflt", + "min", + "max", + "arrayOk" + ] + }, + "string": { + "description": "A string value. Numbers are converted to strings except for attributes with `strict` set to true.", + "requiredOpts": [], + "otherOpts": [ + "dflt", + "noBlank", + "strict", + "arrayOk", + "values" + ] + }, + "color": { + "description": "A string describing color. Supported formats: - hex (e.g. '#d3d3d3') - rgb (e.g. 'rgb(255, 0, 0)') - rgba (e.g. 'rgb(255, 0, 0, 0.5)') - hsl (e.g. 'hsl(0, 100%, 50%)') - hsv (e.g. 'hsv(0, 100%, 100%)') - named colors (full list: http://www.w3.org/TR/css3-color/#svg-color)", + "requiredOpts": [], + "otherOpts": [ + "dflt", + "arrayOk" + ] + }, + "colorlist": { + "description": "A list of colors. Must be an {array} containing valid colors.", + "requiredOpts": [], + "otherOpts": [ + "dflt" + ] + }, + "colorscale": { + "description": "A Plotly colorscale either picked by a name: (any of Greys, YlGnBu, Greens, YlOrRd, Bluered, RdBu, Reds, Blues, Picnic, Rainbow, Portland, Jet, Hot, Blackbody, Earth, Electric, Viridis ) customized as an {array} of 2-element {arrays} where the first element is the normalized color level value (starting at *0* and ending at *1*), and the second item is a valid color string.", + "requiredOpts": [], + "otherOpts": [ + "dflt" + ] + }, + "angle": { + "description": "A number (in degree) between -180 and 180.", + "requiredOpts": [], + "otherOpts": [ + "dflt" + ] + }, + "subplotid": { + "description": "An id string of a subplot type (given by dflt), optionally followed by an integer >1. e.g. if dflt='geo', we can have 'geo', 'geo2', 'geo3', ...", + "requiredOpts": [ + "dflt" + ], + "otherOpts": [] + }, + "flaglist": { + "description": "A string representing a combination of flags (order does not matter here). Combine any of the available `flags` with *+*. (e.g. ('lines+markers')). Values in `extras` cannot be combined.", + "requiredOpts": [ + "flags" + ], + "otherOpts": [ + "dflt", + "extras", + "arrayOk" + ] + }, + "any": { + "description": "Any type.", + "requiredOpts": [], + "otherOpts": [ + "dflt", + "values", + "arrayOk" + ] + }, + "info_array": { + "description": "An {array} of plot information.", + "requiredOpts": [ + "items" + ], + "otherOpts": [ + "dflt", + "freeLength" + ] + } + }, + "metaKeys": [ + "_isSubplotObj", + "_isLinkedToArray", + "_arrayAttrRegexps", + "_deprecated", + "description", + "role", + "editType", + "impliedEdits" + ], + "editType": { + "traces": { + "valType": "flaglist", + "extras": [ + "none" + ], + "flags": [ + "calc", + "calcIfAutorange", + "clearAxisTypes", + "plot", + "style", + "colorbars" + ], + "description": "trace attributes should include an `editType` string matching this flaglist. *calc* is the most extensive: a full `Plotly.plot` starting by clearing `gd.calcdata` to force it to be regenerated *calcIfAutorange* does a full `Plotly.plot`, but only clears and redoes `gd.calcdata` if there is at least one autoranged axis. *clearAxisTypes* resets the types of the axes this trace is on, because new data could cause the automatic axis type detection to change. Log type will not be cleared, as that is never automatically chosen so must have been user-specified. *plot* calls `Plotly.plot` but without first clearing `gd.calcdata`. *style* only calls `module.style` for all trace modules and redraws the legend. *colorbars* only redraws colorbars." + }, + "layout": { + "valType": "flaglist", + "extras": [ + "none" + ], + "flags": [ + "calc", + "calcIfAutorange", + "plot", + "legend", + "ticks", + "layoutstyle", + "modebar", + "camera", + "arraydraw" + ], + "description": "layout attributes should include an `editType` string matching this flaglist. *calc* is the most extensive: a full `Plotly.plot` starting by clearing `gd.calcdata` to force it to be regenerated *calcIfAutorange* does a full `Plotly.plot`, but only clears and redoes `gd.calcdata` if there is at least one autoranged axis. *plot* calls `Plotly.plot` but without first clearing `gd.calcdata`. *legend* only redraws the legend. *ticks* only redraws axis ticks, labels, and gridlines. *layoutstyle* reapplies global and SVG cartesian axis styles. *modebar* just updates the modebar. *camera* just updates the camera settings for gl3d scenes. *arraydraw* allows component arrays to invoke the redraw routines just for the component(s) that changed." + } + }, + "impliedEdits": { + "description": "Sometimes when an attribute is changed, other attributes must be altered as well in order to achieve the intended result. For example, when `range` is specified, it is important to set `autorange` to `false` or the new `range` value would be lost in the redraw. `impliedEdits` is the mechanism to do this: `impliedEdits: {autorange: false}`. Each key is a relative paths to the attribute string to change, using *^* to ascend into the parent container, for example `range[0]` has `impliedEdits: {*^autorange*: false}`. A value of `undefined` means that the attribute will not be changed, but its previous value should be recorded in case we want to reverse this change later. For example, `autorange` has `impliedEdits: {*range[0]*: undefined, *range[1]*:undefined} because the range will likely be changed by redraw." + } + }, + "traces": { + "scatter": { + "meta": { + "description": "The scatter trace type encompasses line charts, scatter charts, text charts, and bubble charts. The data visualized as scatter point or lines is set in `x` and `y`. Text (appearing either on the chart or on hover only) is via `text`. Bubble charts are achieved by setting `marker.size` and/or `marker.color` to numerical arrays." + }, + "attributes": { + "type": "scatter", + "visible": { + "valType": "enumerated", + "values": [ + true, + false, + "legendonly" + ], + "role": "info", + "dflt": true, + "editType": "calc", + "description": "Determines whether or not this trace is visible. If *legendonly*, the trace is not drawn, but can appear as a legend item (provided that the legend itself is visible)." + }, + "showlegend": { + "valType": "boolean", + "role": "info", + "dflt": true, + "editType": "style", + "description": "Determines whether or not an item corresponding to this trace is shown in the legend." + }, + "legendgroup": { + "valType": "string", + "role": "info", + "dflt": "", + "editType": "style", + "description": "Sets the legend group for this trace. Traces part of the same legend group hide/show at the same time when toggling legend items." + }, + "opacity": { + "valType": "number", + "role": "style", + "min": 0, + "max": 1, + "dflt": 1, + "editType": "style", + "description": "Sets the opacity of the trace." + }, + "name": { + "valType": "string", + "role": "info", + "editType": "style", + "description": "Sets the trace name. The trace name appear as the legend item and on hover." + }, + "uid": { + "valType": "string", + "role": "info", + "dflt": "", + "editType": "calc" + }, + "ids": { + "valType": "data_array", + "editType": "calc", + "description": "Assigns id labels to each datum. These ids for object constancy of data points during animation.", + "role": "data" + }, + "customdata": { + "valType": "data_array", + "editType": "calc", + "description": "Assigns extra data each datum. This may be useful when listening to hover, click and selection events. Note that, *scatter* traces also appends customdata items in the markers DOM elements", + "role": "data" + }, + "selectedpoints": { + "valType": "any", + "role": "info", + "editType": "calc", + "description": "Array containing integer indices of selected points. Has an effect only for traces that support selections. Note that an empty array means an empty selection where the `unselected` are turned on for all points, whereas, any other non-array values means no selection all where the `selected` and `unselected` styles have no effect." + }, + "hoverinfo": { + "valType": "flaglist", + "role": "info", + "flags": [ + "x", + "y", + "z", + "text", + "name" + ], + "extras": [ + "all", + "none", + "skip" + ], + "arrayOk": true, + "dflt": "all", + "editType": "none", + "description": "Determines which trace information appear on hover. If `none` or `skip` are set, no information is displayed upon hovering. But, if `none` is set, click and hover events are still fired." + }, + "hoverlabel": { + "bgcolor": { + "valType": "color", + "role": "style", + "arrayOk": true, + "editType": "none", + "description": "Sets the background color of the hover labels for this trace" + }, + "bordercolor": { + "valType": "color", + "role": "style", + "arrayOk": true, + "editType": "none", + "description": "Sets the border color of the hover labels for this trace." + }, + "font": { + "family": { + "valType": "string", + "role": "style", + "noBlank": true, + "strict": true, + "editType": "none", + "description": "HTML font family - the typeface that will be applied by the web browser. The web browser will only be able to apply a font if it is available on the system which it operates. Provide multiple font families, separated by commas, to indicate the preference in which to apply fonts if they aren't available on the system. The plotly service (at https://plot.ly or on-premise) generates images on a server, where only a select number of fonts are installed and supported. These include *Arial*, *Balto*, *Courier New*, *Droid Sans*,, *Droid Serif*, *Droid Sans Mono*, *Gravitas One*, *Old Standard TT*, *Open Sans*, *Overpass*, *PT Sans Narrow*, *Raleway*, *Times New Roman*.", + "arrayOk": true + }, + "size": { + "valType": "number", + "role": "style", + "min": 1, + "editType": "none", + "arrayOk": true + }, + "color": { + "valType": "color", + "role": "style", + "editType": "none", + "arrayOk": true + }, + "editType": "none", + "description": "Sets the font used in hover labels.", + "role": "object", + "familysrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for family .", + "editType": "none" + }, + "sizesrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for size .", + "editType": "none" + }, + "colorsrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for color .", + "editType": "none" + } + }, + "namelength": { + "valType": "integer", + "min": -1, + "arrayOk": true, + "role": "style", + "editType": "none", + "description": "Sets the length (in number of characters) of the trace name in the hover labels for this trace. -1 shows the whole name regardless of length. 0-3 shows the first 0-3 characters, and an integer >3 will show the whole name if it is less than that many characters, but if it is longer, will truncate to `namelength - 3` characters and add an ellipsis." + }, + "editType": "calc", + "role": "object", + "bgcolorsrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for bgcolor .", + "editType": "none" + }, + "bordercolorsrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for bordercolor .", + "editType": "none" + }, + "namelengthsrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for namelength .", + "editType": "none" + } + }, + "stream": { + "token": { + "valType": "string", + "noBlank": true, + "strict": true, + "role": "info", + "editType": "calc", + "description": "The stream id number links a data trace on a plot with a stream. See https://plot.ly/settings for more details." + }, + "maxpoints": { + "valType": "number", + "min": 0, + "max": 10000, + "dflt": 500, + "role": "info", + "editType": "calc", + "description": "Sets the maximum number of points to keep on the plots from an incoming stream. If `maxpoints` is set to *50*, only the newest 50 points will be displayed on the plot." + }, + "editType": "calc", + "role": "object" + }, + "x": { + "valType": "data_array", + "editType": "calc+clearAxisTypes", + "description": "Sets the x coordinates.", + "role": "data" + }, + "x0": { + "valType": "any", + "dflt": 0, + "role": "info", + "editType": "calc+clearAxisTypes", + "description": "Alternate to `x`. Builds a linear space of x coordinates. Use with `dx` where `x0` is the starting coordinate and `dx` the step." + }, + "dx": { + "valType": "number", + "dflt": 1, + "role": "info", + "editType": "calc", + "description": "Sets the x coordinate step. See `x0` for more info." + }, + "y": { + "valType": "data_array", + "editType": "calc+clearAxisTypes", + "description": "Sets the y coordinates.", + "role": "data" + }, + "y0": { + "valType": "any", + "dflt": 0, + "role": "info", + "editType": "calc+clearAxisTypes", + "description": "Alternate to `y`. Builds a linear space of y coordinates. Use with `dy` where `y0` is the starting coordinate and `dy` the step." + }, + "dy": { + "valType": "number", + "dflt": 1, + "role": "info", + "editType": "calc", + "description": "Sets the y coordinate step. See `y0` for more info." + }, + "text": { + "valType": "string", + "role": "info", + "dflt": "", + "arrayOk": true, + "editType": "calc", + "description": "Sets text elements associated with each (x,y) pair. If a single string, the same string appears over all the data points. If an array of string, the items are mapped in order to the this trace's (x,y) coordinates. If trace `hoverinfo` contains a *text* flag and *hovertext* is not set, these elements will be seen in the hover labels." + }, + "hovertext": { + "valType": "string", + "role": "info", + "dflt": "", + "arrayOk": true, + "editType": "style", + "description": "Sets hover text elements associated with each (x,y) pair. If a single string, the same string appears over all the data points. If an array of string, the items are mapped in order to the this trace's (x,y) coordinates. To be seen, trace `hoverinfo` must contain a *text* flag." + }, + "mode": { + "valType": "flaglist", + "flags": [ + "lines", + "markers", + "text" + ], + "extras": [ + "none" + ], + "role": "info", + "editType": "calc", + "description": "Determines the drawing mode for this scatter trace. If the provided `mode` includes *text* then the `text` elements appear at the coordinates. Otherwise, the `text` elements appear on hover. If there are less than 20 points, then the default is *lines+markers*. Otherwise, *lines*." + }, + "hoveron": { + "valType": "flaglist", + "flags": [ + "points", + "fills" + ], + "role": "info", + "editType": "style", + "description": "Do the hover effects highlight individual points (markers or line points) or do they highlight filled regions? If the fill is *toself* or *tonext* and there are no markers or text, then the default is *fills*, otherwise it is *points*." + }, + "line": { + "color": { + "valType": "color", + "role": "style", + "editType": "style", + "description": "Sets the line color." + }, + "width": { + "valType": "number", + "min": 0, + "dflt": 2, + "role": "style", + "editType": "style", + "description": "Sets the line width (in px)." + }, + "shape": { + "valType": "enumerated", + "values": [ + "linear", + "spline", + "hv", + "vh", + "hvh", + "vhv" + ], + "dflt": "linear", + "role": "style", + "editType": "plot", + "description": "Determines the line shape. With *spline* the lines are drawn using spline interpolation. The other available values correspond to step-wise line shapes." + }, + "smoothing": { + "valType": "number", + "min": 0, + "max": 1.3, + "dflt": 1, + "role": "style", + "editType": "plot", + "description": "Has an effect only if `shape` is set to *spline* Sets the amount of smoothing. *0* corresponds to no smoothing (equivalent to a *linear* shape)." + }, + "dash": { + "valType": "string", + "values": [ + "solid", + "dot", + "dash", + "longdash", + "dashdot", + "longdashdot" + ], + "dflt": "solid", + "role": "style", + "editType": "style", + "description": "Sets the dash style of lines. Set to a dash type string (*solid*, *dot*, *dash*, *longdash*, *dashdot*, or *longdashdot*) or a dash length list in px (eg *5px,10px,2px,2px*)." + }, + "simplify": { + "valType": "boolean", + "dflt": true, + "role": "info", + "editType": "plot", + "description": "Simplifies lines by removing nearly-collinear points. When transitioning lines, it may be desirable to disable this so that the number of points along the resulting SVG path is unaffected." + }, + "editType": "plot", + "role": "object" + }, + "connectgaps": { + "valType": "boolean", + "dflt": false, + "role": "info", + "editType": "calc", + "description": "Determines whether or not gaps (i.e. {nan} or missing values) in the provided data arrays are connected." + }, + "cliponaxis": { + "valType": "boolean", + "dflt": true, + "role": "info", + "editType": "plot", + "description": "Determines whether or not markers and text nodes are clipped about the subplot axes. To show markers and text nodes above axis lines and tick labels, make sure to set `xaxis.layer` and `yaxis.layer` to *below traces*." + }, + "fill": { + "valType": "enumerated", + "values": [ + "none", + "tozeroy", + "tozerox", + "tonexty", + "tonextx", + "toself", + "tonext" + ], + "dflt": "none", + "role": "style", + "editType": "calc", + "description": "Sets the area to fill with a solid color. Use with `fillcolor` if not *none*. *tozerox* and *tozeroy* fill to x=0 and y=0 respectively. *tonextx* and *tonexty* fill between the endpoints of this trace and the endpoints of the trace before it, connecting those endpoints with straight lines (to make a stacked area graph); if there is no trace before it, they behave like *tozerox* and *tozeroy*. *toself* connects the endpoints of the trace (or each segment of the trace if it has gaps) into a closed shape. *tonext* fills the space between two traces if one completely encloses the other (eg consecutive contour lines), and behaves like *toself* if there is no trace before it. *tonext* should not be used if one trace does not enclose the other." + }, + "fillcolor": { + "valType": "color", + "role": "style", + "editType": "style", + "description": "Sets the fill color. Defaults to a half-transparent variant of the line color, marker color, or marker line color, whichever is available." + }, + "marker": { + "symbol": { + "valType": "enumerated", + "values": [ + 0, + "circle", + 100, + "circle-open", + 200, + "circle-dot", + 300, + "circle-open-dot", + 1, + "square", + 101, + "square-open", + 201, + "square-dot", + 301, + "square-open-dot", + 2, + "diamond", + 102, + "diamond-open", + 202, + "diamond-dot", + 302, + "diamond-open-dot", + 3, + "cross", + 103, + "cross-open", + 203, + "cross-dot", + 303, + "cross-open-dot", + 4, + "x", + 104, + "x-open", + 204, + "x-dot", + 304, + "x-open-dot", + 5, + "triangle-up", + 105, + "triangle-up-open", + 205, + "triangle-up-dot", + 305, + "triangle-up-open-dot", + 6, + "triangle-down", + 106, + "triangle-down-open", + 206, + "triangle-down-dot", + 306, + "triangle-down-open-dot", + 7, + "triangle-left", + 107, + "triangle-left-open", + 207, + "triangle-left-dot", + 307, + "triangle-left-open-dot", + 8, + "triangle-right", + 108, + "triangle-right-open", + 208, + "triangle-right-dot", + 308, + "triangle-right-open-dot", + 9, + "triangle-ne", + 109, + "triangle-ne-open", + 209, + "triangle-ne-dot", + 309, + "triangle-ne-open-dot", + 10, + "triangle-se", + 110, + "triangle-se-open", + 210, + "triangle-se-dot", + 310, + "triangle-se-open-dot", + 11, + "triangle-sw", + 111, + "triangle-sw-open", + 211, + "triangle-sw-dot", + 311, + "triangle-sw-open-dot", + 12, + "triangle-nw", + 112, + "triangle-nw-open", + 212, + "triangle-nw-dot", + 312, + "triangle-nw-open-dot", + 13, + "pentagon", + 113, + "pentagon-open", + 213, + "pentagon-dot", + 313, + "pentagon-open-dot", + 14, + "hexagon", + 114, + "hexagon-open", + 214, + "hexagon-dot", + 314, + "hexagon-open-dot", + 15, + "hexagon2", + 115, + "hexagon2-open", + 215, + "hexagon2-dot", + 315, + "hexagon2-open-dot", + 16, + "octagon", + 116, + "octagon-open", + 216, + "octagon-dot", + 316, + "octagon-open-dot", + 17, + "star", + 117, + "star-open", + 217, + "star-dot", + 317, + "star-open-dot", + 18, + "hexagram", + 118, + "hexagram-open", + 218, + "hexagram-dot", + 318, + "hexagram-open-dot", + 19, + "star-triangle-up", + 119, + "star-triangle-up-open", + 219, + "star-triangle-up-dot", + 319, + "star-triangle-up-open-dot", + 20, + "star-triangle-down", + 120, + "star-triangle-down-open", + 220, + "star-triangle-down-dot", + 320, + "star-triangle-down-open-dot", + 21, + "star-square", + 121, + "star-square-open", + 221, + "star-square-dot", + 321, + "star-square-open-dot", + 22, + "star-diamond", + 122, + "star-diamond-open", + 222, + "star-diamond-dot", + 322, + "star-diamond-open-dot", + 23, + "diamond-tall", + 123, + "diamond-tall-open", + 223, + "diamond-tall-dot", + 323, + "diamond-tall-open-dot", + 24, + "diamond-wide", + 124, + "diamond-wide-open", + 224, + "diamond-wide-dot", + 324, + "diamond-wide-open-dot", + 25, + "hourglass", + 125, + "hourglass-open", + 26, + "bowtie", + 126, + "bowtie-open", + 27, + "circle-cross", + 127, + "circle-cross-open", + 28, + "circle-x", + 128, + "circle-x-open", + 29, + "square-cross", + 129, + "square-cross-open", + 30, + "square-x", + 130, + "square-x-open", + 31, + "diamond-cross", + 131, + "diamond-cross-open", + 32, + "diamond-x", + 132, + "diamond-x-open", + 33, + "cross-thin", + 133, + "cross-thin-open", + 34, + "x-thin", + 134, + "x-thin-open", + 35, + "asterisk", + 135, + "asterisk-open", + 36, + "hash", + 136, + "hash-open", + 236, + "hash-dot", + 336, + "hash-open-dot", + 37, + "y-up", + 137, + "y-up-open", + 38, + "y-down", + 138, + "y-down-open", + 39, + "y-left", + 139, + "y-left-open", + 40, + "y-right", + 140, + "y-right-open", + 41, + "line-ew", + 141, + "line-ew-open", + 42, + "line-ns", + 142, + "line-ns-open", + 43, + "line-ne", + 143, + "line-ne-open", + 44, + "line-nw", + 144, + "line-nw-open" + ], + "dflt": "circle", + "arrayOk": true, + "role": "style", + "editType": "style", + "description": "Sets the marker symbol type. Adding 100 is equivalent to appending *-open* to a symbol name. Adding 200 is equivalent to appending *-dot* to a symbol name. Adding 300 is equivalent to appending *-open-dot* or *dot-open* to a symbol name." + }, + "opacity": { + "valType": "number", + "min": 0, + "max": 1, + "arrayOk": true, + "role": "style", + "editType": "style", + "description": "Sets the marker opacity." + }, + "size": { + "valType": "number", + "min": 0, + "dflt": 6, + "arrayOk": true, + "role": "style", + "editType": "calcIfAutorange", + "description": "Sets the marker size (in px)." + }, + "maxdisplayed": { + "valType": "number", + "min": 0, + "dflt": 0, + "role": "style", + "editType": "plot", + "description": "Sets a maximum number of points to be drawn on the graph. *0* corresponds to no limit." + }, + "sizeref": { + "valType": "number", + "dflt": 1, + "role": "style", + "editType": "calc", + "description": "Has an effect only if `marker.size` is set to a numerical array. Sets the scale factor used to determine the rendered size of marker points. Use with `sizemin` and `sizemode`." + }, + "sizemin": { + "valType": "number", + "min": 0, + "dflt": 0, + "role": "style", + "editType": "calc", + "description": "Has an effect only if `marker.size` is set to a numerical array. Sets the minimum size (in px) of the rendered marker points." + }, + "sizemode": { + "valType": "enumerated", + "values": [ + "diameter", + "area" + ], + "dflt": "diameter", + "role": "info", + "editType": "calc", + "description": "Has an effect only if `marker.size` is set to a numerical array. Sets the rule for which the data in `size` is converted to pixels." + }, + "showscale": { + "valType": "boolean", + "role": "info", + "dflt": false, + "editType": "calc", + "description": "Has an effect only if `marker.color` is set to a numerical array. Determines whether or not a colorbar is displayed." + }, + "colorbar": { + "thicknessmode": { + "valType": "enumerated", + "values": [ + "fraction", + "pixels" + ], + "role": "style", + "dflt": "pixels", + "description": "Determines whether this color bar's thickness (i.e. the measure in the constant color direction) is set in units of plot *fraction* or in *pixels*. Use `thickness` to set the value.", + "editType": "colorbars" + }, + "thickness": { + "valType": "number", + "role": "style", + "min": 0, + "dflt": 30, + "description": "Sets the thickness of the color bar This measure excludes the size of the padding, ticks and labels.", + "editType": "colorbars" + }, + "lenmode": { + "valType": "enumerated", + "values": [ + "fraction", + "pixels" + ], + "role": "info", + "dflt": "fraction", + "description": "Determines whether this color bar's length (i.e. the measure in the color variation direction) is set in units of plot *fraction* or in *pixels. Use `len` to set the value.", + "editType": "colorbars" + }, + "len": { + "valType": "number", + "min": 0, + "dflt": 1, + "role": "style", + "description": "Sets the length of the color bar This measure excludes the padding of both ends. That is, the color bar length is this length minus the padding on both ends.", + "editType": "colorbars" + }, + "x": { + "valType": "number", + "dflt": 1.02, + "min": -2, + "max": 3, + "role": "style", + "description": "Sets the x position of the color bar (in plot fraction).", + "editType": "colorbars" + }, + "xanchor": { + "valType": "enumerated", + "values": [ + "left", + "center", + "right" + ], + "dflt": "left", + "role": "style", + "description": "Sets this color bar's horizontal position anchor. This anchor binds the `x` position to the *left*, *center* or *right* of the color bar.", + "editType": "colorbars" + }, + "xpad": { + "valType": "number", + "role": "style", + "min": 0, + "dflt": 10, + "description": "Sets the amount of padding (in px) along the x direction.", + "editType": "colorbars" + }, + "y": { + "valType": "number", + "role": "style", + "dflt": 0.5, + "min": -2, + "max": 3, + "description": "Sets the y position of the color bar (in plot fraction).", + "editType": "colorbars" + }, + "yanchor": { + "valType": "enumerated", + "values": [ + "top", + "middle", + "bottom" + ], + "role": "style", + "dflt": "middle", + "description": "Sets this color bar's vertical position anchor This anchor binds the `y` position to the *top*, *middle* or *bottom* of the color bar.", + "editType": "colorbars" + }, + "ypad": { + "valType": "number", + "role": "style", + "min": 0, + "dflt": 10, + "description": "Sets the amount of padding (in px) along the y direction.", + "editType": "colorbars" + }, + "outlinecolor": { + "valType": "color", + "dflt": "#444", + "role": "style", + "editType": "colorbars", + "description": "Sets the axis line color." + }, + "outlinewidth": { + "valType": "number", + "min": 0, + "dflt": 1, + "role": "style", + "editType": "colorbars", + "description": "Sets the width (in px) of the axis line." + }, + "bordercolor": { + "valType": "color", + "dflt": "#444", + "role": "style", + "editType": "colorbars", + "description": "Sets the axis line color." + }, + "borderwidth": { + "valType": "number", + "role": "style", + "min": 0, + "dflt": 0, + "description": "Sets the width (in px) or the border enclosing this color bar.", + "editType": "colorbars" + }, + "bgcolor": { + "valType": "color", + "role": "style", + "dflt": "rgba(0,0,0,0)", + "description": "Sets the color of padded area.", + "editType": "colorbars" + }, + "tickmode": { + "valType": "enumerated", + "values": [ + "auto", + "linear", + "array" + ], + "role": "info", + "editType": "colorbars", + "impliedEdits": {}, + "description": "Sets the tick mode for this axis. If *auto*, the number of ticks is set via `nticks`. If *linear*, the placement of the ticks is determined by a starting position `tick0` and a tick step `dtick` (*linear* is the default value if `tick0` and `dtick` are provided). If *array*, the placement of the ticks is set via `tickvals` and the tick text is `ticktext`. (*array* is the default value if `tickvals` is provided)." + }, + "nticks": { + "valType": "integer", + "min": 0, + "dflt": 0, + "role": "style", + "editType": "colorbars", + "description": "Specifies the maximum number of ticks for the particular axis. The actual number of ticks will be chosen automatically to be less than or equal to `nticks`. Has an effect only if `tickmode` is set to *auto*." + }, + "tick0": { + "valType": "any", + "role": "style", + "editType": "colorbars", + "impliedEdits": { + "tickmode": "linear" + }, + "description": "Sets the placement of the first tick on this axis. Use with `dtick`. If the axis `type` is *log*, then you must take the log of your starting tick (e.g. to set the starting tick to 100, set the `tick0` to 2) except when `dtick`=*L* (see `dtick` for more info). If the axis `type` is *date*, it should be a date string, like date data. If the axis `type` is *category*, it should be a number, using the scale where each category is assigned a serial number from zero in the order it appears." + }, + "dtick": { + "valType": "any", + "role": "style", + "editType": "colorbars", + "impliedEdits": { + "tickmode": "linear" + }, + "description": "Sets the step in-between ticks on this axis. Use with `tick0`. Must be a positive number, or special strings available to *log* and *date* axes. If the axis `type` is *log*, then ticks are set every 10^(n*dtick) where n is the tick number. For example, to set a tick mark at 1, 10, 100, 1000, ... set dtick to 1. To set tick marks at 1, 100, 10000, ... set dtick to 2. To set tick marks at 1, 5, 25, 125, 625, 3125, ... set dtick to log_10(5), or 0.69897000433. *log* has several special values; *L*, where `f` is a positive number, gives ticks linearly spaced in value (but not position). For example `tick0` = 0.1, `dtick` = *L0.5* will put ticks at 0.1, 0.6, 1.1, 1.6 etc. To show powers of 10 plus small digits between, use *D1* (all digits) or *D2* (only 2 and 5). `tick0` is ignored for *D1* and *D2*. If the axis `type` is *date*, then you must convert the time to milliseconds. For example, to set the interval between ticks to one day, set `dtick` to 86400000.0. *date* also has special values *M* gives ticks spaced by a number of months. `n` must be a positive integer. To set ticks on the 15th of every third month, set `tick0` to *2000-01-15* and `dtick` to *M3*. To set ticks every 4 years, set `dtick` to *M48*" + }, + "tickvals": { + "valType": "data_array", + "editType": "colorbars", + "description": "Sets the values at which ticks on this axis appear. Only has an effect if `tickmode` is set to *array*. Used with `ticktext`.", + "role": "data" + }, + "ticktext": { + "valType": "data_array", + "editType": "colorbars", + "description": "Sets the text displayed at the ticks position via `tickvals`. Only has an effect if `tickmode` is set to *array*. Used with `tickvals`.", + "role": "data" + }, + "ticks": { + "valType": "enumerated", + "values": [ + "outside", + "inside", + "" + ], + "role": "style", + "editType": "colorbars", + "description": "Determines whether ticks are drawn or not. If **, this axis' ticks are not drawn. If *outside* (*inside*), this axis' are drawn outside (inside) the axis lines.", + "dflt": "" + }, + "ticklen": { + "valType": "number", + "min": 0, + "dflt": 5, + "role": "style", + "editType": "colorbars", + "description": "Sets the tick length (in px)." + }, + "tickwidth": { + "valType": "number", + "min": 0, + "dflt": 1, + "role": "style", + "editType": "colorbars", + "description": "Sets the tick width (in px)." + }, + "tickcolor": { + "valType": "color", + "dflt": "#444", + "role": "style", + "editType": "colorbars", + "description": "Sets the tick color." + }, + "showticklabels": { + "valType": "boolean", + "dflt": true, + "role": "style", + "editType": "colorbars", + "description": "Determines whether or not the tick labels are drawn." + }, + "tickfont": { + "family": { + "valType": "string", + "role": "style", + "noBlank": true, + "strict": true, + "description": "HTML font family - the typeface that will be applied by the web browser. The web browser will only be able to apply a font if it is available on the system which it operates. Provide multiple font families, separated by commas, to indicate the preference in which to apply fonts if they aren't available on the system. The plotly service (at https://plot.ly or on-premise) generates images on a server, where only a select number of fonts are installed and supported. These include *Arial*, *Balto*, *Courier New*, *Droid Sans*,, *Droid Serif*, *Droid Sans Mono*, *Gravitas One*, *Old Standard TT*, *Open Sans*, *Overpass*, *PT Sans Narrow*, *Raleway*, *Times New Roman*.", + "editType": "colorbars" + }, + "size": { + "valType": "number", + "role": "style", + "min": 1, + "editType": "colorbars" + }, + "color": { + "valType": "color", + "role": "style", + "editType": "colorbars" + }, + "description": "Sets the color bar's tick label font", + "editType": "colorbars", + "role": "object" + }, + "tickangle": { + "valType": "angle", + "dflt": "auto", + "role": "style", + "editType": "colorbars", + "description": "Sets the angle of the tick labels with respect to the horizontal. For example, a `tickangle` of -90 draws the tick labels vertically." + }, + "tickformat": { + "valType": "string", + "dflt": "", + "role": "style", + "editType": "colorbars", + "description": "Sets the tick label formatting rule using d3 formatting mini-languages which are very similar to those in Python. For numbers, see: https://github.com/d3/d3-format/blob/master/README.md#locale_format And for dates see: https://github.com/d3/d3-time-format/blob/master/README.md#locale_format We add one item to d3's date formatter: *%{n}f* for fractional seconds with n digits. For example, *2016-10-13 09:15:23.456* with tickformat *%H~%M~%S.%2f* would display *09~15~23.46*" + }, + "tickformatstops": { + "items": { + "tickformatstop": { + "dtickrange": { + "valType": "info_array", + "role": "info", + "items": [ + { + "valType": "any", + "editType": "colorbars" + }, + { + "valType": "any", + "editType": "colorbars" + } + ], + "editType": "colorbars", + "description": "range [*min*, *max*], where *min*, *max* - dtick values which describe some zoom level, it is possible to omit *min* or *max* value by passing *null*" + }, + "value": { + "valType": "string", + "dflt": "", + "role": "style", + "editType": "colorbars", + "description": "string - dtickformat for described zoom level, the same as *tickformat*" + }, + "editType": "colorbars", + "role": "object" + } + }, + "role": "object" + }, + "tickprefix": { + "valType": "string", + "dflt": "", + "role": "style", + "editType": "colorbars", + "description": "Sets a tick label prefix." + }, + "showtickprefix": { + "valType": "enumerated", + "values": [ + "all", + "first", + "last", + "none" + ], + "dflt": "all", + "role": "style", + "editType": "colorbars", + "description": "If *all*, all tick labels are displayed with a prefix. If *first*, only the first tick is displayed with a prefix. If *last*, only the last tick is displayed with a suffix. If *none*, tick prefixes are hidden." + }, + "ticksuffix": { + "valType": "string", + "dflt": "", + "role": "style", + "editType": "colorbars", + "description": "Sets a tick label suffix." + }, + "showticksuffix": { + "valType": "enumerated", + "values": [ + "all", + "first", + "last", + "none" + ], + "dflt": "all", + "role": "style", + "editType": "colorbars", + "description": "Same as `showtickprefix` but for tick suffixes." + }, + "separatethousands": { + "valType": "boolean", + "dflt": false, + "role": "style", + "editType": "colorbars", + "description": "If \"true\", even 4-digit integers are separated" + }, + "exponentformat": { + "valType": "enumerated", + "values": [ + "none", + "e", + "E", + "power", + "SI", + "B" + ], + "dflt": "B", + "role": "style", + "editType": "colorbars", + "description": "Determines a formatting rule for the tick exponents. For example, consider the number 1,000,000,000. If *none*, it appears as 1,000,000,000. If *e*, 1e+9. If *E*, 1E+9. If *power*, 1x10^9 (with 9 in a super script). If *SI*, 1G. If *B*, 1B." + }, + "showexponent": { + "valType": "enumerated", + "values": [ + "all", + "first", + "last", + "none" + ], + "dflt": "all", + "role": "style", + "editType": "colorbars", + "description": "If *all*, all exponents are shown besides their significands. If *first*, only the exponent of the first tick is shown. If *last*, only the exponent of the last tick is shown. If *none*, no exponents appear." + }, + "title": { + "valType": "string", + "role": "info", + "dflt": "Click to enter colorscale title", + "description": "Sets the title of the color bar.", + "editType": "colorbars" + }, + "titlefont": { + "family": { + "valType": "string", + "role": "style", + "noBlank": true, + "strict": true, + "description": "HTML font family - the typeface that will be applied by the web browser. The web browser will only be able to apply a font if it is available on the system which it operates. Provide multiple font families, separated by commas, to indicate the preference in which to apply fonts if they aren't available on the system. The plotly service (at https://plot.ly or on-premise) generates images on a server, where only a select number of fonts are installed and supported. These include *Arial*, *Balto*, *Courier New*, *Droid Sans*,, *Droid Serif*, *Droid Sans Mono*, *Gravitas One*, *Old Standard TT*, *Open Sans*, *Overpass*, *PT Sans Narrow*, *Raleway*, *Times New Roman*.", + "editType": "colorbars" + }, + "size": { + "valType": "number", + "role": "style", + "min": 1, + "editType": "colorbars" + }, + "color": { + "valType": "color", + "role": "style", + "editType": "colorbars" + }, + "description": "Sets this color bar's title font.", + "editType": "colorbars", + "role": "object" + }, + "titleside": { + "valType": "enumerated", + "values": [ + "right", + "top", + "bottom" + ], + "role": "style", + "dflt": "top", + "description": "Determines the location of the colorbar title with respect to the color bar.", + "editType": "colorbars" + }, + "editType": "colorbars", + "role": "object", + "tickvalssrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for tickvals .", + "editType": "none" + }, + "ticktextsrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for ticktext .", + "editType": "none" + } + }, + "line": { + "width": { + "valType": "number", + "min": 0, + "arrayOk": true, + "role": "style", + "editType": "style", + "description": "Sets the width (in px) of the lines bounding the marker points." + }, + "editType": "calc", + "color": { + "valType": "color", + "arrayOk": true, + "role": "style", + "editType": "style", + "description": "Sets the marker.line color. It accepts either a specific color or an array of numbers that are mapped to the colorscale relative to the max and min values of the array or relative to `cmin` and `cmax` if set." + }, + "colorscale": { + "valType": "colorscale", + "role": "style", + "editType": "calc", + "impliedEdits": { + "autocolorscale": false + }, + "description": "Sets the colorscale and only has an effect if `marker.line.color` is set to a numerical array. The colorscale must be an array containing arrays mapping a normalized value to an rgb, rgba, hex, hsl, hsv, or named color string. At minimum, a mapping for the lowest (0) and highest (1) values are required. For example, `[[0, 'rgb(0,0,255)', [1, 'rgb(255,0,0)']]`. To control the bounds of the colorscale in color space, use `marker.line.cmin` and `marker.line.cmax`. Alternatively, `colorscale` may be a palette name string of the following list: Greys, YlGnBu, Greens, YlOrRd, Bluered, RdBu, Reds, Blues, Picnic, Rainbow, Portland, Jet, Hot, Blackbody, Earth, Electric, Viridis" + }, + "cauto": { + "valType": "boolean", + "role": "info", + "dflt": true, + "editType": "calc", + "impliedEdits": {}, + "description": "Has an effect only if `marker.line.color` is set to a numerical array and `cmin`, `cmax` are set by the user. In this case, it controls whether the range of colors in `colorscale` is mapped to the range of values in the `color` array (`cauto: true`), or the `cmin`/`cmax` values (`cauto: false`). Defaults to `false` when `cmin`, `cmax` are set by the user." + }, + "cmax": { + "valType": "number", + "role": "info", + "dflt": null, + "editType": "plot", + "impliedEdits": { + "cauto": false + }, + "description": "Has an effect only if `marker.line.color` is set to a numerical array. Sets the upper bound of the color domain. Value should be associated to the `marker.line.color` array index, and if set, `marker.line.cmin` must be set as well." + }, + "cmin": { + "valType": "number", + "role": "info", + "dflt": null, + "editType": "plot", + "impliedEdits": { + "cauto": false + }, + "description": "Has an effect only if `marker.line.color` is set to a numerical array. Sets the lower bound of the color domain. Value should be associated to the `marker.line.color` array index, and if set, `marker.line.cmax` must be set as well." + }, + "autocolorscale": { + "valType": "boolean", + "role": "style", + "dflt": true, + "editType": "calc", + "impliedEdits": {}, + "description": "Has an effect only if `marker.line.color` is set to a numerical array. Determines whether the colorscale is a default palette (`autocolorscale: true`) or the palette determined by `marker.line.colorscale`. In case `colorscale` is unspecified or `autocolorscale` is true, the default palette will be chosen according to whether numbers in the `color` array are all positive, all negative or mixed." + }, + "reversescale": { + "valType": "boolean", + "role": "style", + "dflt": false, + "editType": "calc", + "description": "Has an effect only if `marker.line.color` is set to a numerical array. Reverses the color mapping if true (`cmin` will correspond to the last color in the array and `cmax` will correspond to the first color)." + }, + "role": "object", + "widthsrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for width .", + "editType": "none" + }, + "colorsrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for color .", + "editType": "none" + } + }, + "gradient": { + "type": { + "valType": "enumerated", + "values": [ + "radial", + "horizontal", + "vertical", + "none" + ], + "arrayOk": true, + "dflt": "none", + "role": "style", + "editType": "calc", + "description": "Sets the type of gradient used to fill the markers" + }, + "color": { + "valType": "color", + "arrayOk": true, + "role": "style", + "editType": "calc", + "description": "Sets the final color of the gradient fill: the center color for radial, the right for horizontal, or the bottom for vertical." + }, + "editType": "calc", + "role": "object", + "typesrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for type .", + "editType": "none" + }, + "colorsrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for color .", + "editType": "none" + } + }, + "editType": "calc", + "color": { + "valType": "color", + "arrayOk": true, + "role": "style", + "editType": "style", + "description": "Sets the marker color. It accepts either a specific color or an array of numbers that are mapped to the colorscale relative to the max and min values of the array or relative to `cmin` and `cmax` if set." + }, + "colorscale": { + "valType": "colorscale", + "role": "style", + "editType": "calc", + "impliedEdits": { + "autocolorscale": false + }, + "description": "Sets the colorscale and only has an effect if `marker.color` is set to a numerical array. The colorscale must be an array containing arrays mapping a normalized value to an rgb, rgba, hex, hsl, hsv, or named color string. At minimum, a mapping for the lowest (0) and highest (1) values are required. For example, `[[0, 'rgb(0,0,255)', [1, 'rgb(255,0,0)']]`. To control the bounds of the colorscale in color space, use `marker.cmin` and `marker.cmax`. Alternatively, `colorscale` may be a palette name string of the following list: Greys, YlGnBu, Greens, YlOrRd, Bluered, RdBu, Reds, Blues, Picnic, Rainbow, Portland, Jet, Hot, Blackbody, Earth, Electric, Viridis" + }, + "cauto": { + "valType": "boolean", + "role": "info", + "dflt": true, + "editType": "calc", + "impliedEdits": {}, + "description": "Has an effect only if `marker.color` is set to a numerical array and `cmin`, `cmax` are set by the user. In this case, it controls whether the range of colors in `colorscale` is mapped to the range of values in the `color` array (`cauto: true`), or the `cmin`/`cmax` values (`cauto: false`). Defaults to `false` when `cmin`, `cmax` are set by the user." + }, + "cmax": { + "valType": "number", + "role": "info", + "dflt": null, + "editType": "plot", + "impliedEdits": { + "cauto": false + }, + "description": "Has an effect only if `marker.color` is set to a numerical array. Sets the upper bound of the color domain. Value should be associated to the `marker.color` array index, and if set, `marker.cmin` must be set as well." + }, + "cmin": { + "valType": "number", + "role": "info", + "dflt": null, + "editType": "plot", + "impliedEdits": { + "cauto": false + }, + "description": "Has an effect only if `marker.color` is set to a numerical array. Sets the lower bound of the color domain. Value should be associated to the `marker.color` array index, and if set, `marker.cmax` must be set as well." + }, + "autocolorscale": { + "valType": "boolean", + "role": "style", + "dflt": true, + "editType": "calc", + "impliedEdits": {}, + "description": "Has an effect only if `marker.color` is set to a numerical array. Determines whether the colorscale is a default palette (`autocolorscale: true`) or the palette determined by `marker.colorscale`. In case `colorscale` is unspecified or `autocolorscale` is true, the default palette will be chosen according to whether numbers in the `color` array are all positive, all negative or mixed." + }, + "reversescale": { + "valType": "boolean", + "role": "style", + "dflt": false, + "editType": "calc", + "description": "Has an effect only if `marker.color` is set to a numerical array. Reverses the color mapping if true (`cmin` will correspond to the last color in the array and `cmax` will correspond to the first color)." + }, + "role": "object", + "symbolsrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for symbol .", + "editType": "none" + }, + "opacitysrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for opacity .", + "editType": "none" + }, + "sizesrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for size .", + "editType": "none" + }, + "colorsrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for color .", + "editType": "none" + } + }, + "selected": { + "marker": { + "opacity": { + "valType": "number", + "min": 0, + "max": 1, + "role": "style", + "editType": "style", + "description": "Sets the marker opacity of selected points." + }, + "color": { + "valType": "color", + "role": "style", + "editType": "style", + "description": "Sets the marker color of selected points." + }, + "size": { + "valType": "number", + "min": 0, + "role": "style", + "editType": "style", + "description": "Sets the marker size of selected points." + }, + "editType": "style", + "role": "object" + }, + "textfont": { + "color": { + "valType": "color", + "role": "style", + "editType": "style", + "description": "Sets the text font color of selected points." + }, + "editType": "style", + "role": "object" + }, + "editType": "style", + "role": "object" + }, + "unselected": { + "marker": { + "opacity": { + "valType": "number", + "min": 0, + "max": 1, + "role": "style", + "editType": "style", + "description": "Sets the marker opacity of unselected points, applied only when a selection exists." + }, + "color": { + "valType": "color", + "role": "style", + "editType": "style", + "description": "Sets the marker color of unselected points, applied only when a selection exists." + }, + "size": { + "valType": "number", + "min": 0, + "role": "style", + "editType": "style", + "description": "Sets the marker size of unselected points, applied only when a selection exists." + }, + "editType": "style", + "role": "object" + }, + "textfont": { + "color": { + "valType": "color", + "role": "style", + "editType": "style", + "description": "Sets the text font color of unselected points, applied only when a selection exists." + }, + "editType": "style", + "role": "object" + }, + "editType": "style", + "role": "object" + }, + "textposition": { + "valType": "enumerated", + "values": [ + "top left", + "top center", + "top right", + "middle left", + "middle center", + "middle right", + "bottom left", + "bottom center", + "bottom right" + ], + "dflt": "middle center", + "arrayOk": true, + "role": "style", + "editType": "calc", + "description": "Sets the positions of the `text` elements with respects to the (x,y) coordinates." + }, + "textfont": { + "family": { + "valType": "string", + "role": "style", + "noBlank": true, + "strict": true, + "editType": "calc", + "description": "HTML font family - the typeface that will be applied by the web browser. The web browser will only be able to apply a font if it is available on the system which it operates. Provide multiple font families, separated by commas, to indicate the preference in which to apply fonts if they aren't available on the system. The plotly service (at https://plot.ly or on-premise) generates images on a server, where only a select number of fonts are installed and supported. These include *Arial*, *Balto*, *Courier New*, *Droid Sans*,, *Droid Serif*, *Droid Sans Mono*, *Gravitas One*, *Old Standard TT*, *Open Sans*, *Overpass*, *PT Sans Narrow*, *Raleway*, *Times New Roman*.", + "arrayOk": true + }, + "size": { + "valType": "number", + "role": "style", + "min": 1, + "editType": "calc", + "arrayOk": true + }, + "color": { + "valType": "color", + "role": "style", + "editType": "style", + "arrayOk": true + }, + "editType": "calc", + "description": "Sets the text font.", + "role": "object", + "familysrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for family .", + "editType": "none" + }, + "sizesrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for size .", + "editType": "none" + }, + "colorsrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for color .", + "editType": "none" + } + }, + "r": { + "valType": "data_array", + "editType": "calc", + "description": "For polar chart only.Sets the radial coordinates.", + "role": "data" + }, + "t": { + "valType": "data_array", + "editType": "calc", + "description": "For polar chart only.Sets the angular coordinates.", + "role": "data" + }, + "error_y": { + "visible": { + "valType": "boolean", + "role": "info", + "editType": "calc", + "description": "Determines whether or not this set of error bars is visible." + }, + "type": { + "valType": "enumerated", + "values": [ + "percent", + "constant", + "sqrt", + "data" + ], + "role": "info", + "editType": "calc", + "description": "Determines the rule used to generate the error bars. If *constant`, the bar lengths are of a constant value. Set this constant in `value`. If *percent*, the bar lengths correspond to a percentage of underlying data. Set this percentage in `value`. If *sqrt*, the bar lengths correspond to the sqaure of the underlying data. If *array*, the bar lengths are set with data set `array`." + }, + "symmetric": { + "valType": "boolean", + "role": "info", + "editType": "calc", + "description": "Determines whether or not the error bars have the same length in both direction (top/bottom for vertical bars, left/right for horizontal bars." + }, + "array": { + "valType": "data_array", + "editType": "calc", + "description": "Sets the data corresponding the length of each error bar. Values are plotted relative to the underlying data.", + "role": "data" + }, + "arrayminus": { + "valType": "data_array", + "editType": "calc", + "description": "Sets the data corresponding the length of each error bar in the bottom (left) direction for vertical (horizontal) bars Values are plotted relative to the underlying data.", + "role": "data" + }, + "value": { + "valType": "number", + "min": 0, + "dflt": 10, + "role": "info", + "editType": "calc", + "description": "Sets the value of either the percentage (if `type` is set to *percent*) or the constant (if `type` is set to *constant*) corresponding to the lengths of the error bars." + }, + "valueminus": { + "valType": "number", + "min": 0, + "dflt": 10, + "role": "info", + "editType": "calc", + "description": "Sets the value of either the percentage (if `type` is set to *percent*) or the constant (if `type` is set to *constant*) corresponding to the lengths of the error bars in the bottom (left) direction for vertical (horizontal) bars" + }, + "traceref": { + "valType": "integer", + "min": 0, + "dflt": 0, + "role": "info", + "editType": "style" + }, + "tracerefminus": { + "valType": "integer", + "min": 0, + "dflt": 0, + "role": "info", + "editType": "style" + }, + "copy_ystyle": { + "valType": "boolean", + "role": "style", + "editType": "plot" + }, + "copy_zstyle": { + "valType": "boolean", + "role": "style", + "editType": "style" + }, + "color": { + "valType": "color", + "role": "style", + "editType": "style", + "description": "Sets the stoke color of the error bars." + }, + "thickness": { + "valType": "number", + "min": 0, + "dflt": 2, + "role": "style", + "editType": "style", + "description": "Sets the thickness (in px) of the error bars." + }, + "width": { + "valType": "number", + "min": 0, + "role": "style", + "editType": "plot", + "description": "Sets the width (in px) of the cross-bar at both ends of the error bars." + }, + "editType": "calc", + "_deprecated": { + "opacity": { + "valType": "number", + "role": "style", + "editType": "style", + "description": "Obsolete. Use the alpha channel in error bar `color` to set the opacity." + } + }, + "role": "object", + "arraysrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for array .", + "editType": "none" + }, + "arrayminussrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for arrayminus .", + "editType": "none" + } + }, + "error_x": { + "visible": { + "valType": "boolean", + "role": "info", + "editType": "calc", + "description": "Determines whether or not this set of error bars is visible." + }, + "type": { + "valType": "enumerated", + "values": [ + "percent", + "constant", + "sqrt", + "data" + ], + "role": "info", + "editType": "calc", + "description": "Determines the rule used to generate the error bars. If *constant`, the bar lengths are of a constant value. Set this constant in `value`. If *percent*, the bar lengths correspond to a percentage of underlying data. Set this percentage in `value`. If *sqrt*, the bar lengths correspond to the sqaure of the underlying data. If *array*, the bar lengths are set with data set `array`." + }, + "symmetric": { + "valType": "boolean", + "role": "info", + "editType": "calc", + "description": "Determines whether or not the error bars have the same length in both direction (top/bottom for vertical bars, left/right for horizontal bars." + }, + "array": { + "valType": "data_array", + "editType": "calc", + "description": "Sets the data corresponding the length of each error bar. Values are plotted relative to the underlying data.", + "role": "data" + }, + "arrayminus": { + "valType": "data_array", + "editType": "calc", + "description": "Sets the data corresponding the length of each error bar in the bottom (left) direction for vertical (horizontal) bars Values are plotted relative to the underlying data.", + "role": "data" + }, + "value": { + "valType": "number", + "min": 0, + "dflt": 10, + "role": "info", + "editType": "calc", + "description": "Sets the value of either the percentage (if `type` is set to *percent*) or the constant (if `type` is set to *constant*) corresponding to the lengths of the error bars." + }, + "valueminus": { + "valType": "number", + "min": 0, + "dflt": 10, + "role": "info", + "editType": "calc", + "description": "Sets the value of either the percentage (if `type` is set to *percent*) or the constant (if `type` is set to *constant*) corresponding to the lengths of the error bars in the bottom (left) direction for vertical (horizontal) bars" + }, + "traceref": { + "valType": "integer", + "min": 0, + "dflt": 0, + "role": "info", + "editType": "style" + }, + "tracerefminus": { + "valType": "integer", + "min": 0, + "dflt": 0, + "role": "info", + "editType": "style" + }, + "copy_ystyle": { + "valType": "boolean", + "role": "style", + "editType": "plot" + }, + "copy_zstyle": { + "valType": "boolean", + "role": "style", + "editType": "style" + }, + "color": { + "valType": "color", + "role": "style", + "editType": "style", + "description": "Sets the stoke color of the error bars." + }, + "thickness": { + "valType": "number", + "min": 0, + "dflt": 2, + "role": "style", + "editType": "style", + "description": "Sets the thickness (in px) of the error bars." + }, + "width": { + "valType": "number", + "min": 0, + "role": "style", + "editType": "plot", + "description": "Sets the width (in px) of the cross-bar at both ends of the error bars." + }, + "editType": "calc", + "_deprecated": { + "opacity": { + "valType": "number", + "role": "style", + "editType": "style", + "description": "Obsolete. Use the alpha channel in error bar `color` to set the opacity." + } + }, + "role": "object", + "arraysrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for array .", + "editType": "none" + }, + "arrayminussrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for arrayminus .", + "editType": "none" + } + }, + "xcalendar": { + "valType": "enumerated", + "values": [ + "gregorian", + "chinese", + "coptic", + "discworld", + "ethiopian", + "hebrew", + "islamic", + "julian", + "mayan", + "nanakshahi", + "nepali", + "persian", + "jalali", + "taiwan", + "thai", + "ummalqura" + ], + "role": "info", + "editType": "calc", + "dflt": "gregorian", + "description": "Sets the calendar system to use with `x` date data." + }, + "ycalendar": { + "valType": "enumerated", + "values": [ + "gregorian", + "chinese", + "coptic", + "discworld", + "ethiopian", + "hebrew", + "islamic", + "julian", + "mayan", + "nanakshahi", + "nepali", + "persian", + "jalali", + "taiwan", + "thai", + "ummalqura" + ], + "role": "info", + "editType": "calc", + "dflt": "gregorian", + "description": "Sets the calendar system to use with `y` date data." + }, + "xaxis": { + "valType": "subplotid", + "role": "info", + "dflt": "x", + "editType": "calc+clearAxisTypes", + "description": "Sets a reference between this trace's x coordinates and a 2D cartesian x axis. If *x* (the default value), the x coordinates refer to `layout.xaxis`. If *x2*, the x coordinates refer to `layout.xaxis2`, and so on." + }, + "yaxis": { + "valType": "subplotid", + "role": "info", + "dflt": "y", + "editType": "calc+clearAxisTypes", + "description": "Sets a reference between this trace's y coordinates and a 2D cartesian y axis. If *y* (the default value), the y coordinates refer to `layout.yaxis`. If *y2*, the y coordinates refer to `layout.xaxis2`, and so on." + }, + "idssrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for ids .", + "editType": "none" + }, + "customdatasrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for customdata .", + "editType": "none" + }, + "hoverinfosrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for hoverinfo .", + "editType": "none" + }, + "xsrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for x .", + "editType": "none" + }, + "ysrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for y .", + "editType": "none" + }, + "textsrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for text .", + "editType": "none" + }, + "hovertextsrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for hovertext .", + "editType": "none" + }, + "textpositionsrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for textposition .", + "editType": "none" + }, + "rsrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for r .", + "editType": "none" + }, + "tsrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for t .", + "editType": "none" + } + } + }, + "box": { + "meta": { + "description": "In vertical (horizontal) box plots, statistics are computed using `y` (`x`) values. By supplying an `x` (`y`) array, one box per distinct x (y) value is drawn If no `x` (`y`) {array} is provided, a single box is drawn. That box position is then positioned with with `name` or with `x0` (`y0`) if provided. Each box spans from quartile 1 (Q1) to quartile 3 (Q3). The second quartile (Q2) is marked by a line inside the box. By default, the whiskers correspond to the box' edges +/- 1.5 times the interquartile range (IQR = Q3-Q1), see *boxpoints* for other options." + }, + "attributes": { + "type": "box", + "visible": { + "valType": "enumerated", + "values": [ + true, + false, + "legendonly" + ], + "role": "info", + "dflt": true, + "editType": "calc", + "description": "Determines whether or not this trace is visible. If *legendonly*, the trace is not drawn, but can appear as a legend item (provided that the legend itself is visible)." + }, + "showlegend": { + "valType": "boolean", + "role": "info", + "dflt": true, + "editType": "style", + "description": "Determines whether or not an item corresponding to this trace is shown in the legend." + }, + "legendgroup": { + "valType": "string", + "role": "info", + "dflt": "", + "editType": "style", + "description": "Sets the legend group for this trace. Traces part of the same legend group hide/show at the same time when toggling legend items." + }, + "opacity": { + "valType": "number", + "role": "style", + "min": 0, + "max": 1, + "dflt": 1, + "editType": "style", + "description": "Sets the opacity of the trace." + }, + "name": { + "valType": "string", + "role": "info", + "editType": "calc+clearAxisTypes", + "description": "Sets the trace name. The trace name appear as the legend item and on hover. For box traces, the name will also be used for the position coordinate, if `x` and `x0` (`y` and `y0` if horizontal) are missing and the position axis is categorical" + }, + "uid": { + "valType": "string", + "role": "info", + "dflt": "", + "editType": "calc" + }, + "ids": { + "valType": "data_array", + "editType": "calc", + "description": "Assigns id labels to each datum. These ids for object constancy of data points during animation.", + "role": "data" + }, + "customdata": { + "valType": "data_array", + "editType": "calc", + "description": "Assigns extra data each datum. This may be useful when listening to hover, click and selection events. Note that, *scatter* traces also appends customdata items in the markers DOM elements", + "role": "data" + }, + "selectedpoints": { + "valType": "any", + "role": "info", + "editType": "calc", + "description": "Array containing integer indices of selected points. Has an effect only for traces that support selections. Note that an empty array means an empty selection where the `unselected` are turned on for all points, whereas, any other non-array values means no selection all where the `selected` and `unselected` styles have no effect." + }, + "hoverinfo": { + "valType": "flaglist", + "role": "info", + "flags": [ + "x", + "y", + "z", + "text", + "name" + ], + "extras": [ + "all", + "none", + "skip" + ], + "arrayOk": true, + "dflt": "all", + "editType": "none", + "description": "Determines which trace information appear on hover. If `none` or `skip` are set, no information is displayed upon hovering. But, if `none` is set, click and hover events are still fired." + }, + "hoverlabel": { + "bgcolor": { + "valType": "color", + "role": "style", + "arrayOk": true, + "editType": "none", + "description": "Sets the background color of the hover labels for this trace" + }, + "bordercolor": { + "valType": "color", + "role": "style", + "arrayOk": true, + "editType": "none", + "description": "Sets the border color of the hover labels for this trace." + }, + "font": { + "family": { + "valType": "string", + "role": "style", + "noBlank": true, + "strict": true, + "editType": "none", + "description": "HTML font family - the typeface that will be applied by the web browser. The web browser will only be able to apply a font if it is available on the system which it operates. Provide multiple font families, separated by commas, to indicate the preference in which to apply fonts if they aren't available on the system. The plotly service (at https://plot.ly or on-premise) generates images on a server, where only a select number of fonts are installed and supported. These include *Arial*, *Balto*, *Courier New*, *Droid Sans*,, *Droid Serif*, *Droid Sans Mono*, *Gravitas One*, *Old Standard TT*, *Open Sans*, *Overpass*, *PT Sans Narrow*, *Raleway*, *Times New Roman*.", + "arrayOk": true + }, + "size": { + "valType": "number", + "role": "style", + "min": 1, + "editType": "none", + "arrayOk": true + }, + "color": { + "valType": "color", + "role": "style", + "editType": "none", + "arrayOk": true + }, + "editType": "none", + "description": "Sets the font used in hover labels.", + "role": "object", + "familysrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for family .", + "editType": "none" + }, + "sizesrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for size .", + "editType": "none" + }, + "colorsrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for color .", + "editType": "none" + } + }, + "namelength": { + "valType": "integer", + "min": -1, + "arrayOk": true, + "role": "style", + "editType": "none", + "description": "Sets the length (in number of characters) of the trace name in the hover labels for this trace. -1 shows the whole name regardless of length. 0-3 shows the first 0-3 characters, and an integer >3 will show the whole name if it is less than that many characters, but if it is longer, will truncate to `namelength - 3` characters and add an ellipsis." + }, + "editType": "calc", + "role": "object", + "bgcolorsrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for bgcolor .", + "editType": "none" + }, + "bordercolorsrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for bordercolor .", + "editType": "none" + }, + "namelengthsrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for namelength .", + "editType": "none" + } + }, + "stream": { + "token": { + "valType": "string", + "noBlank": true, + "strict": true, + "role": "info", + "editType": "calc", + "description": "The stream id number links a data trace on a plot with a stream. See https://plot.ly/settings for more details." + }, + "maxpoints": { + "valType": "number", + "min": 0, + "max": 10000, + "dflt": 500, + "role": "info", + "editType": "calc", + "description": "Sets the maximum number of points to keep on the plots from an incoming stream. If `maxpoints` is set to *50*, only the newest 50 points will be displayed on the plot." + }, + "editType": "calc", + "role": "object" + }, + "y": { + "valType": "data_array", + "editType": "calc+clearAxisTypes", + "description": "Sets the y sample data or coordinates. See overview for more info.", + "role": "data" + }, + "x": { + "valType": "data_array", + "editType": "calc+clearAxisTypes", + "description": "Sets the x sample data or coordinates. See overview for more info.", + "role": "data" + }, + "x0": { + "valType": "any", + "role": "info", + "editType": "calc+clearAxisTypes", + "description": "Sets the x coordinate of the box. See overview for more info." + }, + "y0": { + "valType": "any", + "role": "info", + "editType": "calc+clearAxisTypes", + "description": "Sets the y coordinate of the box. See overview for more info." + }, + "text": { + "valType": "string", + "role": "info", + "dflt": "", + "arrayOk": true, + "editType": "calc", + "description": "Sets the text elements associated with each sample value. If a single string, the same string appears over all the data points. If an array of string, the items are mapped in order to the this trace's (x,y) coordinates. To be seen, trace `hoverinfo` must contain a *text* flag." + }, + "whiskerwidth": { + "valType": "number", + "min": 0, + "max": 1, + "dflt": 0.5, + "role": "style", + "editType": "calcIfAutorange", + "description": "Sets the width of the whiskers relative to the box' width. For example, with 1, the whiskers are as wide as the box(es)." + }, + "boxpoints": { + "valType": "enumerated", + "values": [ + "all", + "outliers", + "suspectedoutliers", + false + ], + "dflt": "outliers", + "role": "style", + "editType": "calcIfAutorange", + "description": "If *outliers*, only the sample points lying outside the whiskers are shown If *suspectedoutliers*, the outlier points are shown and points either less than 4*Q1-3*Q3 or greater than 4*Q3-3*Q1 are highlighted (see `outliercolor`) If *all*, all sample points are shown If *false*, only the box(es) are shown with no sample points" + }, + "boxmean": { + "valType": "enumerated", + "values": [ + true, + "sd", + false + ], + "dflt": false, + "role": "style", + "editType": "calcIfAutorange", + "description": "If *true*, the mean of the box(es)' underlying distribution is drawn as a dashed line inside the box(es). If *sd* the standard deviation is also drawn." + }, + "jitter": { + "valType": "number", + "min": 0, + "max": 1, + "role": "style", + "editType": "calcIfAutorange", + "description": "Sets the amount of jitter in the sample points drawn. If *0*, the sample points align along the distribution axis. If *1*, the sample points are drawn in a random jitter of width equal to the width of the box(es)." + }, + "pointpos": { + "valType": "number", + "min": -2, + "max": 2, + "role": "style", + "editType": "calcIfAutorange", + "description": "Sets the position of the sample points in relation to the box(es). If *0*, the sample points are places over the center of the box(es). Positive (negative) values correspond to positions to the right (left) for vertical boxes and above (below) for horizontal boxes" + }, + "orientation": { + "valType": "enumerated", + "values": [ + "v", + "h" + ], + "role": "style", + "editType": "calc+clearAxisTypes", + "description": "Sets the orientation of the box(es). If *v* (*h*), the distribution is visualized along the vertical (horizontal)." + }, + "marker": { + "outliercolor": { + "valType": "color", + "dflt": "rgba(0, 0, 0, 0)", + "role": "style", + "editType": "style", + "description": "Sets the color of the outlier sample points." + }, + "symbol": { + "valType": "enumerated", + "values": [ + 0, + "circle", + 100, + "circle-open", + 200, + "circle-dot", + 300, + "circle-open-dot", + 1, + "square", + 101, + "square-open", + 201, + "square-dot", + 301, + "square-open-dot", + 2, + "diamond", + 102, + "diamond-open", + 202, + "diamond-dot", + 302, + "diamond-open-dot", + 3, + "cross", + 103, + "cross-open", + 203, + "cross-dot", + 303, + "cross-open-dot", + 4, + "x", + 104, + "x-open", + 204, + "x-dot", + 304, + "x-open-dot", + 5, + "triangle-up", + 105, + "triangle-up-open", + 205, + "triangle-up-dot", + 305, + "triangle-up-open-dot", + 6, + "triangle-down", + 106, + "triangle-down-open", + 206, + "triangle-down-dot", + 306, + "triangle-down-open-dot", + 7, + "triangle-left", + 107, + "triangle-left-open", + 207, + "triangle-left-dot", + 307, + "triangle-left-open-dot", + 8, + "triangle-right", + 108, + "triangle-right-open", + 208, + "triangle-right-dot", + 308, + "triangle-right-open-dot", + 9, + "triangle-ne", + 109, + "triangle-ne-open", + 209, + "triangle-ne-dot", + 309, + "triangle-ne-open-dot", + 10, + "triangle-se", + 110, + "triangle-se-open", + 210, + "triangle-se-dot", + 310, + "triangle-se-open-dot", + 11, + "triangle-sw", + 111, + "triangle-sw-open", + 211, + "triangle-sw-dot", + 311, + "triangle-sw-open-dot", + 12, + "triangle-nw", + 112, + "triangle-nw-open", + 212, + "triangle-nw-dot", + 312, + "triangle-nw-open-dot", + 13, + "pentagon", + 113, + "pentagon-open", + 213, + "pentagon-dot", + 313, + "pentagon-open-dot", + 14, + "hexagon", + 114, + "hexagon-open", + 214, + "hexagon-dot", + 314, + "hexagon-open-dot", + 15, + "hexagon2", + 115, + "hexagon2-open", + 215, + "hexagon2-dot", + 315, + "hexagon2-open-dot", + 16, + "octagon", + 116, + "octagon-open", + 216, + "octagon-dot", + 316, + "octagon-open-dot", + 17, + "star", + 117, + "star-open", + 217, + "star-dot", + 317, + "star-open-dot", + 18, + "hexagram", + 118, + "hexagram-open", + 218, + "hexagram-dot", + 318, + "hexagram-open-dot", + 19, + "star-triangle-up", + 119, + "star-triangle-up-open", + 219, + "star-triangle-up-dot", + 319, + "star-triangle-up-open-dot", + 20, + "star-triangle-down", + 120, + "star-triangle-down-open", + 220, + "star-triangle-down-dot", + 320, + "star-triangle-down-open-dot", + 21, + "star-square", + 121, + "star-square-open", + 221, + "star-square-dot", + 321, + "star-square-open-dot", + 22, + "star-diamond", + 122, + "star-diamond-open", + 222, + "star-diamond-dot", + 322, + "star-diamond-open-dot", + 23, + "diamond-tall", + 123, + "diamond-tall-open", + 223, + "diamond-tall-dot", + 323, + "diamond-tall-open-dot", + 24, + "diamond-wide", + 124, + "diamond-wide-open", + 224, + "diamond-wide-dot", + 324, + "diamond-wide-open-dot", + 25, + "hourglass", + 125, + "hourglass-open", + 26, + "bowtie", + 126, + "bowtie-open", + 27, + "circle-cross", + 127, + "circle-cross-open", + 28, + "circle-x", + 128, + "circle-x-open", + 29, + "square-cross", + 129, + "square-cross-open", + 30, + "square-x", + 130, + "square-x-open", + 31, + "diamond-cross", + 131, + "diamond-cross-open", + 32, + "diamond-x", + 132, + "diamond-x-open", + 33, + "cross-thin", + 133, + "cross-thin-open", + 34, + "x-thin", + 134, + "x-thin-open", + 35, + "asterisk", + 135, + "asterisk-open", + 36, + "hash", + 136, + "hash-open", + 236, + "hash-dot", + 336, + "hash-open-dot", + 37, + "y-up", + 137, + "y-up-open", + 38, + "y-down", + 138, + "y-down-open", + 39, + "y-left", + 139, + "y-left-open", + 40, + "y-right", + 140, + "y-right-open", + 41, + "line-ew", + 141, + "line-ew-open", + 42, + "line-ns", + 142, + "line-ns-open", + 43, + "line-ne", + 143, + "line-ne-open", + 44, + "line-nw", + 144, + "line-nw-open" + ], + "dflt": "circle", + "arrayOk": false, + "role": "style", + "editType": "plot", + "description": "Sets the marker symbol type. Adding 100 is equivalent to appending *-open* to a symbol name. Adding 200 is equivalent to appending *-dot* to a symbol name. Adding 300 is equivalent to appending *-open-dot* or *dot-open* to a symbol name." + }, + "opacity": { + "valType": "number", + "min": 0, + "max": 1, + "arrayOk": false, + "role": "style", + "editType": "style", + "description": "Sets the marker opacity.", + "dflt": 1 + }, + "size": { + "valType": "number", + "min": 0, + "dflt": 6, + "arrayOk": false, + "role": "style", + "editType": "calcIfAutorange", + "description": "Sets the marker size (in px)." + }, + "color": { + "valType": "color", + "arrayOk": false, + "role": "style", + "editType": "style", + "description": "Sets the marker color. It accepts either a specific color or an array of numbers that are mapped to the colorscale relative to the max and min values of the array or relative to `cmin` and `cmax` if set." + }, + "line": { + "color": { + "valType": "color", + "arrayOk": false, + "role": "style", + "editType": "style", + "description": "Sets the marker.line color. It accepts either a specific color or an array of numbers that are mapped to the colorscale relative to the max and min values of the array or relative to `cmin` and `cmax` if set.", + "dflt": "#444" + }, + "width": { + "valType": "number", + "min": 0, + "arrayOk": false, + "role": "style", + "editType": "style", + "description": "Sets the width (in px) of the lines bounding the marker points.", + "dflt": 0 + }, + "outliercolor": { + "valType": "color", + "role": "style", + "editType": "style", + "description": "Sets the border line color of the outlier sample points. Defaults to marker.color" + }, + "outlierwidth": { + "valType": "number", + "min": 0, + "dflt": 1, + "role": "style", + "editType": "style", + "description": "Sets the border line width (in px) of the outlier sample points." + }, + "editType": "style", + "role": "object" + }, + "editType": "plot", + "role": "object" + }, + "line": { + "color": { + "valType": "color", + "role": "style", + "editType": "style", + "description": "Sets the color of line bounding the box(es)." + }, + "width": { + "valType": "number", + "role": "style", + "min": 0, + "dflt": 2, + "editType": "style", + "description": "Sets the width (in px) of line bounding the box(es)." + }, + "editType": "plot", + "role": "object" + }, + "fillcolor": { + "valType": "color", + "role": "style", + "editType": "style", + "description": "Sets the fill color. Defaults to a half-transparent variant of the line color, marker color, or marker line color, whichever is available." + }, + "selected": { + "marker": { + "opacity": { + "valType": "number", + "min": 0, + "max": 1, + "role": "style", + "editType": "style", + "description": "Sets the marker opacity of selected points." + }, + "color": { + "valType": "color", + "role": "style", + "editType": "style", + "description": "Sets the marker color of selected points." + }, + "size": { + "valType": "number", + "min": 0, + "role": "style", + "editType": "style", + "description": "Sets the marker size of selected points." + }, + "editType": "style", + "role": "object" + }, + "editType": "style", + "role": "object" + }, + "unselected": { + "marker": { + "opacity": { + "valType": "number", + "min": 0, + "max": 1, + "role": "style", + "editType": "style", + "description": "Sets the marker opacity of unselected points, applied only when a selection exists." + }, + "color": { + "valType": "color", + "role": "style", + "editType": "style", + "description": "Sets the marker color of unselected points, applied only when a selection exists." + }, + "size": { + "valType": "number", + "min": 0, + "role": "style", + "editType": "style", + "description": "Sets the marker size of unselected points, applied only when a selection exists." + }, + "editType": "style", + "role": "object" + }, + "editType": "style", + "role": "object" + }, + "hoveron": { + "valType": "flaglist", + "flags": [ + "boxes", + "points" + ], + "dflt": "boxes+points", + "role": "info", + "editType": "style", + "description": "Do the hover effects highlight individual boxes or sample points or both?" + }, + "xcalendar": { + "valType": "enumerated", + "values": [ + "gregorian", + "chinese", + "coptic", + "discworld", + "ethiopian", + "hebrew", + "islamic", + "julian", + "mayan", + "nanakshahi", + "nepali", + "persian", + "jalali", + "taiwan", + "thai", + "ummalqura" + ], + "role": "info", + "editType": "calc", + "dflt": "gregorian", + "description": "Sets the calendar system to use with `x` date data." + }, + "ycalendar": { + "valType": "enumerated", + "values": [ + "gregorian", + "chinese", + "coptic", + "discworld", + "ethiopian", + "hebrew", + "islamic", + "julian", + "mayan", + "nanakshahi", + "nepali", + "persian", + "jalali", + "taiwan", + "thai", + "ummalqura" + ], + "role": "info", + "editType": "calc", + "dflt": "gregorian", + "description": "Sets the calendar system to use with `y` date data." + }, + "xaxis": { + "valType": "subplotid", + "role": "info", + "dflt": "x", + "editType": "calc+clearAxisTypes", + "description": "Sets a reference between this trace's x coordinates and a 2D cartesian x axis. If *x* (the default value), the x coordinates refer to `layout.xaxis`. If *x2*, the x coordinates refer to `layout.xaxis2`, and so on." + }, + "yaxis": { + "valType": "subplotid", + "role": "info", + "dflt": "y", + "editType": "calc+clearAxisTypes", + "description": "Sets a reference between this trace's y coordinates and a 2D cartesian y axis. If *y* (the default value), the y coordinates refer to `layout.yaxis`. If *y2*, the y coordinates refer to `layout.xaxis2`, and so on." + }, + "idssrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for ids .", + "editType": "none" + }, + "customdatasrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for customdata .", + "editType": "none" + }, + "hoverinfosrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for hoverinfo .", + "editType": "none" + }, + "ysrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for y .", + "editType": "none" + }, + "xsrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for x .", + "editType": "none" + }, + "textsrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for text .", + "editType": "none" + } + }, + "layoutAttributes": { + "boxmode": { + "valType": "enumerated", + "values": [ + "group", + "overlay" + ], + "dflt": "overlay", + "role": "info", + "editType": "calc", + "description": "Determines how boxes at the same location coordinate are displayed on the graph. If *group*, the boxes are plotted next to one another centered around the shared location. If *overlay*, the boxes are plotted over one another, you might need to set *opacity* to see them multiple boxes." + }, + "boxgap": { + "valType": "number", + "min": 0, + "max": 1, + "dflt": 0.3, + "role": "style", + "editType": "calc", + "description": "Sets the gap (in plot fraction) between boxes of adjacent location coordinates." + }, + "boxgroupgap": { + "valType": "number", + "min": 0, + "max": 1, + "dflt": 0.3, + "role": "style", + "editType": "calc", + "description": "Sets the gap (in plot fraction) between boxes of the same location coordinate." + } + } + }, + "bar": { + "meta": { + "description": "The data visualized by the span of the bars is set in `y` if `orientation` is set th *v* (the default) and the labels are set in `x`. By setting `orientation` to *h*, the roles are interchanged." + }, + "attributes": { + "type": "bar", + "visible": { + "valType": "enumerated", + "values": [ + true, + false, + "legendonly" + ], + "role": "info", + "dflt": true, + "editType": "calc", + "description": "Determines whether or not this trace is visible. If *legendonly*, the trace is not drawn, but can appear as a legend item (provided that the legend itself is visible)." + }, + "showlegend": { + "valType": "boolean", + "role": "info", + "dflt": true, + "editType": "style", + "description": "Determines whether or not an item corresponding to this trace is shown in the legend." + }, + "legendgroup": { + "valType": "string", + "role": "info", + "dflt": "", + "editType": "style", + "description": "Sets the legend group for this trace. Traces part of the same legend group hide/show at the same time when toggling legend items." + }, + "opacity": { + "valType": "number", + "role": "style", + "min": 0, + "max": 1, + "dflt": 1, + "editType": "style", + "description": "Sets the opacity of the trace." + }, + "name": { + "valType": "string", + "role": "info", + "editType": "style", + "description": "Sets the trace name. The trace name appear as the legend item and on hover." + }, + "uid": { + "valType": "string", + "role": "info", + "dflt": "", + "editType": "calc" + }, + "ids": { + "valType": "data_array", + "editType": "calc", + "description": "Assigns id labels to each datum. These ids for object constancy of data points during animation.", + "role": "data" + }, + "customdata": { + "valType": "data_array", + "editType": "calc", + "description": "Assigns extra data each datum. This may be useful when listening to hover, click and selection events. Note that, *scatter* traces also appends customdata items in the markers DOM elements", + "role": "data" + }, + "selectedpoints": { + "valType": "any", + "role": "info", + "editType": "calc", + "description": "Array containing integer indices of selected points. Has an effect only for traces that support selections. Note that an empty array means an empty selection where the `unselected` are turned on for all points, whereas, any other non-array values means no selection all where the `selected` and `unselected` styles have no effect." + }, + "hoverinfo": { + "valType": "flaglist", + "role": "info", + "flags": [ + "x", + "y", + "z", + "text", + "name" + ], + "extras": [ + "all", + "none", + "skip" + ], + "arrayOk": true, + "dflt": "all", + "editType": "none", + "description": "Determines which trace information appear on hover. If `none` or `skip` are set, no information is displayed upon hovering. But, if `none` is set, click and hover events are still fired." + }, + "hoverlabel": { + "bgcolor": { + "valType": "color", + "role": "style", + "arrayOk": true, + "editType": "none", + "description": "Sets the background color of the hover labels for this trace" + }, + "bordercolor": { + "valType": "color", + "role": "style", + "arrayOk": true, + "editType": "none", + "description": "Sets the border color of the hover labels for this trace." + }, + "font": { + "family": { + "valType": "string", + "role": "style", + "noBlank": true, + "strict": true, + "editType": "none", + "description": "HTML font family - the typeface that will be applied by the web browser. The web browser will only be able to apply a font if it is available on the system which it operates. Provide multiple font families, separated by commas, to indicate the preference in which to apply fonts if they aren't available on the system. The plotly service (at https://plot.ly or on-premise) generates images on a server, where only a select number of fonts are installed and supported. These include *Arial*, *Balto*, *Courier New*, *Droid Sans*,, *Droid Serif*, *Droid Sans Mono*, *Gravitas One*, *Old Standard TT*, *Open Sans*, *Overpass*, *PT Sans Narrow*, *Raleway*, *Times New Roman*.", + "arrayOk": true + }, + "size": { + "valType": "number", + "role": "style", + "min": 1, + "editType": "none", + "arrayOk": true + }, + "color": { + "valType": "color", + "role": "style", + "editType": "none", + "arrayOk": true + }, + "editType": "none", + "description": "Sets the font used in hover labels.", + "role": "object", + "familysrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for family .", + "editType": "none" + }, + "sizesrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for size .", + "editType": "none" + }, + "colorsrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for color .", + "editType": "none" + } + }, + "namelength": { + "valType": "integer", + "min": -1, + "arrayOk": true, + "role": "style", + "editType": "none", + "description": "Sets the length (in number of characters) of the trace name in the hover labels for this trace. -1 shows the whole name regardless of length. 0-3 shows the first 0-3 characters, and an integer >3 will show the whole name if it is less than that many characters, but if it is longer, will truncate to `namelength - 3` characters and add an ellipsis." + }, + "editType": "calc", + "role": "object", + "bgcolorsrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for bgcolor .", + "editType": "none" + }, + "bordercolorsrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for bordercolor .", + "editType": "none" + }, + "namelengthsrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for namelength .", + "editType": "none" + } + }, + "stream": { + "token": { + "valType": "string", + "noBlank": true, + "strict": true, + "role": "info", + "editType": "calc", + "description": "The stream id number links a data trace on a plot with a stream. See https://plot.ly/settings for more details." + }, + "maxpoints": { + "valType": "number", + "min": 0, + "max": 10000, + "dflt": 500, + "role": "info", + "editType": "calc", + "description": "Sets the maximum number of points to keep on the plots from an incoming stream. If `maxpoints` is set to *50*, only the newest 50 points will be displayed on the plot." + }, + "editType": "calc", + "role": "object" + }, + "x": { + "valType": "data_array", + "editType": "calc+clearAxisTypes", + "description": "Sets the x coordinates.", + "role": "data" + }, + "x0": { + "valType": "any", + "dflt": 0, + "role": "info", + "editType": "calc+clearAxisTypes", + "description": "Alternate to `x`. Builds a linear space of x coordinates. Use with `dx` where `x0` is the starting coordinate and `dx` the step." + }, + "dx": { + "valType": "number", + "dflt": 1, + "role": "info", + "editType": "calc", + "description": "Sets the x coordinate step. See `x0` for more info." + }, + "y": { + "valType": "data_array", + "editType": "calc+clearAxisTypes", + "description": "Sets the y coordinates.", + "role": "data" + }, + "y0": { + "valType": "any", + "dflt": 0, + "role": "info", + "editType": "calc+clearAxisTypes", + "description": "Alternate to `y`. Builds a linear space of y coordinates. Use with `dy` where `y0` is the starting coordinate and `dy` the step." + }, + "dy": { + "valType": "number", + "dflt": 1, + "role": "info", + "editType": "calc", + "description": "Sets the y coordinate step. See `y0` for more info." + }, + "text": { + "valType": "string", + "role": "info", + "dflt": "", + "arrayOk": true, + "editType": "calc", + "description": "Sets text elements associated with each (x,y) pair. If a single string, the same string appears over all the data points. If an array of string, the items are mapped in order to the this trace's (x,y) coordinates. If trace `hoverinfo` contains a *text* flag and *hovertext* is not set, these elements will be seen in the hover labels." + }, + "hovertext": { + "valType": "string", + "role": "info", + "dflt": "", + "arrayOk": true, + "editType": "style", + "description": "Sets hover text elements associated with each (x,y) pair. If a single string, the same string appears over all the data points. If an array of string, the items are mapped in order to the this trace's (x,y) coordinates. To be seen, trace `hoverinfo` must contain a *text* flag." + }, + "textposition": { + "valType": "enumerated", + "role": "info", + "values": [ + "inside", + "outside", + "auto", + "none" + ], + "dflt": "none", + "arrayOk": true, + "editType": "calc", + "description": "Specifies the location of the `text`. *inside* positions `text` inside, next to the bar end (rotated and scaled if needed). *outside* positions `text` outside, next to the bar end (scaled if needed). *auto* positions `text` inside or outside so that `text` size is maximized." + }, + "textfont": { + "family": { + "valType": "string", + "role": "style", + "noBlank": true, + "strict": true, + "editType": "calc", + "description": "HTML font family - the typeface that will be applied by the web browser. The web browser will only be able to apply a font if it is available on the system which it operates. Provide multiple font families, separated by commas, to indicate the preference in which to apply fonts if they aren't available on the system. The plotly service (at https://plot.ly or on-premise) generates images on a server, where only a select number of fonts are installed and supported. These include *Arial*, *Balto*, *Courier New*, *Droid Sans*,, *Droid Serif*, *Droid Sans Mono*, *Gravitas One*, *Old Standard TT*, *Open Sans*, *Overpass*, *PT Sans Narrow*, *Raleway*, *Times New Roman*.", + "arrayOk": true + }, + "size": { + "valType": "number", + "role": "style", + "min": 1, + "editType": "calc", + "arrayOk": true + }, + "color": { + "valType": "color", + "role": "style", + "editType": "calc", + "arrayOk": true + }, + "editType": "calc", + "description": "Sets the font used for `text`.", + "role": "object", + "familysrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for family .", + "editType": "none" + }, + "sizesrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for size .", + "editType": "none" + }, + "colorsrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for color .", + "editType": "none" + } + }, + "insidetextfont": { + "family": { + "valType": "string", + "role": "style", + "noBlank": true, + "strict": true, + "editType": "calc", + "description": "HTML font family - the typeface that will be applied by the web browser. The web browser will only be able to apply a font if it is available on the system which it operates. Provide multiple font families, separated by commas, to indicate the preference in which to apply fonts if they aren't available on the system. The plotly service (at https://plot.ly or on-premise) generates images on a server, where only a select number of fonts are installed and supported. These include *Arial*, *Balto*, *Courier New*, *Droid Sans*,, *Droid Serif*, *Droid Sans Mono*, *Gravitas One*, *Old Standard TT*, *Open Sans*, *Overpass*, *PT Sans Narrow*, *Raleway*, *Times New Roman*.", + "arrayOk": true + }, + "size": { + "valType": "number", + "role": "style", + "min": 1, + "editType": "calc", + "arrayOk": true + }, + "color": { + "valType": "color", + "role": "style", + "editType": "calc", + "arrayOk": true + }, + "editType": "calc", + "description": "Sets the font used for `text` lying inside the bar.", + "role": "object", + "familysrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for family .", + "editType": "none" + }, + "sizesrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for size .", + "editType": "none" + }, + "colorsrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for color .", + "editType": "none" + } + }, + "outsidetextfont": { + "family": { + "valType": "string", + "role": "style", + "noBlank": true, + "strict": true, + "editType": "calc", + "description": "HTML font family - the typeface that will be applied by the web browser. The web browser will only be able to apply a font if it is available on the system which it operates. Provide multiple font families, separated by commas, to indicate the preference in which to apply fonts if they aren't available on the system. The plotly service (at https://plot.ly or on-premise) generates images on a server, where only a select number of fonts are installed and supported. These include *Arial*, *Balto*, *Courier New*, *Droid Sans*,, *Droid Serif*, *Droid Sans Mono*, *Gravitas One*, *Old Standard TT*, *Open Sans*, *Overpass*, *PT Sans Narrow*, *Raleway*, *Times New Roman*.", + "arrayOk": true + }, + "size": { + "valType": "number", + "role": "style", + "min": 1, + "editType": "calc", + "arrayOk": true + }, + "color": { + "valType": "color", + "role": "style", + "editType": "calc", + "arrayOk": true + }, + "editType": "calc", + "description": "Sets the font used for `text` lying outside the bar.", + "role": "object", + "familysrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for family .", + "editType": "none" + }, + "sizesrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for size .", + "editType": "none" + }, + "colorsrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for color .", + "editType": "none" + } + }, + "constraintext": { + "valType": "enumerated", + "values": [ + "inside", + "outside", + "both", + "none" + ], + "role": "info", + "dflt": "both", + "editType": "calc", + "description": "Constrain the size of text inside or outside a bar to be no larger than the bar itself." + }, + "orientation": { + "valType": "enumerated", + "role": "info", + "values": [ + "v", + "h" + ], + "editType": "calc+clearAxisTypes", + "description": "Sets the orientation of the bars. With *v* (*h*), the value of the each bar spans along the vertical (horizontal)." + }, + "base": { + "valType": "any", + "dflt": null, + "arrayOk": true, + "role": "info", + "editType": "calc", + "description": "Sets where the bar base is drawn (in position axis units). In *stack* or *relative* barmode, traces that set *base* will be excluded and drawn in *overlay* mode instead." + }, + "offset": { + "valType": "number", + "dflt": null, + "arrayOk": true, + "role": "info", + "editType": "calc", + "description": "Shifts the position where the bar is drawn (in position axis units). In *group* barmode, traces that set *offset* will be excluded and drawn in *overlay* mode instead." + }, + "width": { + "valType": "number", + "dflt": null, + "min": 0, + "arrayOk": true, + "role": "info", + "editType": "calc", + "description": "Sets the bar width (in position axis units)." + }, + "marker": { + "line": { + "width": { + "valType": "number", + "min": 0, + "arrayOk": true, + "role": "style", + "editType": "style", + "description": "Sets the width (in px) of the lines bounding the marker points.", + "dflt": 0 + }, + "editType": "calc", + "color": { + "valType": "color", + "arrayOk": true, + "role": "style", + "editType": "style", + "description": "Sets the marker.line color. It accepts either a specific color or an array of numbers that are mapped to the colorscale relative to the max and min values of the array or relative to `cmin` and `cmax` if set." + }, + "colorscale": { + "valType": "colorscale", + "role": "style", + "editType": "calc", + "impliedEdits": { + "autocolorscale": false + }, + "description": "Sets the colorscale and only has an effect if `marker.line.color` is set to a numerical array. The colorscale must be an array containing arrays mapping a normalized value to an rgb, rgba, hex, hsl, hsv, or named color string. At minimum, a mapping for the lowest (0) and highest (1) values are required. For example, `[[0, 'rgb(0,0,255)', [1, 'rgb(255,0,0)']]`. To control the bounds of the colorscale in color space, use `marker.line.cmin` and `marker.line.cmax`. Alternatively, `colorscale` may be a palette name string of the following list: Greys, YlGnBu, Greens, YlOrRd, Bluered, RdBu, Reds, Blues, Picnic, Rainbow, Portland, Jet, Hot, Blackbody, Earth, Electric, Viridis" + }, + "cauto": { + "valType": "boolean", + "role": "info", + "dflt": true, + "editType": "calc", + "impliedEdits": {}, + "description": "Has an effect only if `marker.line.color` is set to a numerical array and `cmin`, `cmax` are set by the user. In this case, it controls whether the range of colors in `colorscale` is mapped to the range of values in the `color` array (`cauto: true`), or the `cmin`/`cmax` values (`cauto: false`). Defaults to `false` when `cmin`, `cmax` are set by the user." + }, + "cmax": { + "valType": "number", + "role": "info", + "dflt": null, + "editType": "plot", + "impliedEdits": { + "cauto": false + }, + "description": "Has an effect only if `marker.line.color` is set to a numerical array. Sets the upper bound of the color domain. Value should be associated to the `marker.line.color` array index, and if set, `marker.line.cmin` must be set as well." + }, + "cmin": { + "valType": "number", + "role": "info", + "dflt": null, + "editType": "plot", + "impliedEdits": { + "cauto": false + }, + "description": "Has an effect only if `marker.line.color` is set to a numerical array. Sets the lower bound of the color domain. Value should be associated to the `marker.line.color` array index, and if set, `marker.line.cmax` must be set as well." + }, + "autocolorscale": { + "valType": "boolean", + "role": "style", + "dflt": true, + "editType": "calc", + "impliedEdits": {}, + "description": "Has an effect only if `marker.line.color` is set to a numerical array. Determines whether the colorscale is a default palette (`autocolorscale: true`) or the palette determined by `marker.line.colorscale`. In case `colorscale` is unspecified or `autocolorscale` is true, the default palette will be chosen according to whether numbers in the `color` array are all positive, all negative or mixed." + }, + "reversescale": { + "valType": "boolean", + "role": "style", + "dflt": false, + "editType": "calc", + "description": "Has an effect only if `marker.line.color` is set to a numerical array. Reverses the color mapping if true (`cmin` will correspond to the last color in the array and `cmax` will correspond to the first color)." + }, + "role": "object", + "widthsrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for width .", + "editType": "none" + }, + "colorsrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for color .", + "editType": "none" + } + }, + "editType": "calc", + "color": { + "valType": "color", + "arrayOk": true, + "role": "style", + "editType": "style", + "description": "Sets the marker color. It accepts either a specific color or an array of numbers that are mapped to the colorscale relative to the max and min values of the array or relative to `cmin` and `cmax` if set." + }, + "colorscale": { + "valType": "colorscale", + "role": "style", + "editType": "calc", + "impliedEdits": { + "autocolorscale": false + }, + "description": "Sets the colorscale and only has an effect if `marker.color` is set to a numerical array. The colorscale must be an array containing arrays mapping a normalized value to an rgb, rgba, hex, hsl, hsv, or named color string. At minimum, a mapping for the lowest (0) and highest (1) values are required. For example, `[[0, 'rgb(0,0,255)', [1, 'rgb(255,0,0)']]`. To control the bounds of the colorscale in color space, use `marker.cmin` and `marker.cmax`. Alternatively, `colorscale` may be a palette name string of the following list: Greys, YlGnBu, Greens, YlOrRd, Bluered, RdBu, Reds, Blues, Picnic, Rainbow, Portland, Jet, Hot, Blackbody, Earth, Electric, Viridis" + }, + "cauto": { + "valType": "boolean", + "role": "info", + "dflt": true, + "editType": "calc", + "impliedEdits": {}, + "description": "Has an effect only if `marker.color` is set to a numerical array and `cmin`, `cmax` are set by the user. In this case, it controls whether the range of colors in `colorscale` is mapped to the range of values in the `color` array (`cauto: true`), or the `cmin`/`cmax` values (`cauto: false`). Defaults to `false` when `cmin`, `cmax` are set by the user." + }, + "cmax": { + "valType": "number", + "role": "info", + "dflt": null, + "editType": "plot", + "impliedEdits": { + "cauto": false + }, + "description": "Has an effect only if `marker.color` is set to a numerical array. Sets the upper bound of the color domain. Value should be associated to the `marker.color` array index, and if set, `marker.cmin` must be set as well." + }, + "cmin": { + "valType": "number", + "role": "info", + "dflt": null, + "editType": "plot", + "impliedEdits": { + "cauto": false + }, + "description": "Has an effect only if `marker.color` is set to a numerical array. Sets the lower bound of the color domain. Value should be associated to the `marker.color` array index, and if set, `marker.cmax` must be set as well." + }, + "autocolorscale": { + "valType": "boolean", + "role": "style", + "dflt": true, + "editType": "calc", + "impliedEdits": {}, + "description": "Has an effect only if `marker.color` is set to a numerical array. Determines whether the colorscale is a default palette (`autocolorscale: true`) or the palette determined by `marker.colorscale`. In case `colorscale` is unspecified or `autocolorscale` is true, the default palette will be chosen according to whether numbers in the `color` array are all positive, all negative or mixed." + }, + "reversescale": { + "valType": "boolean", + "role": "style", + "dflt": false, + "editType": "calc", + "description": "Has an effect only if `marker.color` is set to a numerical array. Reverses the color mapping if true (`cmin` will correspond to the last color in the array and `cmax` will correspond to the first color)." + }, + "showscale": { + "valType": "boolean", + "role": "info", + "dflt": false, + "editType": "calc", + "description": "Has an effect only if `marker.color` is set to a numerical array. Determines whether or not a colorbar is displayed." + }, + "colorbar": { + "thicknessmode": { + "valType": "enumerated", + "values": [ + "fraction", + "pixels" + ], + "role": "style", + "dflt": "pixels", + "description": "Determines whether this color bar's thickness (i.e. the measure in the constant color direction) is set in units of plot *fraction* or in *pixels*. Use `thickness` to set the value.", + "editType": "colorbars" + }, + "thickness": { + "valType": "number", + "role": "style", + "min": 0, + "dflt": 30, + "description": "Sets the thickness of the color bar This measure excludes the size of the padding, ticks and labels.", + "editType": "colorbars" + }, + "lenmode": { + "valType": "enumerated", + "values": [ + "fraction", + "pixels" + ], + "role": "info", + "dflt": "fraction", + "description": "Determines whether this color bar's length (i.e. the measure in the color variation direction) is set in units of plot *fraction* or in *pixels. Use `len` to set the value.", + "editType": "colorbars" + }, + "len": { + "valType": "number", + "min": 0, + "dflt": 1, + "role": "style", + "description": "Sets the length of the color bar This measure excludes the padding of both ends. That is, the color bar length is this length minus the padding on both ends.", + "editType": "colorbars" + }, + "x": { + "valType": "number", + "dflt": 1.02, + "min": -2, + "max": 3, + "role": "style", + "description": "Sets the x position of the color bar (in plot fraction).", + "editType": "colorbars" + }, + "xanchor": { + "valType": "enumerated", + "values": [ + "left", + "center", + "right" + ], + "dflt": "left", + "role": "style", + "description": "Sets this color bar's horizontal position anchor. This anchor binds the `x` position to the *left*, *center* or *right* of the color bar.", + "editType": "colorbars" + }, + "xpad": { + "valType": "number", + "role": "style", + "min": 0, + "dflt": 10, + "description": "Sets the amount of padding (in px) along the x direction.", + "editType": "colorbars" + }, + "y": { + "valType": "number", + "role": "style", + "dflt": 0.5, + "min": -2, + "max": 3, + "description": "Sets the y position of the color bar (in plot fraction).", + "editType": "colorbars" + }, + "yanchor": { + "valType": "enumerated", + "values": [ + "top", + "middle", + "bottom" + ], + "role": "style", + "dflt": "middle", + "description": "Sets this color bar's vertical position anchor This anchor binds the `y` position to the *top*, *middle* or *bottom* of the color bar.", + "editType": "colorbars" + }, + "ypad": { + "valType": "number", + "role": "style", + "min": 0, + "dflt": 10, + "description": "Sets the amount of padding (in px) along the y direction.", + "editType": "colorbars" + }, + "outlinecolor": { + "valType": "color", + "dflt": "#444", + "role": "style", + "editType": "colorbars", + "description": "Sets the axis line color." + }, + "outlinewidth": { + "valType": "number", + "min": 0, + "dflt": 1, + "role": "style", + "editType": "colorbars", + "description": "Sets the width (in px) of the axis line." + }, + "bordercolor": { + "valType": "color", + "dflt": "#444", + "role": "style", + "editType": "colorbars", + "description": "Sets the axis line color." + }, + "borderwidth": { + "valType": "number", + "role": "style", + "min": 0, + "dflt": 0, + "description": "Sets the width (in px) or the border enclosing this color bar.", + "editType": "colorbars" + }, + "bgcolor": { + "valType": "color", + "role": "style", + "dflt": "rgba(0,0,0,0)", + "description": "Sets the color of padded area.", + "editType": "colorbars" + }, + "tickmode": { + "valType": "enumerated", + "values": [ + "auto", + "linear", + "array" + ], + "role": "info", + "editType": "colorbars", + "impliedEdits": {}, + "description": "Sets the tick mode for this axis. If *auto*, the number of ticks is set via `nticks`. If *linear*, the placement of the ticks is determined by a starting position `tick0` and a tick step `dtick` (*linear* is the default value if `tick0` and `dtick` are provided). If *array*, the placement of the ticks is set via `tickvals` and the tick text is `ticktext`. (*array* is the default value if `tickvals` is provided)." + }, + "nticks": { + "valType": "integer", + "min": 0, + "dflt": 0, + "role": "style", + "editType": "colorbars", + "description": "Specifies the maximum number of ticks for the particular axis. The actual number of ticks will be chosen automatically to be less than or equal to `nticks`. Has an effect only if `tickmode` is set to *auto*." + }, + "tick0": { + "valType": "any", + "role": "style", + "editType": "colorbars", + "impliedEdits": { + "tickmode": "linear" + }, + "description": "Sets the placement of the first tick on this axis. Use with `dtick`. If the axis `type` is *log*, then you must take the log of your starting tick (e.g. to set the starting tick to 100, set the `tick0` to 2) except when `dtick`=*L* (see `dtick` for more info). If the axis `type` is *date*, it should be a date string, like date data. If the axis `type` is *category*, it should be a number, using the scale where each category is assigned a serial number from zero in the order it appears." + }, + "dtick": { + "valType": "any", + "role": "style", + "editType": "colorbars", + "impliedEdits": { + "tickmode": "linear" + }, + "description": "Sets the step in-between ticks on this axis. Use with `tick0`. Must be a positive number, or special strings available to *log* and *date* axes. If the axis `type` is *log*, then ticks are set every 10^(n*dtick) where n is the tick number. For example, to set a tick mark at 1, 10, 100, 1000, ... set dtick to 1. To set tick marks at 1, 100, 10000, ... set dtick to 2. To set tick marks at 1, 5, 25, 125, 625, 3125, ... set dtick to log_10(5), or 0.69897000433. *log* has several special values; *L*, where `f` is a positive number, gives ticks linearly spaced in value (but not position). For example `tick0` = 0.1, `dtick` = *L0.5* will put ticks at 0.1, 0.6, 1.1, 1.6 etc. To show powers of 10 plus small digits between, use *D1* (all digits) or *D2* (only 2 and 5). `tick0` is ignored for *D1* and *D2*. If the axis `type` is *date*, then you must convert the time to milliseconds. For example, to set the interval between ticks to one day, set `dtick` to 86400000.0. *date* also has special values *M* gives ticks spaced by a number of months. `n` must be a positive integer. To set ticks on the 15th of every third month, set `tick0` to *2000-01-15* and `dtick` to *M3*. To set ticks every 4 years, set `dtick` to *M48*" + }, + "tickvals": { + "valType": "data_array", + "editType": "colorbars", + "description": "Sets the values at which ticks on this axis appear. Only has an effect if `tickmode` is set to *array*. Used with `ticktext`.", + "role": "data" + }, + "ticktext": { + "valType": "data_array", + "editType": "colorbars", + "description": "Sets the text displayed at the ticks position via `tickvals`. Only has an effect if `tickmode` is set to *array*. Used with `tickvals`.", + "role": "data" + }, + "ticks": { + "valType": "enumerated", + "values": [ + "outside", + "inside", + "" + ], + "role": "style", + "editType": "colorbars", + "description": "Determines whether ticks are drawn or not. If **, this axis' ticks are not drawn. If *outside* (*inside*), this axis' are drawn outside (inside) the axis lines.", + "dflt": "" + }, + "ticklen": { + "valType": "number", + "min": 0, + "dflt": 5, + "role": "style", + "editType": "colorbars", + "description": "Sets the tick length (in px)." + }, + "tickwidth": { + "valType": "number", + "min": 0, + "dflt": 1, + "role": "style", + "editType": "colorbars", + "description": "Sets the tick width (in px)." + }, + "tickcolor": { + "valType": "color", + "dflt": "#444", + "role": "style", + "editType": "colorbars", + "description": "Sets the tick color." + }, + "showticklabels": { + "valType": "boolean", + "dflt": true, + "role": "style", + "editType": "colorbars", + "description": "Determines whether or not the tick labels are drawn." + }, + "tickfont": { + "family": { + "valType": "string", + "role": "style", + "noBlank": true, + "strict": true, + "description": "HTML font family - the typeface that will be applied by the web browser. The web browser will only be able to apply a font if it is available on the system which it operates. Provide multiple font families, separated by commas, to indicate the preference in which to apply fonts if they aren't available on the system. The plotly service (at https://plot.ly or on-premise) generates images on a server, where only a select number of fonts are installed and supported. These include *Arial*, *Balto*, *Courier New*, *Droid Sans*,, *Droid Serif*, *Droid Sans Mono*, *Gravitas One*, *Old Standard TT*, *Open Sans*, *Overpass*, *PT Sans Narrow*, *Raleway*, *Times New Roman*.", + "editType": "colorbars" + }, + "size": { + "valType": "number", + "role": "style", + "min": 1, + "editType": "colorbars" + }, + "color": { + "valType": "color", + "role": "style", + "editType": "colorbars" + }, + "description": "Sets the color bar's tick label font", + "editType": "colorbars", + "role": "object" + }, + "tickangle": { + "valType": "angle", + "dflt": "auto", + "role": "style", + "editType": "colorbars", + "description": "Sets the angle of the tick labels with respect to the horizontal. For example, a `tickangle` of -90 draws the tick labels vertically." + }, + "tickformat": { + "valType": "string", + "dflt": "", + "role": "style", + "editType": "colorbars", + "description": "Sets the tick label formatting rule using d3 formatting mini-languages which are very similar to those in Python. For numbers, see: https://github.com/d3/d3-format/blob/master/README.md#locale_format And for dates see: https://github.com/d3/d3-time-format/blob/master/README.md#locale_format We add one item to d3's date formatter: *%{n}f* for fractional seconds with n digits. For example, *2016-10-13 09:15:23.456* with tickformat *%H~%M~%S.%2f* would display *09~15~23.46*" + }, + "tickformatstops": { + "items": { + "tickformatstop": { + "dtickrange": { + "valType": "info_array", + "role": "info", + "items": [ + { + "valType": "any", + "editType": "colorbars" + }, + { + "valType": "any", + "editType": "colorbars" + } + ], + "editType": "colorbars", + "description": "range [*min*, *max*], where *min*, *max* - dtick values which describe some zoom level, it is possible to omit *min* or *max* value by passing *null*" + }, + "value": { + "valType": "string", + "dflt": "", + "role": "style", + "editType": "colorbars", + "description": "string - dtickformat for described zoom level, the same as *tickformat*" + }, + "editType": "colorbars", + "role": "object" + } + }, + "role": "object" + }, + "tickprefix": { + "valType": "string", + "dflt": "", + "role": "style", + "editType": "colorbars", + "description": "Sets a tick label prefix." + }, + "showtickprefix": { + "valType": "enumerated", + "values": [ + "all", + "first", + "last", + "none" + ], + "dflt": "all", + "role": "style", + "editType": "colorbars", + "description": "If *all*, all tick labels are displayed with a prefix. If *first*, only the first tick is displayed with a prefix. If *last*, only the last tick is displayed with a suffix. If *none*, tick prefixes are hidden." + }, + "ticksuffix": { + "valType": "string", + "dflt": "", + "role": "style", + "editType": "colorbars", + "description": "Sets a tick label suffix." + }, + "showticksuffix": { + "valType": "enumerated", + "values": [ + "all", + "first", + "last", + "none" + ], + "dflt": "all", + "role": "style", + "editType": "colorbars", + "description": "Same as `showtickprefix` but for tick suffixes." + }, + "separatethousands": { + "valType": "boolean", + "dflt": false, + "role": "style", + "editType": "colorbars", + "description": "If \"true\", even 4-digit integers are separated" + }, + "exponentformat": { + "valType": "enumerated", + "values": [ + "none", + "e", + "E", + "power", + "SI", + "B" + ], + "dflt": "B", + "role": "style", + "editType": "colorbars", + "description": "Determines a formatting rule for the tick exponents. For example, consider the number 1,000,000,000. If *none*, it appears as 1,000,000,000. If *e*, 1e+9. If *E*, 1E+9. If *power*, 1x10^9 (with 9 in a super script). If *SI*, 1G. If *B*, 1B." + }, + "showexponent": { + "valType": "enumerated", + "values": [ + "all", + "first", + "last", + "none" + ], + "dflt": "all", + "role": "style", + "editType": "colorbars", + "description": "If *all*, all exponents are shown besides their significands. If *first*, only the exponent of the first tick is shown. If *last*, only the exponent of the last tick is shown. If *none*, no exponents appear." + }, + "title": { + "valType": "string", + "role": "info", + "dflt": "Click to enter colorscale title", + "description": "Sets the title of the color bar.", + "editType": "colorbars" + }, + "titlefont": { + "family": { + "valType": "string", + "role": "style", + "noBlank": true, + "strict": true, + "description": "HTML font family - the typeface that will be applied by the web browser. The web browser will only be able to apply a font if it is available on the system which it operates. Provide multiple font families, separated by commas, to indicate the preference in which to apply fonts if they aren't available on the system. The plotly service (at https://plot.ly or on-premise) generates images on a server, where only a select number of fonts are installed and supported. These include *Arial*, *Balto*, *Courier New*, *Droid Sans*,, *Droid Serif*, *Droid Sans Mono*, *Gravitas One*, *Old Standard TT*, *Open Sans*, *Overpass*, *PT Sans Narrow*, *Raleway*, *Times New Roman*.", + "editType": "colorbars" + }, + "size": { + "valType": "number", + "role": "style", + "min": 1, + "editType": "colorbars" + }, + "color": { + "valType": "color", + "role": "style", + "editType": "colorbars" + }, + "description": "Sets this color bar's title font.", + "editType": "colorbars", + "role": "object" + }, + "titleside": { + "valType": "enumerated", + "values": [ + "right", + "top", + "bottom" + ], + "role": "style", + "dflt": "top", + "description": "Determines the location of the colorbar title with respect to the color bar.", + "editType": "colorbars" + }, + "editType": "colorbars", + "role": "object", + "tickvalssrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for tickvals .", + "editType": "none" + }, + "ticktextsrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for ticktext .", + "editType": "none" + } + }, + "opacity": { + "valType": "number", + "arrayOk": true, + "dflt": 1, + "min": 0, + "max": 1, + "role": "style", + "editType": "style", + "description": "Sets the opacity of the bars." + }, + "role": "object", + "colorsrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for color .", + "editType": "none" + }, + "opacitysrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for opacity .", + "editType": "none" + } + }, + "selected": { + "marker": { + "opacity": { + "valType": "number", + "min": 0, + "max": 1, + "role": "style", + "editType": "style", + "description": "Sets the marker opacity of selected points." + }, + "color": { + "valType": "color", + "role": "style", + "editType": "style", + "description": "Sets the marker color of selected points." + }, + "editType": "style", + "role": "object" + }, + "textfont": { + "color": { + "valType": "color", + "role": "style", + "editType": "style", + "description": "Sets the text font color of selected points." + }, + "editType": "style", + "role": "object" + }, + "editType": "style", + "role": "object" + }, + "unselected": { + "marker": { + "opacity": { + "valType": "number", + "min": 0, + "max": 1, + "role": "style", + "editType": "style", + "description": "Sets the marker opacity of unselected points, applied only when a selection exists." + }, + "color": { + "valType": "color", + "role": "style", + "editType": "style", + "description": "Sets the marker color of unselected points, applied only when a selection exists." + }, + "editType": "style", + "role": "object" + }, + "textfont": { + "color": { + "valType": "color", + "role": "style", + "editType": "style", + "description": "Sets the text font color of unselected points, applied only when a selection exists." + }, + "editType": "style", + "role": "object" + }, + "editType": "style", + "role": "object" + }, + "r": { + "valType": "data_array", + "editType": "calc", + "description": "For polar chart only.Sets the radial coordinates.", + "role": "data" + }, + "t": { + "valType": "data_array", + "editType": "calc", + "description": "For polar chart only.Sets the angular coordinates.", + "role": "data" + }, + "error_y": { + "visible": { + "valType": "boolean", + "role": "info", + "editType": "calc", + "description": "Determines whether or not this set of error bars is visible." + }, + "type": { + "valType": "enumerated", + "values": [ + "percent", + "constant", + "sqrt", + "data" + ], + "role": "info", + "editType": "calc", + "description": "Determines the rule used to generate the error bars. If *constant`, the bar lengths are of a constant value. Set this constant in `value`. If *percent*, the bar lengths correspond to a percentage of underlying data. Set this percentage in `value`. If *sqrt*, the bar lengths correspond to the sqaure of the underlying data. If *array*, the bar lengths are set with data set `array`." + }, + "symmetric": { + "valType": "boolean", + "role": "info", + "editType": "calc", + "description": "Determines whether or not the error bars have the same length in both direction (top/bottom for vertical bars, left/right for horizontal bars." + }, + "array": { + "valType": "data_array", + "editType": "calc", + "description": "Sets the data corresponding the length of each error bar. Values are plotted relative to the underlying data.", + "role": "data" + }, + "arrayminus": { + "valType": "data_array", + "editType": "calc", + "description": "Sets the data corresponding the length of each error bar in the bottom (left) direction for vertical (horizontal) bars Values are plotted relative to the underlying data.", + "role": "data" + }, + "value": { + "valType": "number", + "min": 0, + "dflt": 10, + "role": "info", + "editType": "calc", + "description": "Sets the value of either the percentage (if `type` is set to *percent*) or the constant (if `type` is set to *constant*) corresponding to the lengths of the error bars." + }, + "valueminus": { + "valType": "number", + "min": 0, + "dflt": 10, + "role": "info", + "editType": "calc", + "description": "Sets the value of either the percentage (if `type` is set to *percent*) or the constant (if `type` is set to *constant*) corresponding to the lengths of the error bars in the bottom (left) direction for vertical (horizontal) bars" + }, + "traceref": { + "valType": "integer", + "min": 0, + "dflt": 0, + "role": "info", + "editType": "style" + }, + "tracerefminus": { + "valType": "integer", + "min": 0, + "dflt": 0, + "role": "info", + "editType": "style" + }, + "copy_ystyle": { + "valType": "boolean", + "role": "style", + "editType": "plot" + }, + "copy_zstyle": { + "valType": "boolean", + "role": "style", + "editType": "style" + }, + "color": { + "valType": "color", + "role": "style", + "editType": "style", + "description": "Sets the stoke color of the error bars." + }, + "thickness": { + "valType": "number", + "min": 0, + "dflt": 2, + "role": "style", + "editType": "style", + "description": "Sets the thickness (in px) of the error bars." + }, + "width": { + "valType": "number", + "min": 0, + "role": "style", + "editType": "plot", + "description": "Sets the width (in px) of the cross-bar at both ends of the error bars." + }, + "editType": "calc", + "_deprecated": { + "opacity": { + "valType": "number", + "role": "style", + "editType": "style", + "description": "Obsolete. Use the alpha channel in error bar `color` to set the opacity." + } + }, + "role": "object", + "arraysrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for array .", + "editType": "none" + }, + "arrayminussrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for arrayminus .", + "editType": "none" + } + }, + "error_x": { + "visible": { + "valType": "boolean", + "role": "info", + "editType": "calc", + "description": "Determines whether or not this set of error bars is visible." + }, + "type": { + "valType": "enumerated", + "values": [ + "percent", + "constant", + "sqrt", + "data" + ], + "role": "info", + "editType": "calc", + "description": "Determines the rule used to generate the error bars. If *constant`, the bar lengths are of a constant value. Set this constant in `value`. If *percent*, the bar lengths correspond to a percentage of underlying data. Set this percentage in `value`. If *sqrt*, the bar lengths correspond to the sqaure of the underlying data. If *array*, the bar lengths are set with data set `array`." + }, + "symmetric": { + "valType": "boolean", + "role": "info", + "editType": "calc", + "description": "Determines whether or not the error bars have the same length in both direction (top/bottom for vertical bars, left/right for horizontal bars." + }, + "array": { + "valType": "data_array", + "editType": "calc", + "description": "Sets the data corresponding the length of each error bar. Values are plotted relative to the underlying data.", + "role": "data" + }, + "arrayminus": { + "valType": "data_array", + "editType": "calc", + "description": "Sets the data corresponding the length of each error bar in the bottom (left) direction for vertical (horizontal) bars Values are plotted relative to the underlying data.", + "role": "data" + }, + "value": { + "valType": "number", + "min": 0, + "dflt": 10, + "role": "info", + "editType": "calc", + "description": "Sets the value of either the percentage (if `type` is set to *percent*) or the constant (if `type` is set to *constant*) corresponding to the lengths of the error bars." + }, + "valueminus": { + "valType": "number", + "min": 0, + "dflt": 10, + "role": "info", + "editType": "calc", + "description": "Sets the value of either the percentage (if `type` is set to *percent*) or the constant (if `type` is set to *constant*) corresponding to the lengths of the error bars in the bottom (left) direction for vertical (horizontal) bars" + }, + "traceref": { + "valType": "integer", + "min": 0, + "dflt": 0, + "role": "info", + "editType": "style" + }, + "tracerefminus": { + "valType": "integer", + "min": 0, + "dflt": 0, + "role": "info", + "editType": "style" + }, + "copy_ystyle": { + "valType": "boolean", + "role": "style", + "editType": "plot" + }, + "copy_zstyle": { + "valType": "boolean", + "role": "style", + "editType": "style" + }, + "color": { + "valType": "color", + "role": "style", + "editType": "style", + "description": "Sets the stoke color of the error bars." + }, + "thickness": { + "valType": "number", + "min": 0, + "dflt": 2, + "role": "style", + "editType": "style", + "description": "Sets the thickness (in px) of the error bars." + }, + "width": { + "valType": "number", + "min": 0, + "role": "style", + "editType": "plot", + "description": "Sets the width (in px) of the cross-bar at both ends of the error bars." + }, + "editType": "calc", + "_deprecated": { + "opacity": { + "valType": "number", + "role": "style", + "editType": "style", + "description": "Obsolete. Use the alpha channel in error bar `color` to set the opacity." + } + }, + "role": "object", + "arraysrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for array .", + "editType": "none" + }, + "arrayminussrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for arrayminus .", + "editType": "none" + } + }, + "_deprecated": { + "bardir": { + "valType": "enumerated", + "role": "info", + "editType": "calc", + "values": [ + "v", + "h" + ], + "description": "Renamed to `orientation`." + } + }, + "xcalendar": { + "valType": "enumerated", + "values": [ + "gregorian", + "chinese", + "coptic", + "discworld", + "ethiopian", + "hebrew", + "islamic", + "julian", + "mayan", + "nanakshahi", + "nepali", + "persian", + "jalali", + "taiwan", + "thai", + "ummalqura" + ], + "role": "info", + "editType": "calc", + "dflt": "gregorian", + "description": "Sets the calendar system to use with `x` date data." + }, + "ycalendar": { + "valType": "enumerated", + "values": [ + "gregorian", + "chinese", + "coptic", + "discworld", + "ethiopian", + "hebrew", + "islamic", + "julian", + "mayan", + "nanakshahi", + "nepali", + "persian", + "jalali", + "taiwan", + "thai", + "ummalqura" + ], + "role": "info", + "editType": "calc", + "dflt": "gregorian", + "description": "Sets the calendar system to use with `y` date data." + }, + "xaxis": { + "valType": "subplotid", + "role": "info", + "dflt": "x", + "editType": "calc+clearAxisTypes", + "description": "Sets a reference between this trace's x coordinates and a 2D cartesian x axis. If *x* (the default value), the x coordinates refer to `layout.xaxis`. If *x2*, the x coordinates refer to `layout.xaxis2`, and so on." + }, + "yaxis": { + "valType": "subplotid", + "role": "info", + "dflt": "y", + "editType": "calc+clearAxisTypes", + "description": "Sets a reference between this trace's y coordinates and a 2D cartesian y axis. If *y* (the default value), the y coordinates refer to `layout.yaxis`. If *y2*, the y coordinates refer to `layout.xaxis2`, and so on." + }, + "idssrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for ids .", + "editType": "none" + }, + "customdatasrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for customdata .", + "editType": "none" + }, + "hoverinfosrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for hoverinfo .", + "editType": "none" + }, + "xsrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for x .", + "editType": "none" + }, + "ysrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for y .", + "editType": "none" + }, + "textsrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for text .", + "editType": "none" + }, + "hovertextsrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for hovertext .", + "editType": "none" + }, + "textpositionsrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for textposition .", + "editType": "none" + }, + "basesrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for base .", + "editType": "none" + }, + "offsetsrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for offset .", + "editType": "none" + }, + "widthsrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for width .", + "editType": "none" + }, + "rsrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for r .", + "editType": "none" + }, + "tsrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for t .", + "editType": "none" + } + }, + "layoutAttributes": { + "barmode": { + "valType": "enumerated", + "values": [ + "stack", + "group", + "overlay", + "relative" + ], + "dflt": "group", + "role": "info", + "editType": "calc", + "description": "Determines how bars at the same location coordinate are displayed on the graph. With *stack*, the bars are stacked on top of one another With *relative*, the bars are stacked on top of one another, with negative values below the axis, positive values above With *group*, the bars are plotted next to one another centered around the shared location. With *overlay*, the bars are plotted over one another, you might need to an *opacity* to see multiple bars." + }, + "barnorm": { + "valType": "enumerated", + "values": [ + "", + "fraction", + "percent" + ], + "dflt": "", + "role": "info", + "editType": "calc", + "description": "Sets the normalization for bar traces on the graph. With *fraction*, the value of each bar is divide by the sum of the values at the location coordinate. With *percent*, the results form *fraction* are presented in percents." + }, + "bargap": { + "valType": "number", + "min": 0, + "max": 1, + "role": "style", + "editType": "calc", + "description": "Sets the gap (in plot fraction) between bars of adjacent location coordinates." + }, + "bargroupgap": { + "valType": "number", + "min": 0, + "max": 1, + "dflt": 0, + "role": "style", + "editType": "calc", + "description": "Sets the gap (in plot fraction) between bars of the same location coordinate." + } + } + }, + "heatmap": { + "meta": { + "description": "The data that describes the heatmap value-to-color mapping is set in `z`. Data in `z` can either be a {2D array} of values (ragged or not) or a 1D array of values. In the case where `z` is a {2D array}, say that `z` has N rows and M columns. Then, by default, the resulting heatmap will have N partitions along the y axis and M partitions along the x axis. In other words, the i-th row/ j-th column cell in `z` is mapped to the i-th partition of the y axis (starting from the bottom of the plot) and the j-th partition of the x-axis (starting from the left of the plot). This behavior can be flipped by using `transpose`. Moreover, `x` (`y`) can be provided with M or M+1 (N or N+1) elements. If M (N), then the coordinates correspond to the center of the heatmap cells and the cells have equal width. If M+1 (N+1), then the coordinates correspond to the edges of the heatmap cells. In the case where `z` is a 1D {array}, the x and y coordinates must be provided in `x` and `y` respectively to form data triplets." + }, + "attributes": { + "type": "heatmap", + "visible": { + "valType": "enumerated", + "values": [ + true, + false, + "legendonly" + ], + "role": "info", + "dflt": true, + "editType": "calc", + "description": "Determines whether or not this trace is visible. If *legendonly*, the trace is not drawn, but can appear as a legend item (provided that the legend itself is visible)." + }, + "showlegend": { + "valType": "boolean", + "role": "info", + "dflt": true, + "editType": "style", + "description": "Determines whether or not an item corresponding to this trace is shown in the legend." + }, + "legendgroup": { + "valType": "string", + "role": "info", + "dflt": "", + "editType": "style", + "description": "Sets the legend group for this trace. Traces part of the same legend group hide/show at the same time when toggling legend items." + }, + "opacity": { + "valType": "number", + "role": "style", + "min": 0, + "max": 1, + "dflt": 1, + "editType": "style", + "description": "Sets the opacity of the trace." + }, + "name": { + "valType": "string", + "role": "info", + "editType": "style", + "description": "Sets the trace name. The trace name appear as the legend item and on hover." + }, + "uid": { + "valType": "string", + "role": "info", + "dflt": "", + "editType": "calc" + }, + "ids": { + "valType": "data_array", + "editType": "calc", + "description": "Assigns id labels to each datum. These ids for object constancy of data points during animation.", + "role": "data" + }, + "customdata": { + "valType": "data_array", + "editType": "calc", + "description": "Assigns extra data each datum. This may be useful when listening to hover, click and selection events. Note that, *scatter* traces also appends customdata items in the markers DOM elements", + "role": "data" + }, + "selectedpoints": { + "valType": "any", + "role": "info", + "editType": "calc", + "description": "Array containing integer indices of selected points. Has an effect only for traces that support selections. Note that an empty array means an empty selection where the `unselected` are turned on for all points, whereas, any other non-array values means no selection all where the `selected` and `unselected` styles have no effect." + }, + "hoverinfo": { + "valType": "flaglist", + "role": "info", + "flags": [ + "x", + "y", + "z", + "text", + "name" + ], + "extras": [ + "all", + "none", + "skip" + ], + "arrayOk": true, + "dflt": "all", + "editType": "none", + "description": "Determines which trace information appear on hover. If `none` or `skip` are set, no information is displayed upon hovering. But, if `none` is set, click and hover events are still fired." + }, + "hoverlabel": { + "bgcolor": { + "valType": "color", + "role": "style", + "arrayOk": true, + "editType": "none", + "description": "Sets the background color of the hover labels for this trace" + }, + "bordercolor": { + "valType": "color", + "role": "style", + "arrayOk": true, + "editType": "none", + "description": "Sets the border color of the hover labels for this trace." + }, + "font": { + "family": { + "valType": "string", + "role": "style", + "noBlank": true, + "strict": true, + "editType": "none", + "description": "HTML font family - the typeface that will be applied by the web browser. The web browser will only be able to apply a font if it is available on the system which it operates. Provide multiple font families, separated by commas, to indicate the preference in which to apply fonts if they aren't available on the system. The plotly service (at https://plot.ly or on-premise) generates images on a server, where only a select number of fonts are installed and supported. These include *Arial*, *Balto*, *Courier New*, *Droid Sans*,, *Droid Serif*, *Droid Sans Mono*, *Gravitas One*, *Old Standard TT*, *Open Sans*, *Overpass*, *PT Sans Narrow*, *Raleway*, *Times New Roman*.", + "arrayOk": true + }, + "size": { + "valType": "number", + "role": "style", + "min": 1, + "editType": "none", + "arrayOk": true + }, + "color": { + "valType": "color", + "role": "style", + "editType": "none", + "arrayOk": true + }, + "editType": "none", + "description": "Sets the font used in hover labels.", + "role": "object", + "familysrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for family .", + "editType": "none" + }, + "sizesrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for size .", + "editType": "none" + }, + "colorsrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for color .", + "editType": "none" + } + }, + "namelength": { + "valType": "integer", + "min": -1, + "arrayOk": true, + "role": "style", + "editType": "none", + "description": "Sets the length (in number of characters) of the trace name in the hover labels for this trace. -1 shows the whole name regardless of length. 0-3 shows the first 0-3 characters, and an integer >3 will show the whole name if it is less than that many characters, but if it is longer, will truncate to `namelength - 3` characters and add an ellipsis." + }, + "editType": "calc", + "role": "object", + "bgcolorsrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for bgcolor .", + "editType": "none" + }, + "bordercolorsrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for bordercolor .", + "editType": "none" + }, + "namelengthsrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for namelength .", + "editType": "none" + } + }, + "stream": { + "token": { + "valType": "string", + "noBlank": true, + "strict": true, + "role": "info", + "editType": "calc", + "description": "The stream id number links a data trace on a plot with a stream. See https://plot.ly/settings for more details." + }, + "maxpoints": { + "valType": "number", + "min": 0, + "max": 10000, + "dflt": 500, + "role": "info", + "editType": "calc", + "description": "Sets the maximum number of points to keep on the plots from an incoming stream. If `maxpoints` is set to *50*, only the newest 50 points will be displayed on the plot." + }, + "editType": "calc", + "role": "object" + }, + "z": { + "valType": "data_array", + "editType": "calc", + "description": "Sets the z data.", + "role": "data" + }, + "x": { + "valType": "data_array", + "editType": "calc+clearAxisTypes", + "description": "Sets the x coordinates.", + "impliedEdits": { + "xtype": "array" + }, + "role": "data" + }, + "x0": { + "valType": "any", + "dflt": 0, + "role": "info", + "editType": "calc+clearAxisTypes", + "description": "Alternate to `x`. Builds a linear space of x coordinates. Use with `dx` where `x0` is the starting coordinate and `dx` the step.", + "impliedEdits": { + "xtype": "scaled" + } + }, + "dx": { + "valType": "number", + "dflt": 1, + "role": "info", + "editType": "calc", + "description": "Sets the x coordinate step. See `x0` for more info.", + "impliedEdits": { + "xtype": "scaled" + } + }, + "y": { + "valType": "data_array", + "editType": "calc+clearAxisTypes", + "description": "Sets the y coordinates.", + "impliedEdits": { + "ytype": "array" + }, + "role": "data" + }, + "y0": { + "valType": "any", + "dflt": 0, + "role": "info", + "editType": "calc+clearAxisTypes", + "description": "Alternate to `y`. Builds a linear space of y coordinates. Use with `dy` where `y0` is the starting coordinate and `dy` the step.", + "impliedEdits": { + "ytype": "scaled" + } + }, + "dy": { + "valType": "number", + "dflt": 1, + "role": "info", + "editType": "calc", + "description": "Sets the y coordinate step. See `y0` for more info.", + "impliedEdits": { + "ytype": "scaled" + } + }, + "text": { + "valType": "data_array", + "editType": "calc", + "description": "Sets the text elements associated with each z value.", + "role": "data" + }, + "transpose": { + "valType": "boolean", + "dflt": false, + "role": "info", + "editType": "calc", + "description": "Transposes the z data." + }, + "xtype": { + "valType": "enumerated", + "values": [ + "array", + "scaled" + ], + "role": "info", + "editType": "calc+clearAxisTypes", + "description": "If *array*, the heatmap's x coordinates are given by *x* (the default behavior when `x` is provided). If *scaled*, the heatmap's x coordinates are given by *x0* and *dx* (the default behavior when `x` is not provided)." + }, + "ytype": { + "valType": "enumerated", + "values": [ + "array", + "scaled" + ], + "role": "info", + "editType": "calc+clearAxisTypes", + "description": "If *array*, the heatmap's y coordinates are given by *y* (the default behavior when `y` is provided) If *scaled*, the heatmap's y coordinates are given by *y0* and *dy* (the default behavior when `y` is not provided)" + }, + "zsmooth": { + "valType": "enumerated", + "values": [ + "fast", + "best", + false + ], + "dflt": false, + "role": "style", + "editType": "calc", + "description": "Picks a smoothing algorithm use to smooth `z` data." + }, + "connectgaps": { + "valType": "boolean", + "dflt": false, + "role": "info", + "editType": "calc", + "description": "Determines whether or not gaps (i.e. {nan} or missing values) in the `z` data are filled in." + }, + "xgap": { + "valType": "number", + "dflt": 0, + "min": 0, + "role": "style", + "editType": "plot", + "description": "Sets the horizontal gap (in pixels) between bricks." + }, + "ygap": { + "valType": "number", + "dflt": 0, + "min": 0, + "role": "style", + "editType": "plot", + "description": "Sets the vertical gap (in pixels) between bricks." + }, + "zhoverformat": { + "valType": "string", + "dflt": "", + "role": "style", + "editType": "none", + "description": "Sets the hover text formatting rule using d3 formatting mini-languages which are very similar to those in Python. See: https://github.com/d3/d3-format/blob/master/README.md#locale_format" + }, + "zauto": { + "valType": "boolean", + "role": "info", + "dflt": true, + "editType": "calc", + "impliedEdits": {}, + "description": "Determines the whether or not the color domain is computed with respect to the input data." + }, + "zmin": { + "valType": "number", + "role": "info", + "dflt": null, + "editType": "plot", + "impliedEdits": { + "zauto": false + }, + "description": "Sets the lower bound of color domain." + }, + "zmax": { + "valType": "number", + "role": "info", + "dflt": null, + "editType": "plot", + "impliedEdits": { + "zauto": false + }, + "description": "Sets the upper bound of color domain." + }, + "colorscale": { + "valType": "colorscale", + "role": "style", + "editType": "calc", + "impliedEdits": { + "autocolorscale": false + }, + "description": "Sets the colorscale. The colorscale must be an array containing arrays mapping a normalized value to an rgb, rgba, hex, hsl, hsv, or named color string. At minimum, a mapping for the lowest (0) and highest (1) values are required. For example, `[[0, 'rgb(0,0,255)', [1, 'rgb(255,0,0)']]`. To control the bounds of the colorscale in z space, use zmin and zmax" + }, + "autocolorscale": { + "valType": "boolean", + "role": "style", + "dflt": false, + "editType": "calc", + "impliedEdits": {}, + "description": "Determines whether or not the colorscale is picked using the sign of the input z values." + }, + "reversescale": { + "valType": "boolean", + "role": "style", + "dflt": false, + "editType": "calc", + "description": "Reverses the colorscale." + }, + "showscale": { + "valType": "boolean", + "role": "info", + "dflt": true, + "editType": "calc", + "description": "Determines whether or not a colorbar is displayed for this trace." + }, + "colorbar": { + "thicknessmode": { + "valType": "enumerated", + "values": [ + "fraction", + "pixels" + ], + "role": "style", + "dflt": "pixels", + "description": "Determines whether this color bar's thickness (i.e. the measure in the constant color direction) is set in units of plot *fraction* or in *pixels*. Use `thickness` to set the value.", + "editType": "colorbars" + }, + "thickness": { + "valType": "number", + "role": "style", + "min": 0, + "dflt": 30, + "description": "Sets the thickness of the color bar This measure excludes the size of the padding, ticks and labels.", + "editType": "colorbars" + }, + "lenmode": { + "valType": "enumerated", + "values": [ + "fraction", + "pixels" + ], + "role": "info", + "dflt": "fraction", + "description": "Determines whether this color bar's length (i.e. the measure in the color variation direction) is set in units of plot *fraction* or in *pixels. Use `len` to set the value.", + "editType": "colorbars" + }, + "len": { + "valType": "number", + "min": 0, + "dflt": 1, + "role": "style", + "description": "Sets the length of the color bar This measure excludes the padding of both ends. That is, the color bar length is this length minus the padding on both ends.", + "editType": "colorbars" + }, + "x": { + "valType": "number", + "dflt": 1.02, + "min": -2, + "max": 3, + "role": "style", + "description": "Sets the x position of the color bar (in plot fraction).", + "editType": "colorbars" + }, + "xanchor": { + "valType": "enumerated", + "values": [ + "left", + "center", + "right" + ], + "dflt": "left", + "role": "style", + "description": "Sets this color bar's horizontal position anchor. This anchor binds the `x` position to the *left*, *center* or *right* of the color bar.", + "editType": "colorbars" + }, + "xpad": { + "valType": "number", + "role": "style", + "min": 0, + "dflt": 10, + "description": "Sets the amount of padding (in px) along the x direction.", + "editType": "colorbars" + }, + "y": { + "valType": "number", + "role": "style", + "dflt": 0.5, + "min": -2, + "max": 3, + "description": "Sets the y position of the color bar (in plot fraction).", + "editType": "colorbars" + }, + "yanchor": { + "valType": "enumerated", + "values": [ + "top", + "middle", + "bottom" + ], + "role": "style", + "dflt": "middle", + "description": "Sets this color bar's vertical position anchor This anchor binds the `y` position to the *top*, *middle* or *bottom* of the color bar.", + "editType": "colorbars" + }, + "ypad": { + "valType": "number", + "role": "style", + "min": 0, + "dflt": 10, + "description": "Sets the amount of padding (in px) along the y direction.", + "editType": "colorbars" + }, + "outlinecolor": { + "valType": "color", + "dflt": "#444", + "role": "style", + "editType": "colorbars", + "description": "Sets the axis line color." + }, + "outlinewidth": { + "valType": "number", + "min": 0, + "dflt": 1, + "role": "style", + "editType": "colorbars", + "description": "Sets the width (in px) of the axis line." + }, + "bordercolor": { + "valType": "color", + "dflt": "#444", + "role": "style", + "editType": "colorbars", + "description": "Sets the axis line color." + }, + "borderwidth": { + "valType": "number", + "role": "style", + "min": 0, + "dflt": 0, + "description": "Sets the width (in px) or the border enclosing this color bar.", + "editType": "colorbars" + }, + "bgcolor": { + "valType": "color", + "role": "style", + "dflt": "rgba(0,0,0,0)", + "description": "Sets the color of padded area.", + "editType": "colorbars" + }, + "tickmode": { + "valType": "enumerated", + "values": [ + "auto", + "linear", + "array" + ], + "role": "info", + "editType": "colorbars", + "impliedEdits": {}, + "description": "Sets the tick mode for this axis. If *auto*, the number of ticks is set via `nticks`. If *linear*, the placement of the ticks is determined by a starting position `tick0` and a tick step `dtick` (*linear* is the default value if `tick0` and `dtick` are provided). If *array*, the placement of the ticks is set via `tickvals` and the tick text is `ticktext`. (*array* is the default value if `tickvals` is provided)." + }, + "nticks": { + "valType": "integer", + "min": 0, + "dflt": 0, + "role": "style", + "editType": "colorbars", + "description": "Specifies the maximum number of ticks for the particular axis. The actual number of ticks will be chosen automatically to be less than or equal to `nticks`. Has an effect only if `tickmode` is set to *auto*." + }, + "tick0": { + "valType": "any", + "role": "style", + "editType": "colorbars", + "impliedEdits": { + "tickmode": "linear" + }, + "description": "Sets the placement of the first tick on this axis. Use with `dtick`. If the axis `type` is *log*, then you must take the log of your starting tick (e.g. to set the starting tick to 100, set the `tick0` to 2) except when `dtick`=*L* (see `dtick` for more info). If the axis `type` is *date*, it should be a date string, like date data. If the axis `type` is *category*, it should be a number, using the scale where each category is assigned a serial number from zero in the order it appears." + }, + "dtick": { + "valType": "any", + "role": "style", + "editType": "colorbars", + "impliedEdits": { + "tickmode": "linear" + }, + "description": "Sets the step in-between ticks on this axis. Use with `tick0`. Must be a positive number, or special strings available to *log* and *date* axes. If the axis `type` is *log*, then ticks are set every 10^(n*dtick) where n is the tick number. For example, to set a tick mark at 1, 10, 100, 1000, ... set dtick to 1. To set tick marks at 1, 100, 10000, ... set dtick to 2. To set tick marks at 1, 5, 25, 125, 625, 3125, ... set dtick to log_10(5), or 0.69897000433. *log* has several special values; *L*, where `f` is a positive number, gives ticks linearly spaced in value (but not position). For example `tick0` = 0.1, `dtick` = *L0.5* will put ticks at 0.1, 0.6, 1.1, 1.6 etc. To show powers of 10 plus small digits between, use *D1* (all digits) or *D2* (only 2 and 5). `tick0` is ignored for *D1* and *D2*. If the axis `type` is *date*, then you must convert the time to milliseconds. For example, to set the interval between ticks to one day, set `dtick` to 86400000.0. *date* also has special values *M* gives ticks spaced by a number of months. `n` must be a positive integer. To set ticks on the 15th of every third month, set `tick0` to *2000-01-15* and `dtick` to *M3*. To set ticks every 4 years, set `dtick` to *M48*" + }, + "tickvals": { + "valType": "data_array", + "editType": "colorbars", + "description": "Sets the values at which ticks on this axis appear. Only has an effect if `tickmode` is set to *array*. Used with `ticktext`.", + "role": "data" + }, + "ticktext": { + "valType": "data_array", + "editType": "colorbars", + "description": "Sets the text displayed at the ticks position via `tickvals`. Only has an effect if `tickmode` is set to *array*. Used with `tickvals`.", + "role": "data" + }, + "ticks": { + "valType": "enumerated", + "values": [ + "outside", + "inside", + "" + ], + "role": "style", + "editType": "colorbars", + "description": "Determines whether ticks are drawn or not. If **, this axis' ticks are not drawn. If *outside* (*inside*), this axis' are drawn outside (inside) the axis lines.", + "dflt": "" + }, + "ticklen": { + "valType": "number", + "min": 0, + "dflt": 5, + "role": "style", + "editType": "colorbars", + "description": "Sets the tick length (in px)." + }, + "tickwidth": { + "valType": "number", + "min": 0, + "dflt": 1, + "role": "style", + "editType": "colorbars", + "description": "Sets the tick width (in px)." + }, + "tickcolor": { + "valType": "color", + "dflt": "#444", + "role": "style", + "editType": "colorbars", + "description": "Sets the tick color." + }, + "showticklabels": { + "valType": "boolean", + "dflt": true, + "role": "style", + "editType": "colorbars", + "description": "Determines whether or not the tick labels are drawn." + }, + "tickfont": { + "family": { + "valType": "string", + "role": "style", + "noBlank": true, + "strict": true, + "description": "HTML font family - the typeface that will be applied by the web browser. The web browser will only be able to apply a font if it is available on the system which it operates. Provide multiple font families, separated by commas, to indicate the preference in which to apply fonts if they aren't available on the system. The plotly service (at https://plot.ly or on-premise) generates images on a server, where only a select number of fonts are installed and supported. These include *Arial*, *Balto*, *Courier New*, *Droid Sans*,, *Droid Serif*, *Droid Sans Mono*, *Gravitas One*, *Old Standard TT*, *Open Sans*, *Overpass*, *PT Sans Narrow*, *Raleway*, *Times New Roman*.", + "editType": "colorbars" + }, + "size": { + "valType": "number", + "role": "style", + "min": 1, + "editType": "colorbars" + }, + "color": { + "valType": "color", + "role": "style", + "editType": "colorbars" + }, + "description": "Sets the color bar's tick label font", + "editType": "colorbars", + "role": "object" + }, + "tickangle": { + "valType": "angle", + "dflt": "auto", + "role": "style", + "editType": "colorbars", + "description": "Sets the angle of the tick labels with respect to the horizontal. For example, a `tickangle` of -90 draws the tick labels vertically." + }, + "tickformat": { + "valType": "string", + "dflt": "", + "role": "style", + "editType": "colorbars", + "description": "Sets the tick label formatting rule using d3 formatting mini-languages which are very similar to those in Python. For numbers, see: https://github.com/d3/d3-format/blob/master/README.md#locale_format And for dates see: https://github.com/d3/d3-time-format/blob/master/README.md#locale_format We add one item to d3's date formatter: *%{n}f* for fractional seconds with n digits. For example, *2016-10-13 09:15:23.456* with tickformat *%H~%M~%S.%2f* would display *09~15~23.46*" + }, + "tickformatstops": { + "items": { + "tickformatstop": { + "dtickrange": { + "valType": "info_array", + "role": "info", + "items": [ + { + "valType": "any", + "editType": "colorbars" + }, + { + "valType": "any", + "editType": "colorbars" + } + ], + "editType": "colorbars", + "description": "range [*min*, *max*], where *min*, *max* - dtick values which describe some zoom level, it is possible to omit *min* or *max* value by passing *null*" + }, + "value": { + "valType": "string", + "dflt": "", + "role": "style", + "editType": "colorbars", + "description": "string - dtickformat for described zoom level, the same as *tickformat*" + }, + "editType": "colorbars", + "role": "object" + } + }, + "role": "object" + }, + "tickprefix": { + "valType": "string", + "dflt": "", + "role": "style", + "editType": "colorbars", + "description": "Sets a tick label prefix." + }, + "showtickprefix": { + "valType": "enumerated", + "values": [ + "all", + "first", + "last", + "none" + ], + "dflt": "all", + "role": "style", + "editType": "colorbars", + "description": "If *all*, all tick labels are displayed with a prefix. If *first*, only the first tick is displayed with a prefix. If *last*, only the last tick is displayed with a suffix. If *none*, tick prefixes are hidden." + }, + "ticksuffix": { + "valType": "string", + "dflt": "", + "role": "style", + "editType": "colorbars", + "description": "Sets a tick label suffix." + }, + "showticksuffix": { + "valType": "enumerated", + "values": [ + "all", + "first", + "last", + "none" + ], + "dflt": "all", + "role": "style", + "editType": "colorbars", + "description": "Same as `showtickprefix` but for tick suffixes." + }, + "separatethousands": { + "valType": "boolean", + "dflt": false, + "role": "style", + "editType": "colorbars", + "description": "If \"true\", even 4-digit integers are separated" + }, + "exponentformat": { + "valType": "enumerated", + "values": [ + "none", + "e", + "E", + "power", + "SI", + "B" + ], + "dflt": "B", + "role": "style", + "editType": "colorbars", + "description": "Determines a formatting rule for the tick exponents. For example, consider the number 1,000,000,000. If *none*, it appears as 1,000,000,000. If *e*, 1e+9. If *E*, 1E+9. If *power*, 1x10^9 (with 9 in a super script). If *SI*, 1G. If *B*, 1B." + }, + "showexponent": { + "valType": "enumerated", + "values": [ + "all", + "first", + "last", + "none" + ], + "dflt": "all", + "role": "style", + "editType": "colorbars", + "description": "If *all*, all exponents are shown besides their significands. If *first*, only the exponent of the first tick is shown. If *last*, only the exponent of the last tick is shown. If *none*, no exponents appear." + }, + "title": { + "valType": "string", + "role": "info", + "dflt": "Click to enter colorscale title", + "description": "Sets the title of the color bar.", + "editType": "colorbars" + }, + "titlefont": { + "family": { + "valType": "string", + "role": "style", + "noBlank": true, + "strict": true, + "description": "HTML font family - the typeface that will be applied by the web browser. The web browser will only be able to apply a font if it is available on the system which it operates. Provide multiple font families, separated by commas, to indicate the preference in which to apply fonts if they aren't available on the system. The plotly service (at https://plot.ly or on-premise) generates images on a server, where only a select number of fonts are installed and supported. These include *Arial*, *Balto*, *Courier New*, *Droid Sans*,, *Droid Serif*, *Droid Sans Mono*, *Gravitas One*, *Old Standard TT*, *Open Sans*, *Overpass*, *PT Sans Narrow*, *Raleway*, *Times New Roman*.", + "editType": "colorbars" + }, + "size": { + "valType": "number", + "role": "style", + "min": 1, + "editType": "colorbars" + }, + "color": { + "valType": "color", + "role": "style", + "editType": "colorbars" + }, + "description": "Sets this color bar's title font.", + "editType": "colorbars", + "role": "object" + }, + "titleside": { + "valType": "enumerated", + "values": [ + "right", + "top", + "bottom" + ], + "role": "style", + "dflt": "top", + "description": "Determines the location of the colorbar title with respect to the color bar.", + "editType": "colorbars" + }, + "editType": "colorbars", + "role": "object", + "tickvalssrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for tickvals .", + "editType": "none" + }, + "ticktextsrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for ticktext .", + "editType": "none" + } + }, + "xcalendar": { + "valType": "enumerated", + "values": [ + "gregorian", + "chinese", + "coptic", + "discworld", + "ethiopian", + "hebrew", + "islamic", + "julian", + "mayan", + "nanakshahi", + "nepali", + "persian", + "jalali", + "taiwan", + "thai", + "ummalqura" + ], + "role": "info", + "editType": "calc", + "dflt": "gregorian", + "description": "Sets the calendar system to use with `x` date data." + }, + "ycalendar": { + "valType": "enumerated", + "values": [ + "gregorian", + "chinese", + "coptic", + "discworld", + "ethiopian", + "hebrew", + "islamic", + "julian", + "mayan", + "nanakshahi", + "nepali", + "persian", + "jalali", + "taiwan", + "thai", + "ummalqura" + ], + "role": "info", + "editType": "calc", + "dflt": "gregorian", + "description": "Sets the calendar system to use with `y` date data." + }, + "xaxis": { + "valType": "subplotid", + "role": "info", + "dflt": "x", + "editType": "calc+clearAxisTypes", + "description": "Sets a reference between this trace's x coordinates and a 2D cartesian x axis. If *x* (the default value), the x coordinates refer to `layout.xaxis`. If *x2*, the x coordinates refer to `layout.xaxis2`, and so on." + }, + "yaxis": { + "valType": "subplotid", + "role": "info", + "dflt": "y", + "editType": "calc+clearAxisTypes", + "description": "Sets a reference between this trace's y coordinates and a 2D cartesian y axis. If *y* (the default value), the y coordinates refer to `layout.yaxis`. If *y2*, the y coordinates refer to `layout.xaxis2`, and so on." + }, + "idssrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for ids .", + "editType": "none" + }, + "customdatasrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for customdata .", + "editType": "none" + }, + "hoverinfosrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for hoverinfo .", + "editType": "none" + }, + "zsrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for z .", + "editType": "none" + }, + "xsrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for x .", + "editType": "none" + }, + "ysrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for y .", + "editType": "none" + }, + "textsrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for text .", + "editType": "none" + } + } + }, + "histogram": { + "meta": { + "description": "The sample data from which statistics are computed is set in `x` for vertically spanning histograms and in `y` for horizontally spanning histograms. Binning options are set `xbins` and `ybins` respectively if no aggregation data is provided." + }, + "attributes": { + "type": "histogram", + "visible": { + "valType": "enumerated", + "values": [ + true, + false, + "legendonly" + ], + "role": "info", + "dflt": true, + "editType": "calc", + "description": "Determines whether or not this trace is visible. If *legendonly*, the trace is not drawn, but can appear as a legend item (provided that the legend itself is visible)." + }, + "showlegend": { + "valType": "boolean", + "role": "info", + "dflt": true, + "editType": "style", + "description": "Determines whether or not an item corresponding to this trace is shown in the legend." + }, + "legendgroup": { + "valType": "string", + "role": "info", + "dflt": "", + "editType": "style", + "description": "Sets the legend group for this trace. Traces part of the same legend group hide/show at the same time when toggling legend items." + }, + "opacity": { + "valType": "number", + "role": "style", + "min": 0, + "max": 1, + "dflt": 1, + "editType": "style", + "description": "Sets the opacity of the trace." + }, + "name": { + "valType": "string", + "role": "info", + "editType": "style", + "description": "Sets the trace name. The trace name appear as the legend item and on hover." + }, + "uid": { + "valType": "string", + "role": "info", + "dflt": "", + "editType": "calc" + }, + "ids": { + "valType": "data_array", + "editType": "calc", + "description": "Assigns id labels to each datum. These ids for object constancy of data points during animation.", + "role": "data" + }, + "customdata": { + "valType": "data_array", + "editType": "calc", + "description": "Assigns extra data each datum. This may be useful when listening to hover, click and selection events. Note that, *scatter* traces also appends customdata items in the markers DOM elements", + "role": "data" + }, + "selectedpoints": { + "valType": "any", + "role": "info", + "editType": "calc", + "description": "Array containing integer indices of selected points. Has an effect only for traces that support selections. Note that an empty array means an empty selection where the `unselected` are turned on for all points, whereas, any other non-array values means no selection all where the `selected` and `unselected` styles have no effect." + }, + "hoverinfo": { + "valType": "flaglist", + "role": "info", + "flags": [ + "x", + "y", + "z", + "text", + "name" + ], + "extras": [ + "all", + "none", + "skip" + ], + "arrayOk": true, + "dflt": "all", + "editType": "none", + "description": "Determines which trace information appear on hover. If `none` or `skip` are set, no information is displayed upon hovering. But, if `none` is set, click and hover events are still fired." + }, + "hoverlabel": { + "bgcolor": { + "valType": "color", + "role": "style", + "arrayOk": true, + "editType": "none", + "description": "Sets the background color of the hover labels for this trace" + }, + "bordercolor": { + "valType": "color", + "role": "style", + "arrayOk": true, + "editType": "none", + "description": "Sets the border color of the hover labels for this trace." + }, + "font": { + "family": { + "valType": "string", + "role": "style", + "noBlank": true, + "strict": true, + "editType": "none", + "description": "HTML font family - the typeface that will be applied by the web browser. The web browser will only be able to apply a font if it is available on the system which it operates. Provide multiple font families, separated by commas, to indicate the preference in which to apply fonts if they aren't available on the system. The plotly service (at https://plot.ly or on-premise) generates images on a server, where only a select number of fonts are installed and supported. These include *Arial*, *Balto*, *Courier New*, *Droid Sans*,, *Droid Serif*, *Droid Sans Mono*, *Gravitas One*, *Old Standard TT*, *Open Sans*, *Overpass*, *PT Sans Narrow*, *Raleway*, *Times New Roman*.", + "arrayOk": true + }, + "size": { + "valType": "number", + "role": "style", + "min": 1, + "editType": "none", + "arrayOk": true + }, + "color": { + "valType": "color", + "role": "style", + "editType": "none", + "arrayOk": true + }, + "editType": "none", + "description": "Sets the font used in hover labels.", + "role": "object", + "familysrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for family .", + "editType": "none" + }, + "sizesrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for size .", + "editType": "none" + }, + "colorsrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for color .", + "editType": "none" + } + }, + "namelength": { + "valType": "integer", + "min": -1, + "arrayOk": true, + "role": "style", + "editType": "none", + "description": "Sets the length (in number of characters) of the trace name in the hover labels for this trace. -1 shows the whole name regardless of length. 0-3 shows the first 0-3 characters, and an integer >3 will show the whole name if it is less than that many characters, but if it is longer, will truncate to `namelength - 3` characters and add an ellipsis." + }, + "editType": "calc", + "role": "object", + "bgcolorsrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for bgcolor .", + "editType": "none" + }, + "bordercolorsrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for bordercolor .", + "editType": "none" + }, + "namelengthsrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for namelength .", + "editType": "none" + } + }, + "stream": { + "token": { + "valType": "string", + "noBlank": true, + "strict": true, + "role": "info", + "editType": "calc", + "description": "The stream id number links a data trace on a plot with a stream. See https://plot.ly/settings for more details." + }, + "maxpoints": { + "valType": "number", + "min": 0, + "max": 10000, + "dflt": 500, + "role": "info", + "editType": "calc", + "description": "Sets the maximum number of points to keep on the plots from an incoming stream. If `maxpoints` is set to *50*, only the newest 50 points will be displayed on the plot." + }, + "editType": "calc", + "role": "object" + }, + "x": { + "valType": "data_array", + "editType": "calc+clearAxisTypes", + "description": "Sets the sample data to be binned on the x axis.", + "role": "data" + }, + "y": { + "valType": "data_array", + "editType": "calc+clearAxisTypes", + "description": "Sets the sample data to be binned on the y axis.", + "role": "data" + }, + "text": { + "valType": "string", + "role": "info", + "dflt": "", + "arrayOk": true, + "editType": "calc", + "description": "Sets text elements associated with each (x,y) pair. If a single string, the same string appears over all the data points. If an array of string, the items are mapped in order to the this trace's (x,y) coordinates. If trace `hoverinfo` contains a *text* flag and *hovertext* is not set, these elements will be seen in the hover labels." + }, + "orientation": { + "valType": "enumerated", + "role": "info", + "values": [ + "v", + "h" + ], + "editType": "calc+clearAxisTypes", + "description": "Sets the orientation of the bars. With *v* (*h*), the value of the each bar spans along the vertical (horizontal)." + }, + "histfunc": { + "valType": "enumerated", + "values": [ + "count", + "sum", + "avg", + "min", + "max" + ], + "role": "style", + "dflt": "count", + "editType": "calc", + "description": "Specifies the binning function used for this histogram trace. If *count*, the histogram values are computed by counting the number of values lying inside each bin. If *sum*, *avg*, *min*, *max*, the histogram values are computed using the sum, the average, the minimum or the maximum of the values lying inside each bin respectively." + }, + "histnorm": { + "valType": "enumerated", + "values": [ + "", + "percent", + "probability", + "density", + "probability density" + ], + "dflt": "", + "role": "style", + "editType": "calc", + "description": "Specifies the type of normalization used for this histogram trace. If **, the span of each bar corresponds to the number of occurrences (i.e. the number of data points lying inside the bins). If *percent* / *probability*, the span of each bar corresponds to the percentage / fraction of occurrences with respect to the total number of sample points (here, the sum of all bin HEIGHTS equals 100% / 1). If *density*, the span of each bar corresponds to the number of occurrences in a bin divided by the size of the bin interval (here, the sum of all bin AREAS equals the total number of sample points). If *probability density*, the area of each bar corresponds to the probability that an event will fall into the corresponding bin (here, the sum of all bin AREAS equals 1)." + }, + "cumulative": { + "enabled": { + "valType": "boolean", + "dflt": false, + "role": "info", + "editType": "calc", + "description": "If true, display the cumulative distribution by summing the binned values. Use the `direction` and `centralbin` attributes to tune the accumulation method. Note: in this mode, the *density* `histnorm` settings behave the same as their equivalents without *density*: ** and *density* both rise to the number of data points, and *probability* and *probability density* both rise to the number of sample points." + }, + "direction": { + "valType": "enumerated", + "values": [ + "increasing", + "decreasing" + ], + "dflt": "increasing", + "role": "info", + "editType": "calc", + "description": "Only applies if cumulative is enabled. If *increasing* (default) we sum all prior bins, so the result increases from left to right. If *decreasing* we sum later bins so the result decreases from left to right." + }, + "currentbin": { + "valType": "enumerated", + "values": [ + "include", + "exclude", + "half" + ], + "dflt": "include", + "role": "info", + "editType": "calc", + "description": "Only applies if cumulative is enabled. Sets whether the current bin is included, excluded, or has half of its value included in the current cumulative value. *include* is the default for compatibility with various other tools, however it introduces a half-bin bias to the results. *exclude* makes the opposite half-bin bias, and *half* removes it." + }, + "editType": "calc", + "role": "object" + }, + "autobinx": { + "valType": "boolean", + "dflt": null, + "role": "style", + "editType": "calc", + "impliedEdits": {}, + "description": "Determines whether or not the x axis bin attributes are picked by an algorithm. Note that this should be set to false if you want to manually set the number of bins using the attributes in xbins." + }, + "nbinsx": { + "valType": "integer", + "min": 0, + "dflt": 0, + "role": "style", + "editType": "calc", + "description": "Specifies the maximum number of desired bins. This value will be used in an algorithm that will decide the optimal bin size such that the histogram best visualizes the distribution of the data." + }, + "xbins": { + "start": { + "valType": "any", + "dflt": null, + "role": "style", + "editType": "calc", + "impliedEdits": { + "^autobinx": false + }, + "description": "Sets the starting value for the x axis bins." + }, + "end": { + "valType": "any", + "dflt": null, + "role": "style", + "editType": "calc", + "impliedEdits": { + "^autobinx": false + }, + "description": "Sets the end value for the x axis bins." + }, + "size": { + "valType": "any", + "dflt": null, + "role": "style", + "editType": "calc", + "impliedEdits": { + "^autobinx": false + }, + "description": "Sets the step in-between value each x axis bin." + }, + "editType": "calc", + "impliedEdits": { + "autobinx": false, + "role": "object" + }, + "role": "object" + }, + "autobiny": { + "valType": "boolean", + "dflt": null, + "role": "style", + "editType": "calc", + "impliedEdits": {}, + "description": "Determines whether or not the y axis bin attributes are picked by an algorithm. Note that this should be set to false if you want to manually set the number of bins using the attributes in ybins." + }, + "nbinsy": { + "valType": "integer", + "min": 0, + "dflt": 0, + "role": "style", + "editType": "calc", + "description": "Specifies the maximum number of desired bins. This value will be used in an algorithm that will decide the optimal bin size such that the histogram best visualizes the distribution of the data." + }, + "ybins": { + "start": { + "valType": "any", + "dflt": null, + "role": "style", + "editType": "calc", + "impliedEdits": { + "^autobiny": false + }, + "description": "Sets the starting value for the y axis bins." + }, + "end": { + "valType": "any", + "dflt": null, + "role": "style", + "editType": "calc", + "impliedEdits": { + "^autobiny": false + }, + "description": "Sets the end value for the y axis bins." + }, + "size": { + "valType": "any", + "dflt": null, + "role": "style", + "editType": "calc", + "impliedEdits": { + "^autobiny": false + }, + "description": "Sets the step in-between value each y axis bin." + }, + "editType": "calc", + "impliedEdits": { + "autobiny": false, + "role": "object" + }, + "role": "object" + }, + "marker": { + "line": { + "width": { + "valType": "number", + "min": 0, + "arrayOk": true, + "role": "style", + "editType": "style", + "description": "Sets the width (in px) of the lines bounding the marker points.", + "dflt": 0 + }, + "editType": "calc", + "color": { + "valType": "color", + "arrayOk": true, + "role": "style", + "editType": "style", + "description": "Sets the marker.line color. It accepts either a specific color or an array of numbers that are mapped to the colorscale relative to the max and min values of the array or relative to `cmin` and `cmax` if set." + }, + "colorscale": { + "valType": "colorscale", + "role": "style", + "editType": "calc", + "impliedEdits": { + "autocolorscale": false + }, + "description": "Sets the colorscale and only has an effect if `marker.line.color` is set to a numerical array. The colorscale must be an array containing arrays mapping a normalized value to an rgb, rgba, hex, hsl, hsv, or named color string. At minimum, a mapping for the lowest (0) and highest (1) values are required. For example, `[[0, 'rgb(0,0,255)', [1, 'rgb(255,0,0)']]`. To control the bounds of the colorscale in color space, use `marker.line.cmin` and `marker.line.cmax`. Alternatively, `colorscale` may be a palette name string of the following list: Greys, YlGnBu, Greens, YlOrRd, Bluered, RdBu, Reds, Blues, Picnic, Rainbow, Portland, Jet, Hot, Blackbody, Earth, Electric, Viridis" + }, + "cauto": { + "valType": "boolean", + "role": "info", + "dflt": true, + "editType": "calc", + "impliedEdits": {}, + "description": "Has an effect only if `marker.line.color` is set to a numerical array and `cmin`, `cmax` are set by the user. In this case, it controls whether the range of colors in `colorscale` is mapped to the range of values in the `color` array (`cauto: true`), or the `cmin`/`cmax` values (`cauto: false`). Defaults to `false` when `cmin`, `cmax` are set by the user." + }, + "cmax": { + "valType": "number", + "role": "info", + "dflt": null, + "editType": "plot", + "impliedEdits": { + "cauto": false + }, + "description": "Has an effect only if `marker.line.color` is set to a numerical array. Sets the upper bound of the color domain. Value should be associated to the `marker.line.color` array index, and if set, `marker.line.cmin` must be set as well." + }, + "cmin": { + "valType": "number", + "role": "info", + "dflt": null, + "editType": "plot", + "impliedEdits": { + "cauto": false + }, + "description": "Has an effect only if `marker.line.color` is set to a numerical array. Sets the lower bound of the color domain. Value should be associated to the `marker.line.color` array index, and if set, `marker.line.cmax` must be set as well." + }, + "autocolorscale": { + "valType": "boolean", + "role": "style", + "dflt": true, + "editType": "calc", + "impliedEdits": {}, + "description": "Has an effect only if `marker.line.color` is set to a numerical array. Determines whether the colorscale is a default palette (`autocolorscale: true`) or the palette determined by `marker.line.colorscale`. In case `colorscale` is unspecified or `autocolorscale` is true, the default palette will be chosen according to whether numbers in the `color` array are all positive, all negative or mixed." + }, + "reversescale": { + "valType": "boolean", + "role": "style", + "dflt": false, + "editType": "calc", + "description": "Has an effect only if `marker.line.color` is set to a numerical array. Reverses the color mapping if true (`cmin` will correspond to the last color in the array and `cmax` will correspond to the first color)." + }, + "role": "object", + "widthsrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for width .", + "editType": "none" + }, + "colorsrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for color .", + "editType": "none" + } + }, + "editType": "calc", + "color": { + "valType": "color", + "arrayOk": true, + "role": "style", + "editType": "style", + "description": "Sets the marker color. It accepts either a specific color or an array of numbers that are mapped to the colorscale relative to the max and min values of the array or relative to `cmin` and `cmax` if set." + }, + "colorscale": { + "valType": "colorscale", + "role": "style", + "editType": "calc", + "impliedEdits": { + "autocolorscale": false + }, + "description": "Sets the colorscale and only has an effect if `marker.color` is set to a numerical array. The colorscale must be an array containing arrays mapping a normalized value to an rgb, rgba, hex, hsl, hsv, or named color string. At minimum, a mapping for the lowest (0) and highest (1) values are required. For example, `[[0, 'rgb(0,0,255)', [1, 'rgb(255,0,0)']]`. To control the bounds of the colorscale in color space, use `marker.cmin` and `marker.cmax`. Alternatively, `colorscale` may be a palette name string of the following list: Greys, YlGnBu, Greens, YlOrRd, Bluered, RdBu, Reds, Blues, Picnic, Rainbow, Portland, Jet, Hot, Blackbody, Earth, Electric, Viridis" + }, + "cauto": { + "valType": "boolean", + "role": "info", + "dflt": true, + "editType": "calc", + "impliedEdits": {}, + "description": "Has an effect only if `marker.color` is set to a numerical array and `cmin`, `cmax` are set by the user. In this case, it controls whether the range of colors in `colorscale` is mapped to the range of values in the `color` array (`cauto: true`), or the `cmin`/`cmax` values (`cauto: false`). Defaults to `false` when `cmin`, `cmax` are set by the user." + }, + "cmax": { + "valType": "number", + "role": "info", + "dflt": null, + "editType": "plot", + "impliedEdits": { + "cauto": false + }, + "description": "Has an effect only if `marker.color` is set to a numerical array. Sets the upper bound of the color domain. Value should be associated to the `marker.color` array index, and if set, `marker.cmin` must be set as well." + }, + "cmin": { + "valType": "number", + "role": "info", + "dflt": null, + "editType": "plot", + "impliedEdits": { + "cauto": false + }, + "description": "Has an effect only if `marker.color` is set to a numerical array. Sets the lower bound of the color domain. Value should be associated to the `marker.color` array index, and if set, `marker.cmax` must be set as well." + }, + "autocolorscale": { + "valType": "boolean", + "role": "style", + "dflt": true, + "editType": "calc", + "impliedEdits": {}, + "description": "Has an effect only if `marker.color` is set to a numerical array. Determines whether the colorscale is a default palette (`autocolorscale: true`) or the palette determined by `marker.colorscale`. In case `colorscale` is unspecified or `autocolorscale` is true, the default palette will be chosen according to whether numbers in the `color` array are all positive, all negative or mixed." + }, + "reversescale": { + "valType": "boolean", + "role": "style", + "dflt": false, + "editType": "calc", + "description": "Has an effect only if `marker.color` is set to a numerical array. Reverses the color mapping if true (`cmin` will correspond to the last color in the array and `cmax` will correspond to the first color)." + }, + "showscale": { + "valType": "boolean", + "role": "info", + "dflt": false, + "editType": "calc", + "description": "Has an effect only if `marker.color` is set to a numerical array. Determines whether or not a colorbar is displayed." + }, + "colorbar": { + "thicknessmode": { + "valType": "enumerated", + "values": [ + "fraction", + "pixels" + ], + "role": "style", + "dflt": "pixels", + "description": "Determines whether this color bar's thickness (i.e. the measure in the constant color direction) is set in units of plot *fraction* or in *pixels*. Use `thickness` to set the value.", + "editType": "colorbars" + }, + "thickness": { + "valType": "number", + "role": "style", + "min": 0, + "dflt": 30, + "description": "Sets the thickness of the color bar This measure excludes the size of the padding, ticks and labels.", + "editType": "colorbars" + }, + "lenmode": { + "valType": "enumerated", + "values": [ + "fraction", + "pixels" + ], + "role": "info", + "dflt": "fraction", + "description": "Determines whether this color bar's length (i.e. the measure in the color variation direction) is set in units of plot *fraction* or in *pixels. Use `len` to set the value.", + "editType": "colorbars" + }, + "len": { + "valType": "number", + "min": 0, + "dflt": 1, + "role": "style", + "description": "Sets the length of the color bar This measure excludes the padding of both ends. That is, the color bar length is this length minus the padding on both ends.", + "editType": "colorbars" + }, + "x": { + "valType": "number", + "dflt": 1.02, + "min": -2, + "max": 3, + "role": "style", + "description": "Sets the x position of the color bar (in plot fraction).", + "editType": "colorbars" + }, + "xanchor": { + "valType": "enumerated", + "values": [ + "left", + "center", + "right" + ], + "dflt": "left", + "role": "style", + "description": "Sets this color bar's horizontal position anchor. This anchor binds the `x` position to the *left*, *center* or *right* of the color bar.", + "editType": "colorbars" + }, + "xpad": { + "valType": "number", + "role": "style", + "min": 0, + "dflt": 10, + "description": "Sets the amount of padding (in px) along the x direction.", + "editType": "colorbars" + }, + "y": { + "valType": "number", + "role": "style", + "dflt": 0.5, + "min": -2, + "max": 3, + "description": "Sets the y position of the color bar (in plot fraction).", + "editType": "colorbars" + }, + "yanchor": { + "valType": "enumerated", + "values": [ + "top", + "middle", + "bottom" + ], + "role": "style", + "dflt": "middle", + "description": "Sets this color bar's vertical position anchor This anchor binds the `y` position to the *top*, *middle* or *bottom* of the color bar.", + "editType": "colorbars" + }, + "ypad": { + "valType": "number", + "role": "style", + "min": 0, + "dflt": 10, + "description": "Sets the amount of padding (in px) along the y direction.", + "editType": "colorbars" + }, + "outlinecolor": { + "valType": "color", + "dflt": "#444", + "role": "style", + "editType": "colorbars", + "description": "Sets the axis line color." + }, + "outlinewidth": { + "valType": "number", + "min": 0, + "dflt": 1, + "role": "style", + "editType": "colorbars", + "description": "Sets the width (in px) of the axis line." + }, + "bordercolor": { + "valType": "color", + "dflt": "#444", + "role": "style", + "editType": "colorbars", + "description": "Sets the axis line color." + }, + "borderwidth": { + "valType": "number", + "role": "style", + "min": 0, + "dflt": 0, + "description": "Sets the width (in px) or the border enclosing this color bar.", + "editType": "colorbars" + }, + "bgcolor": { + "valType": "color", + "role": "style", + "dflt": "rgba(0,0,0,0)", + "description": "Sets the color of padded area.", + "editType": "colorbars" + }, + "tickmode": { + "valType": "enumerated", + "values": [ + "auto", + "linear", + "array" + ], + "role": "info", + "editType": "colorbars", + "impliedEdits": {}, + "description": "Sets the tick mode for this axis. If *auto*, the number of ticks is set via `nticks`. If *linear*, the placement of the ticks is determined by a starting position `tick0` and a tick step `dtick` (*linear* is the default value if `tick0` and `dtick` are provided). If *array*, the placement of the ticks is set via `tickvals` and the tick text is `ticktext`. (*array* is the default value if `tickvals` is provided)." + }, + "nticks": { + "valType": "integer", + "min": 0, + "dflt": 0, + "role": "style", + "editType": "colorbars", + "description": "Specifies the maximum number of ticks for the particular axis. The actual number of ticks will be chosen automatically to be less than or equal to `nticks`. Has an effect only if `tickmode` is set to *auto*." + }, + "tick0": { + "valType": "any", + "role": "style", + "editType": "colorbars", + "impliedEdits": { + "tickmode": "linear" + }, + "description": "Sets the placement of the first tick on this axis. Use with `dtick`. If the axis `type` is *log*, then you must take the log of your starting tick (e.g. to set the starting tick to 100, set the `tick0` to 2) except when `dtick`=*L* (see `dtick` for more info). If the axis `type` is *date*, it should be a date string, like date data. If the axis `type` is *category*, it should be a number, using the scale where each category is assigned a serial number from zero in the order it appears." + }, + "dtick": { + "valType": "any", + "role": "style", + "editType": "colorbars", + "impliedEdits": { + "tickmode": "linear" + }, + "description": "Sets the step in-between ticks on this axis. Use with `tick0`. Must be a positive number, or special strings available to *log* and *date* axes. If the axis `type` is *log*, then ticks are set every 10^(n*dtick) where n is the tick number. For example, to set a tick mark at 1, 10, 100, 1000, ... set dtick to 1. To set tick marks at 1, 100, 10000, ... set dtick to 2. To set tick marks at 1, 5, 25, 125, 625, 3125, ... set dtick to log_10(5), or 0.69897000433. *log* has several special values; *L*, where `f` is a positive number, gives ticks linearly spaced in value (but not position). For example `tick0` = 0.1, `dtick` = *L0.5* will put ticks at 0.1, 0.6, 1.1, 1.6 etc. To show powers of 10 plus small digits between, use *D1* (all digits) or *D2* (only 2 and 5). `tick0` is ignored for *D1* and *D2*. If the axis `type` is *date*, then you must convert the time to milliseconds. For example, to set the interval between ticks to one day, set `dtick` to 86400000.0. *date* also has special values *M* gives ticks spaced by a number of months. `n` must be a positive integer. To set ticks on the 15th of every third month, set `tick0` to *2000-01-15* and `dtick` to *M3*. To set ticks every 4 years, set `dtick` to *M48*" + }, + "tickvals": { + "valType": "data_array", + "editType": "colorbars", + "description": "Sets the values at which ticks on this axis appear. Only has an effect if `tickmode` is set to *array*. Used with `ticktext`.", + "role": "data" + }, + "ticktext": { + "valType": "data_array", + "editType": "colorbars", + "description": "Sets the text displayed at the ticks position via `tickvals`. Only has an effect if `tickmode` is set to *array*. Used with `tickvals`.", + "role": "data" + }, + "ticks": { + "valType": "enumerated", + "values": [ + "outside", + "inside", + "" + ], + "role": "style", + "editType": "colorbars", + "description": "Determines whether ticks are drawn or not. If **, this axis' ticks are not drawn. If *outside* (*inside*), this axis' are drawn outside (inside) the axis lines.", + "dflt": "" + }, + "ticklen": { + "valType": "number", + "min": 0, + "dflt": 5, + "role": "style", + "editType": "colorbars", + "description": "Sets the tick length (in px)." + }, + "tickwidth": { + "valType": "number", + "min": 0, + "dflt": 1, + "role": "style", + "editType": "colorbars", + "description": "Sets the tick width (in px)." + }, + "tickcolor": { + "valType": "color", + "dflt": "#444", + "role": "style", + "editType": "colorbars", + "description": "Sets the tick color." + }, + "showticklabels": { + "valType": "boolean", + "dflt": true, + "role": "style", + "editType": "colorbars", + "description": "Determines whether or not the tick labels are drawn." + }, + "tickfont": { + "family": { + "valType": "string", + "role": "style", + "noBlank": true, + "strict": true, + "description": "HTML font family - the typeface that will be applied by the web browser. The web browser will only be able to apply a font if it is available on the system which it operates. Provide multiple font families, separated by commas, to indicate the preference in which to apply fonts if they aren't available on the system. The plotly service (at https://plot.ly or on-premise) generates images on a server, where only a select number of fonts are installed and supported. These include *Arial*, *Balto*, *Courier New*, *Droid Sans*,, *Droid Serif*, *Droid Sans Mono*, *Gravitas One*, *Old Standard TT*, *Open Sans*, *Overpass*, *PT Sans Narrow*, *Raleway*, *Times New Roman*.", + "editType": "colorbars" + }, + "size": { + "valType": "number", + "role": "style", + "min": 1, + "editType": "colorbars" + }, + "color": { + "valType": "color", + "role": "style", + "editType": "colorbars" + }, + "description": "Sets the color bar's tick label font", + "editType": "colorbars", + "role": "object" + }, + "tickangle": { + "valType": "angle", + "dflt": "auto", + "role": "style", + "editType": "colorbars", + "description": "Sets the angle of the tick labels with respect to the horizontal. For example, a `tickangle` of -90 draws the tick labels vertically." + }, + "tickformat": { + "valType": "string", + "dflt": "", + "role": "style", + "editType": "colorbars", + "description": "Sets the tick label formatting rule using d3 formatting mini-languages which are very similar to those in Python. For numbers, see: https://github.com/d3/d3-format/blob/master/README.md#locale_format And for dates see: https://github.com/d3/d3-time-format/blob/master/README.md#locale_format We add one item to d3's date formatter: *%{n}f* for fractional seconds with n digits. For example, *2016-10-13 09:15:23.456* with tickformat *%H~%M~%S.%2f* would display *09~15~23.46*" + }, + "tickformatstops": { + "items": { + "tickformatstop": { + "dtickrange": { + "valType": "info_array", + "role": "info", + "items": [ + { + "valType": "any", + "editType": "colorbars" + }, + { + "valType": "any", + "editType": "colorbars" + } + ], + "editType": "colorbars", + "description": "range [*min*, *max*], where *min*, *max* - dtick values which describe some zoom level, it is possible to omit *min* or *max* value by passing *null*" + }, + "value": { + "valType": "string", + "dflt": "", + "role": "style", + "editType": "colorbars", + "description": "string - dtickformat for described zoom level, the same as *tickformat*" + }, + "editType": "colorbars", + "role": "object" + } + }, + "role": "object" + }, + "tickprefix": { + "valType": "string", + "dflt": "", + "role": "style", + "editType": "colorbars", + "description": "Sets a tick label prefix." + }, + "showtickprefix": { + "valType": "enumerated", + "values": [ + "all", + "first", + "last", + "none" + ], + "dflt": "all", + "role": "style", + "editType": "colorbars", + "description": "If *all*, all tick labels are displayed with a prefix. If *first*, only the first tick is displayed with a prefix. If *last*, only the last tick is displayed with a suffix. If *none*, tick prefixes are hidden." + }, + "ticksuffix": { + "valType": "string", + "dflt": "", + "role": "style", + "editType": "colorbars", + "description": "Sets a tick label suffix." + }, + "showticksuffix": { + "valType": "enumerated", + "values": [ + "all", + "first", + "last", + "none" + ], + "dflt": "all", + "role": "style", + "editType": "colorbars", + "description": "Same as `showtickprefix` but for tick suffixes." + }, + "separatethousands": { + "valType": "boolean", + "dflt": false, + "role": "style", + "editType": "colorbars", + "description": "If \"true\", even 4-digit integers are separated" + }, + "exponentformat": { + "valType": "enumerated", + "values": [ + "none", + "e", + "E", + "power", + "SI", + "B" + ], + "dflt": "B", + "role": "style", + "editType": "colorbars", + "description": "Determines a formatting rule for the tick exponents. For example, consider the number 1,000,000,000. If *none*, it appears as 1,000,000,000. If *e*, 1e+9. If *E*, 1E+9. If *power*, 1x10^9 (with 9 in a super script). If *SI*, 1G. If *B*, 1B." + }, + "showexponent": { + "valType": "enumerated", + "values": [ + "all", + "first", + "last", + "none" + ], + "dflt": "all", + "role": "style", + "editType": "colorbars", + "description": "If *all*, all exponents are shown besides their significands. If *first*, only the exponent of the first tick is shown. If *last*, only the exponent of the last tick is shown. If *none*, no exponents appear." + }, + "title": { + "valType": "string", + "role": "info", + "dflt": "Click to enter colorscale title", + "description": "Sets the title of the color bar.", + "editType": "colorbars" + }, + "titlefont": { + "family": { + "valType": "string", + "role": "style", + "noBlank": true, + "strict": true, + "description": "HTML font family - the typeface that will be applied by the web browser. The web browser will only be able to apply a font if it is available on the system which it operates. Provide multiple font families, separated by commas, to indicate the preference in which to apply fonts if they aren't available on the system. The plotly service (at https://plot.ly or on-premise) generates images on a server, where only a select number of fonts are installed and supported. These include *Arial*, *Balto*, *Courier New*, *Droid Sans*,, *Droid Serif*, *Droid Sans Mono*, *Gravitas One*, *Old Standard TT*, *Open Sans*, *Overpass*, *PT Sans Narrow*, *Raleway*, *Times New Roman*.", + "editType": "colorbars" + }, + "size": { + "valType": "number", + "role": "style", + "min": 1, + "editType": "colorbars" + }, + "color": { + "valType": "color", + "role": "style", + "editType": "colorbars" + }, + "description": "Sets this color bar's title font.", + "editType": "colorbars", + "role": "object" + }, + "titleside": { + "valType": "enumerated", + "values": [ + "right", + "top", + "bottom" + ], + "role": "style", + "dflt": "top", + "description": "Determines the location of the colorbar title with respect to the color bar.", + "editType": "colorbars" + }, + "editType": "colorbars", + "role": "object", + "tickvalssrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for tickvals .", + "editType": "none" + }, + "ticktextsrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for ticktext .", + "editType": "none" + } + }, + "opacity": { + "valType": "number", + "arrayOk": true, + "dflt": 1, + "min": 0, + "max": 1, + "role": "style", + "editType": "style", + "description": "Sets the opacity of the bars." + }, + "role": "object", + "colorsrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for color .", + "editType": "none" + }, + "opacitysrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for opacity .", + "editType": "none" + } + }, + "selected": { + "marker": { + "opacity": { + "valType": "number", + "min": 0, + "max": 1, + "role": "style", + "editType": "style", + "description": "Sets the marker opacity of selected points." + }, + "color": { + "valType": "color", + "role": "style", + "editType": "style", + "description": "Sets the marker color of selected points." + }, + "editType": "style", + "role": "object" + }, + "textfont": { + "color": { + "valType": "color", + "role": "style", + "editType": "style", + "description": "Sets the text font color of selected points." + }, + "editType": "style", + "role": "object" + }, + "editType": "style", + "role": "object" + }, + "unselected": { + "marker": { + "opacity": { + "valType": "number", + "min": 0, + "max": 1, + "role": "style", + "editType": "style", + "description": "Sets the marker opacity of unselected points, applied only when a selection exists." + }, + "color": { + "valType": "color", + "role": "style", + "editType": "style", + "description": "Sets the marker color of unselected points, applied only when a selection exists." + }, + "editType": "style", + "role": "object" + }, + "textfont": { + "color": { + "valType": "color", + "role": "style", + "editType": "style", + "description": "Sets the text font color of unselected points, applied only when a selection exists." + }, + "editType": "style", + "role": "object" + }, + "editType": "style", + "role": "object" + }, + "error_y": { + "visible": { + "valType": "boolean", + "role": "info", + "editType": "calc", + "description": "Determines whether or not this set of error bars is visible." + }, + "type": { + "valType": "enumerated", + "values": [ + "percent", + "constant", + "sqrt", + "data" + ], + "role": "info", + "editType": "calc", + "description": "Determines the rule used to generate the error bars. If *constant`, the bar lengths are of a constant value. Set this constant in `value`. If *percent*, the bar lengths correspond to a percentage of underlying data. Set this percentage in `value`. If *sqrt*, the bar lengths correspond to the sqaure of the underlying data. If *array*, the bar lengths are set with data set `array`." + }, + "symmetric": { + "valType": "boolean", + "role": "info", + "editType": "calc", + "description": "Determines whether or not the error bars have the same length in both direction (top/bottom for vertical bars, left/right for horizontal bars." + }, + "array": { + "valType": "data_array", + "editType": "calc", + "description": "Sets the data corresponding the length of each error bar. Values are plotted relative to the underlying data.", + "role": "data" + }, + "arrayminus": { + "valType": "data_array", + "editType": "calc", + "description": "Sets the data corresponding the length of each error bar in the bottom (left) direction for vertical (horizontal) bars Values are plotted relative to the underlying data.", + "role": "data" + }, + "value": { + "valType": "number", + "min": 0, + "dflt": 10, + "role": "info", + "editType": "calc", + "description": "Sets the value of either the percentage (if `type` is set to *percent*) or the constant (if `type` is set to *constant*) corresponding to the lengths of the error bars." + }, + "valueminus": { + "valType": "number", + "min": 0, + "dflt": 10, + "role": "info", + "editType": "calc", + "description": "Sets the value of either the percentage (if `type` is set to *percent*) or the constant (if `type` is set to *constant*) corresponding to the lengths of the error bars in the bottom (left) direction for vertical (horizontal) bars" + }, + "traceref": { + "valType": "integer", + "min": 0, + "dflt": 0, + "role": "info", + "editType": "style" + }, + "tracerefminus": { + "valType": "integer", + "min": 0, + "dflt": 0, + "role": "info", + "editType": "style" + }, + "copy_ystyle": { + "valType": "boolean", + "role": "style", + "editType": "plot" + }, + "copy_zstyle": { + "valType": "boolean", + "role": "style", + "editType": "style" + }, + "color": { + "valType": "color", + "role": "style", + "editType": "style", + "description": "Sets the stoke color of the error bars." + }, + "thickness": { + "valType": "number", + "min": 0, + "dflt": 2, + "role": "style", + "editType": "style", + "description": "Sets the thickness (in px) of the error bars." + }, + "width": { + "valType": "number", + "min": 0, + "role": "style", + "editType": "plot", + "description": "Sets the width (in px) of the cross-bar at both ends of the error bars." + }, + "editType": "calc", + "_deprecated": { + "opacity": { + "valType": "number", + "role": "style", + "editType": "style", + "description": "Obsolete. Use the alpha channel in error bar `color` to set the opacity." + } + }, + "role": "object", + "arraysrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for array .", + "editType": "none" + }, + "arrayminussrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for arrayminus .", + "editType": "none" + } + }, + "error_x": { + "visible": { + "valType": "boolean", + "role": "info", + "editType": "calc", + "description": "Determines whether or not this set of error bars is visible." + }, + "type": { + "valType": "enumerated", + "values": [ + "percent", + "constant", + "sqrt", + "data" + ], + "role": "info", + "editType": "calc", + "description": "Determines the rule used to generate the error bars. If *constant`, the bar lengths are of a constant value. Set this constant in `value`. If *percent*, the bar lengths correspond to a percentage of underlying data. Set this percentage in `value`. If *sqrt*, the bar lengths correspond to the sqaure of the underlying data. If *array*, the bar lengths are set with data set `array`." + }, + "symmetric": { + "valType": "boolean", + "role": "info", + "editType": "calc", + "description": "Determines whether or not the error bars have the same length in both direction (top/bottom for vertical bars, left/right for horizontal bars." + }, + "array": { + "valType": "data_array", + "editType": "calc", + "description": "Sets the data corresponding the length of each error bar. Values are plotted relative to the underlying data.", + "role": "data" + }, + "arrayminus": { + "valType": "data_array", + "editType": "calc", + "description": "Sets the data corresponding the length of each error bar in the bottom (left) direction for vertical (horizontal) bars Values are plotted relative to the underlying data.", + "role": "data" + }, + "value": { + "valType": "number", + "min": 0, + "dflt": 10, + "role": "info", + "editType": "calc", + "description": "Sets the value of either the percentage (if `type` is set to *percent*) or the constant (if `type` is set to *constant*) corresponding to the lengths of the error bars." + }, + "valueminus": { + "valType": "number", + "min": 0, + "dflt": 10, + "role": "info", + "editType": "calc", + "description": "Sets the value of either the percentage (if `type` is set to *percent*) or the constant (if `type` is set to *constant*) corresponding to the lengths of the error bars in the bottom (left) direction for vertical (horizontal) bars" + }, + "traceref": { + "valType": "integer", + "min": 0, + "dflt": 0, + "role": "info", + "editType": "style" + }, + "tracerefminus": { + "valType": "integer", + "min": 0, + "dflt": 0, + "role": "info", + "editType": "style" + }, + "copy_ystyle": { + "valType": "boolean", + "role": "style", + "editType": "plot" + }, + "copy_zstyle": { + "valType": "boolean", + "role": "style", + "editType": "style" + }, + "color": { + "valType": "color", + "role": "style", + "editType": "style", + "description": "Sets the stoke color of the error bars." + }, + "thickness": { + "valType": "number", + "min": 0, + "dflt": 2, + "role": "style", + "editType": "style", + "description": "Sets the thickness (in px) of the error bars." + }, + "width": { + "valType": "number", + "min": 0, + "role": "style", + "editType": "plot", + "description": "Sets the width (in px) of the cross-bar at both ends of the error bars." + }, + "editType": "calc", + "_deprecated": { + "opacity": { + "valType": "number", + "role": "style", + "editType": "style", + "description": "Obsolete. Use the alpha channel in error bar `color` to set the opacity." + } + }, + "role": "object", + "arraysrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for array .", + "editType": "none" + }, + "arrayminussrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for arrayminus .", + "editType": "none" + } + }, + "_deprecated": { + "bardir": { + "valType": "enumerated", + "role": "info", + "editType": "calc", + "values": [ + "v", + "h" + ], + "description": "Renamed to `orientation`." + } + }, + "xcalendar": { + "valType": "enumerated", + "values": [ + "gregorian", + "chinese", + "coptic", + "discworld", + "ethiopian", + "hebrew", + "islamic", + "julian", + "mayan", + "nanakshahi", + "nepali", + "persian", + "jalali", + "taiwan", + "thai", + "ummalqura" + ], + "role": "info", + "editType": "calc", + "dflt": "gregorian", + "description": "Sets the calendar system to use with `x` date data." + }, + "ycalendar": { + "valType": "enumerated", + "values": [ + "gregorian", + "chinese", + "coptic", + "discworld", + "ethiopian", + "hebrew", + "islamic", + "julian", + "mayan", + "nanakshahi", + "nepali", + "persian", + "jalali", + "taiwan", + "thai", + "ummalqura" + ], + "role": "info", + "editType": "calc", + "dflt": "gregorian", + "description": "Sets the calendar system to use with `y` date data." + }, + "xaxis": { + "valType": "subplotid", + "role": "info", + "dflt": "x", + "editType": "calc+clearAxisTypes", + "description": "Sets a reference between this trace's x coordinates and a 2D cartesian x axis. If *x* (the default value), the x coordinates refer to `layout.xaxis`. If *x2*, the x coordinates refer to `layout.xaxis2`, and so on." + }, + "yaxis": { + "valType": "subplotid", + "role": "info", + "dflt": "y", + "editType": "calc+clearAxisTypes", + "description": "Sets a reference between this trace's y coordinates and a 2D cartesian y axis. If *y* (the default value), the y coordinates refer to `layout.yaxis`. If *y2*, the y coordinates refer to `layout.xaxis2`, and so on." + }, + "idssrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for ids .", + "editType": "none" + }, + "customdatasrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for customdata .", + "editType": "none" + }, + "hoverinfosrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for hoverinfo .", + "editType": "none" + }, + "xsrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for x .", + "editType": "none" + }, + "ysrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for y .", + "editType": "none" + }, + "textsrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for text .", + "editType": "none" + } + }, + "layoutAttributes": { + "barmode": { + "valType": "enumerated", + "values": [ + "stack", + "group", + "overlay", + "relative" + ], + "dflt": "group", + "role": "info", + "editType": "calc", + "description": "Determines how bars at the same location coordinate are displayed on the graph. With *stack*, the bars are stacked on top of one another With *relative*, the bars are stacked on top of one another, with negative values below the axis, positive values above With *group*, the bars are plotted next to one another centered around the shared location. With *overlay*, the bars are plotted over one another, you might need to an *opacity* to see multiple bars." + }, + "barnorm": { + "valType": "enumerated", + "values": [ + "", + "fraction", + "percent" + ], + "dflt": "", + "role": "info", + "editType": "calc", + "description": "Sets the normalization for bar traces on the graph. With *fraction*, the value of each bar is divide by the sum of the values at the location coordinate. With *percent*, the results form *fraction* are presented in percents." + }, + "bargap": { + "valType": "number", + "min": 0, + "max": 1, + "role": "style", + "editType": "calc", + "description": "Sets the gap (in plot fraction) between bars of adjacent location coordinates." + }, + "bargroupgap": { + "valType": "number", + "min": 0, + "max": 1, + "dflt": 0, + "role": "style", + "editType": "calc", + "description": "Sets the gap (in plot fraction) between bars of the same location coordinate." + } + } + }, + "histogram2d": { + "meta": { + "hrName": "histogram_2d", + "description": "The sample data from which statistics are computed is set in `x` and `y` (where `x` and `y` represent marginal distributions, binning is set in `xbins` and `ybins` in this case) or `z` (where `z` represent the 2D distribution and binning set, binning is set by `x` and `y` in this case). The resulting distribution is visualized as a heatmap." + }, + "attributes": { + "type": "histogram2d", + "visible": { + "valType": "enumerated", + "values": [ + true, + false, + "legendonly" + ], + "role": "info", + "dflt": true, + "editType": "calc", + "description": "Determines whether or not this trace is visible. If *legendonly*, the trace is not drawn, but can appear as a legend item (provided that the legend itself is visible)." + }, + "showlegend": { + "valType": "boolean", + "role": "info", + "dflt": true, + "editType": "style", + "description": "Determines whether or not an item corresponding to this trace is shown in the legend." + }, + "legendgroup": { + "valType": "string", + "role": "info", + "dflt": "", + "editType": "style", + "description": "Sets the legend group for this trace. Traces part of the same legend group hide/show at the same time when toggling legend items." + }, + "opacity": { + "valType": "number", + "role": "style", + "min": 0, + "max": 1, + "dflt": 1, + "editType": "style", + "description": "Sets the opacity of the trace." + }, + "name": { + "valType": "string", + "role": "info", + "editType": "style", + "description": "Sets the trace name. The trace name appear as the legend item and on hover." + }, + "uid": { + "valType": "string", + "role": "info", + "dflt": "", + "editType": "calc" + }, + "ids": { + "valType": "data_array", + "editType": "calc", + "description": "Assigns id labels to each datum. These ids for object constancy of data points during animation.", + "role": "data" + }, + "customdata": { + "valType": "data_array", + "editType": "calc", + "description": "Assigns extra data each datum. This may be useful when listening to hover, click and selection events. Note that, *scatter* traces also appends customdata items in the markers DOM elements", + "role": "data" + }, + "selectedpoints": { + "valType": "any", + "role": "info", + "editType": "calc", + "description": "Array containing integer indices of selected points. Has an effect only for traces that support selections. Note that an empty array means an empty selection where the `unselected` are turned on for all points, whereas, any other non-array values means no selection all where the `selected` and `unselected` styles have no effect." + }, + "hoverinfo": { + "valType": "flaglist", + "role": "info", + "flags": [ + "x", + "y", + "z", + "text", + "name" + ], + "extras": [ + "all", + "none", + "skip" + ], + "arrayOk": true, + "dflt": "all", + "editType": "none", + "description": "Determines which trace information appear on hover. If `none` or `skip` are set, no information is displayed upon hovering. But, if `none` is set, click and hover events are still fired." + }, + "hoverlabel": { + "bgcolor": { + "valType": "color", + "role": "style", + "arrayOk": true, + "editType": "none", + "description": "Sets the background color of the hover labels for this trace" + }, + "bordercolor": { + "valType": "color", + "role": "style", + "arrayOk": true, + "editType": "none", + "description": "Sets the border color of the hover labels for this trace." + }, + "font": { + "family": { + "valType": "string", + "role": "style", + "noBlank": true, + "strict": true, + "editType": "none", + "description": "HTML font family - the typeface that will be applied by the web browser. The web browser will only be able to apply a font if it is available on the system which it operates. Provide multiple font families, separated by commas, to indicate the preference in which to apply fonts if they aren't available on the system. The plotly service (at https://plot.ly or on-premise) generates images on a server, where only a select number of fonts are installed and supported. These include *Arial*, *Balto*, *Courier New*, *Droid Sans*,, *Droid Serif*, *Droid Sans Mono*, *Gravitas One*, *Old Standard TT*, *Open Sans*, *Overpass*, *PT Sans Narrow*, *Raleway*, *Times New Roman*.", + "arrayOk": true + }, + "size": { + "valType": "number", + "role": "style", + "min": 1, + "editType": "none", + "arrayOk": true + }, + "color": { + "valType": "color", + "role": "style", + "editType": "none", + "arrayOk": true + }, + "editType": "none", + "description": "Sets the font used in hover labels.", + "role": "object", + "familysrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for family .", + "editType": "none" + }, + "sizesrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for size .", + "editType": "none" + }, + "colorsrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for color .", + "editType": "none" + } + }, + "namelength": { + "valType": "integer", + "min": -1, + "arrayOk": true, + "role": "style", + "editType": "none", + "description": "Sets the length (in number of characters) of the trace name in the hover labels for this trace. -1 shows the whole name regardless of length. 0-3 shows the first 0-3 characters, and an integer >3 will show the whole name if it is less than that many characters, but if it is longer, will truncate to `namelength - 3` characters and add an ellipsis." + }, + "editType": "calc", + "role": "object", + "bgcolorsrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for bgcolor .", + "editType": "none" + }, + "bordercolorsrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for bordercolor .", + "editType": "none" + }, + "namelengthsrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for namelength .", + "editType": "none" + } + }, + "stream": { + "token": { + "valType": "string", + "noBlank": true, + "strict": true, + "role": "info", + "editType": "calc", + "description": "The stream id number links a data trace on a plot with a stream. See https://plot.ly/settings for more details." + }, + "maxpoints": { + "valType": "number", + "min": 0, + "max": 10000, + "dflt": 500, + "role": "info", + "editType": "calc", + "description": "Sets the maximum number of points to keep on the plots from an incoming stream. If `maxpoints` is set to *50*, only the newest 50 points will be displayed on the plot." + }, + "editType": "calc", + "role": "object" + }, + "x": { + "valType": "data_array", + "editType": "calc+clearAxisTypes", + "description": "Sets the sample data to be binned on the x axis.", + "role": "data" + }, + "y": { + "valType": "data_array", + "editType": "calc+clearAxisTypes", + "description": "Sets the sample data to be binned on the y axis.", + "role": "data" + }, + "z": { + "valType": "data_array", + "editType": "calc", + "description": "Sets the aggregation data.", + "role": "data" + }, + "marker": { + "color": { + "valType": "data_array", + "editType": "calc", + "description": "Sets the aggregation data.", + "role": "data" + }, + "editType": "calc", + "role": "object", + "colorsrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for color .", + "editType": "none" + } + }, + "histnorm": { + "valType": "enumerated", + "values": [ + "", + "percent", + "probability", + "density", + "probability density" + ], + "dflt": "", + "role": "style", + "editType": "calc", + "description": "Specifies the type of normalization used for this histogram trace. If **, the span of each bar corresponds to the number of occurrences (i.e. the number of data points lying inside the bins). If *percent* / *probability*, the span of each bar corresponds to the percentage / fraction of occurrences with respect to the total number of sample points (here, the sum of all bin HEIGHTS equals 100% / 1). If *density*, the span of each bar corresponds to the number of occurrences in a bin divided by the size of the bin interval (here, the sum of all bin AREAS equals the total number of sample points). If *probability density*, the area of each bar corresponds to the probability that an event will fall into the corresponding bin (here, the sum of all bin AREAS equals 1)." + }, + "histfunc": { + "valType": "enumerated", + "values": [ + "count", + "sum", + "avg", + "min", + "max" + ], + "role": "style", + "dflt": "count", + "editType": "calc", + "description": "Specifies the binning function used for this histogram trace. If *count*, the histogram values are computed by counting the number of values lying inside each bin. If *sum*, *avg*, *min*, *max*, the histogram values are computed using the sum, the average, the minimum or the maximum of the values lying inside each bin respectively." + }, + "autobinx": { + "valType": "boolean", + "dflt": null, + "role": "style", + "editType": "calc", + "impliedEdits": {}, + "description": "Determines whether or not the x axis bin attributes are picked by an algorithm. Note that this should be set to false if you want to manually set the number of bins using the attributes in xbins." + }, + "nbinsx": { + "valType": "integer", + "min": 0, + "dflt": 0, + "role": "style", + "editType": "calc", + "description": "Specifies the maximum number of desired bins. This value will be used in an algorithm that will decide the optimal bin size such that the histogram best visualizes the distribution of the data." + }, + "xbins": { + "start": { + "valType": "any", + "dflt": null, + "role": "style", + "editType": "calc", + "impliedEdits": { + "^autobinx": false + }, + "description": "Sets the starting value for the x axis bins." + }, + "end": { + "valType": "any", + "dflt": null, + "role": "style", + "editType": "calc", + "impliedEdits": { + "^autobinx": false + }, + "description": "Sets the end value for the x axis bins." + }, + "size": { + "valType": "any", + "dflt": null, + "role": "style", + "editType": "calc", + "impliedEdits": { + "^autobinx": false + }, + "description": "Sets the step in-between value each x axis bin." + }, + "editType": "calc", + "impliedEdits": { + "autobinx": false, + "role": "object" + }, + "role": "object" + }, + "autobiny": { + "valType": "boolean", + "dflt": null, + "role": "style", + "editType": "calc", + "impliedEdits": {}, + "description": "Determines whether or not the y axis bin attributes are picked by an algorithm. Note that this should be set to false if you want to manually set the number of bins using the attributes in ybins." + }, + "nbinsy": { + "valType": "integer", + "min": 0, + "dflt": 0, + "role": "style", + "editType": "calc", + "description": "Specifies the maximum number of desired bins. This value will be used in an algorithm that will decide the optimal bin size such that the histogram best visualizes the distribution of the data." + }, + "ybins": { + "start": { + "valType": "any", + "dflt": null, + "role": "style", + "editType": "calc", + "impliedEdits": { + "^autobiny": false + }, + "description": "Sets the starting value for the y axis bins." + }, + "end": { + "valType": "any", + "dflt": null, + "role": "style", + "editType": "calc", + "impliedEdits": { + "^autobiny": false + }, + "description": "Sets the end value for the y axis bins." + }, + "size": { + "valType": "any", + "dflt": null, + "role": "style", + "editType": "calc", + "impliedEdits": { + "^autobiny": false + }, + "description": "Sets the step in-between value each y axis bin." + }, + "editType": "calc", + "impliedEdits": { + "autobiny": false, + "role": "object" + }, + "role": "object" + }, + "xgap": { + "valType": "number", + "dflt": 0, + "min": 0, + "role": "style", + "editType": "plot", + "description": "Sets the horizontal gap (in pixels) between bricks." + }, + "ygap": { + "valType": "number", + "dflt": 0, + "min": 0, + "role": "style", + "editType": "plot", + "description": "Sets the vertical gap (in pixels) between bricks." + }, + "zsmooth": { + "valType": "enumerated", + "values": [ + "fast", + "best", + false + ], + "dflt": false, + "role": "style", + "editType": "calc", + "description": "Picks a smoothing algorithm use to smooth `z` data." + }, + "zhoverformat": { + "valType": "string", + "dflt": "", + "role": "style", + "editType": "none", + "description": "Sets the hover text formatting rule using d3 formatting mini-languages which are very similar to those in Python. See: https://github.com/d3/d3-format/blob/master/README.md#locale_format" + }, + "zauto": { + "valType": "boolean", + "role": "info", + "dflt": true, + "editType": "calc", + "impliedEdits": {}, + "description": "Determines the whether or not the color domain is computed with respect to the input data." + }, + "zmin": { + "valType": "number", + "role": "info", + "dflt": null, + "editType": "plot", + "impliedEdits": { + "zauto": false + }, + "description": "Sets the lower bound of color domain." + }, + "zmax": { + "valType": "number", + "role": "info", + "dflt": null, + "editType": "plot", + "impliedEdits": { + "zauto": false + }, + "description": "Sets the upper bound of color domain." + }, + "colorscale": { + "valType": "colorscale", + "role": "style", + "editType": "calc", + "impliedEdits": { + "autocolorscale": false + }, + "description": "Sets the colorscale. The colorscale must be an array containing arrays mapping a normalized value to an rgb, rgba, hex, hsl, hsv, or named color string. At minimum, a mapping for the lowest (0) and highest (1) values are required. For example, `[[0, 'rgb(0,0,255)', [1, 'rgb(255,0,0)']]`. To control the bounds of the colorscale in z space, use zmin and zmax" + }, + "autocolorscale": { + "valType": "boolean", + "role": "style", + "dflt": false, + "editType": "calc", + "impliedEdits": {}, + "description": "Determines whether or not the colorscale is picked using the sign of the input z values." + }, + "reversescale": { + "valType": "boolean", + "role": "style", + "dflt": false, + "editType": "calc", + "description": "Reverses the colorscale." + }, + "showscale": { + "valType": "boolean", + "role": "info", + "dflt": true, + "editType": "calc", + "description": "Determines whether or not a colorbar is displayed for this trace." + }, + "colorbar": { + "thicknessmode": { + "valType": "enumerated", + "values": [ + "fraction", + "pixels" + ], + "role": "style", + "dflt": "pixels", + "description": "Determines whether this color bar's thickness (i.e. the measure in the constant color direction) is set in units of plot *fraction* or in *pixels*. Use `thickness` to set the value.", + "editType": "colorbars" + }, + "thickness": { + "valType": "number", + "role": "style", + "min": 0, + "dflt": 30, + "description": "Sets the thickness of the color bar This measure excludes the size of the padding, ticks and labels.", + "editType": "colorbars" + }, + "lenmode": { + "valType": "enumerated", + "values": [ + "fraction", + "pixels" + ], + "role": "info", + "dflt": "fraction", + "description": "Determines whether this color bar's length (i.e. the measure in the color variation direction) is set in units of plot *fraction* or in *pixels. Use `len` to set the value.", + "editType": "colorbars" + }, + "len": { + "valType": "number", + "min": 0, + "dflt": 1, + "role": "style", + "description": "Sets the length of the color bar This measure excludes the padding of both ends. That is, the color bar length is this length minus the padding on both ends.", + "editType": "colorbars" + }, + "x": { + "valType": "number", + "dflt": 1.02, + "min": -2, + "max": 3, + "role": "style", + "description": "Sets the x position of the color bar (in plot fraction).", + "editType": "colorbars" + }, + "xanchor": { + "valType": "enumerated", + "values": [ + "left", + "center", + "right" + ], + "dflt": "left", + "role": "style", + "description": "Sets this color bar's horizontal position anchor. This anchor binds the `x` position to the *left*, *center* or *right* of the color bar.", + "editType": "colorbars" + }, + "xpad": { + "valType": "number", + "role": "style", + "min": 0, + "dflt": 10, + "description": "Sets the amount of padding (in px) along the x direction.", + "editType": "colorbars" + }, + "y": { + "valType": "number", + "role": "style", + "dflt": 0.5, + "min": -2, + "max": 3, + "description": "Sets the y position of the color bar (in plot fraction).", + "editType": "colorbars" + }, + "yanchor": { + "valType": "enumerated", + "values": [ + "top", + "middle", + "bottom" + ], + "role": "style", + "dflt": "middle", + "description": "Sets this color bar's vertical position anchor This anchor binds the `y` position to the *top*, *middle* or *bottom* of the color bar.", + "editType": "colorbars" + }, + "ypad": { + "valType": "number", + "role": "style", + "min": 0, + "dflt": 10, + "description": "Sets the amount of padding (in px) along the y direction.", + "editType": "colorbars" + }, + "outlinecolor": { + "valType": "color", + "dflt": "#444", + "role": "style", + "editType": "colorbars", + "description": "Sets the axis line color." + }, + "outlinewidth": { + "valType": "number", + "min": 0, + "dflt": 1, + "role": "style", + "editType": "colorbars", + "description": "Sets the width (in px) of the axis line." + }, + "bordercolor": { + "valType": "color", + "dflt": "#444", + "role": "style", + "editType": "colorbars", + "description": "Sets the axis line color." + }, + "borderwidth": { + "valType": "number", + "role": "style", + "min": 0, + "dflt": 0, + "description": "Sets the width (in px) or the border enclosing this color bar.", + "editType": "colorbars" + }, + "bgcolor": { + "valType": "color", + "role": "style", + "dflt": "rgba(0,0,0,0)", + "description": "Sets the color of padded area.", + "editType": "colorbars" + }, + "tickmode": { + "valType": "enumerated", + "values": [ + "auto", + "linear", + "array" + ], + "role": "info", + "editType": "colorbars", + "impliedEdits": {}, + "description": "Sets the tick mode for this axis. If *auto*, the number of ticks is set via `nticks`. If *linear*, the placement of the ticks is determined by a starting position `tick0` and a tick step `dtick` (*linear* is the default value if `tick0` and `dtick` are provided). If *array*, the placement of the ticks is set via `tickvals` and the tick text is `ticktext`. (*array* is the default value if `tickvals` is provided)." + }, + "nticks": { + "valType": "integer", + "min": 0, + "dflt": 0, + "role": "style", + "editType": "colorbars", + "description": "Specifies the maximum number of ticks for the particular axis. The actual number of ticks will be chosen automatically to be less than or equal to `nticks`. Has an effect only if `tickmode` is set to *auto*." + }, + "tick0": { + "valType": "any", + "role": "style", + "editType": "colorbars", + "impliedEdits": { + "tickmode": "linear" + }, + "description": "Sets the placement of the first tick on this axis. Use with `dtick`. If the axis `type` is *log*, then you must take the log of your starting tick (e.g. to set the starting tick to 100, set the `tick0` to 2) except when `dtick`=*L* (see `dtick` for more info). If the axis `type` is *date*, it should be a date string, like date data. If the axis `type` is *category*, it should be a number, using the scale where each category is assigned a serial number from zero in the order it appears." + }, + "dtick": { + "valType": "any", + "role": "style", + "editType": "colorbars", + "impliedEdits": { + "tickmode": "linear" + }, + "description": "Sets the step in-between ticks on this axis. Use with `tick0`. Must be a positive number, or special strings available to *log* and *date* axes. If the axis `type` is *log*, then ticks are set every 10^(n*dtick) where n is the tick number. For example, to set a tick mark at 1, 10, 100, 1000, ... set dtick to 1. To set tick marks at 1, 100, 10000, ... set dtick to 2. To set tick marks at 1, 5, 25, 125, 625, 3125, ... set dtick to log_10(5), or 0.69897000433. *log* has several special values; *L*, where `f` is a positive number, gives ticks linearly spaced in value (but not position). For example `tick0` = 0.1, `dtick` = *L0.5* will put ticks at 0.1, 0.6, 1.1, 1.6 etc. To show powers of 10 plus small digits between, use *D1* (all digits) or *D2* (only 2 and 5). `tick0` is ignored for *D1* and *D2*. If the axis `type` is *date*, then you must convert the time to milliseconds. For example, to set the interval between ticks to one day, set `dtick` to 86400000.0. *date* also has special values *M* gives ticks spaced by a number of months. `n` must be a positive integer. To set ticks on the 15th of every third month, set `tick0` to *2000-01-15* and `dtick` to *M3*. To set ticks every 4 years, set `dtick` to *M48*" + }, + "tickvals": { + "valType": "data_array", + "editType": "colorbars", + "description": "Sets the values at which ticks on this axis appear. Only has an effect if `tickmode` is set to *array*. Used with `ticktext`.", + "role": "data" + }, + "ticktext": { + "valType": "data_array", + "editType": "colorbars", + "description": "Sets the text displayed at the ticks position via `tickvals`. Only has an effect if `tickmode` is set to *array*. Used with `tickvals`.", + "role": "data" + }, + "ticks": { + "valType": "enumerated", + "values": [ + "outside", + "inside", + "" + ], + "role": "style", + "editType": "colorbars", + "description": "Determines whether ticks are drawn or not. If **, this axis' ticks are not drawn. If *outside* (*inside*), this axis' are drawn outside (inside) the axis lines.", + "dflt": "" + }, + "ticklen": { + "valType": "number", + "min": 0, + "dflt": 5, + "role": "style", + "editType": "colorbars", + "description": "Sets the tick length (in px)." + }, + "tickwidth": { + "valType": "number", + "min": 0, + "dflt": 1, + "role": "style", + "editType": "colorbars", + "description": "Sets the tick width (in px)." + }, + "tickcolor": { + "valType": "color", + "dflt": "#444", + "role": "style", + "editType": "colorbars", + "description": "Sets the tick color." + }, + "showticklabels": { + "valType": "boolean", + "dflt": true, + "role": "style", + "editType": "colorbars", + "description": "Determines whether or not the tick labels are drawn." + }, + "tickfont": { + "family": { + "valType": "string", + "role": "style", + "noBlank": true, + "strict": true, + "description": "HTML font family - the typeface that will be applied by the web browser. The web browser will only be able to apply a font if it is available on the system which it operates. Provide multiple font families, separated by commas, to indicate the preference in which to apply fonts if they aren't available on the system. The plotly service (at https://plot.ly or on-premise) generates images on a server, where only a select number of fonts are installed and supported. These include *Arial*, *Balto*, *Courier New*, *Droid Sans*,, *Droid Serif*, *Droid Sans Mono*, *Gravitas One*, *Old Standard TT*, *Open Sans*, *Overpass*, *PT Sans Narrow*, *Raleway*, *Times New Roman*.", + "editType": "colorbars" + }, + "size": { + "valType": "number", + "role": "style", + "min": 1, + "editType": "colorbars" + }, + "color": { + "valType": "color", + "role": "style", + "editType": "colorbars" + }, + "description": "Sets the color bar's tick label font", + "editType": "colorbars", + "role": "object" + }, + "tickangle": { + "valType": "angle", + "dflt": "auto", + "role": "style", + "editType": "colorbars", + "description": "Sets the angle of the tick labels with respect to the horizontal. For example, a `tickangle` of -90 draws the tick labels vertically." + }, + "tickformat": { + "valType": "string", + "dflt": "", + "role": "style", + "editType": "colorbars", + "description": "Sets the tick label formatting rule using d3 formatting mini-languages which are very similar to those in Python. For numbers, see: https://github.com/d3/d3-format/blob/master/README.md#locale_format And for dates see: https://github.com/d3/d3-time-format/blob/master/README.md#locale_format We add one item to d3's date formatter: *%{n}f* for fractional seconds with n digits. For example, *2016-10-13 09:15:23.456* with tickformat *%H~%M~%S.%2f* would display *09~15~23.46*" + }, + "tickformatstops": { + "items": { + "tickformatstop": { + "dtickrange": { + "valType": "info_array", + "role": "info", + "items": [ + { + "valType": "any", + "editType": "colorbars" + }, + { + "valType": "any", + "editType": "colorbars" + } + ], + "editType": "colorbars", + "description": "range [*min*, *max*], where *min*, *max* - dtick values which describe some zoom level, it is possible to omit *min* or *max* value by passing *null*" + }, + "value": { + "valType": "string", + "dflt": "", + "role": "style", + "editType": "colorbars", + "description": "string - dtickformat for described zoom level, the same as *tickformat*" + }, + "editType": "colorbars", + "role": "object" + } + }, + "role": "object" + }, + "tickprefix": { + "valType": "string", + "dflt": "", + "role": "style", + "editType": "colorbars", + "description": "Sets a tick label prefix." + }, + "showtickprefix": { + "valType": "enumerated", + "values": [ + "all", + "first", + "last", + "none" + ], + "dflt": "all", + "role": "style", + "editType": "colorbars", + "description": "If *all*, all tick labels are displayed with a prefix. If *first*, only the first tick is displayed with a prefix. If *last*, only the last tick is displayed with a suffix. If *none*, tick prefixes are hidden." + }, + "ticksuffix": { + "valType": "string", + "dflt": "", + "role": "style", + "editType": "colorbars", + "description": "Sets a tick label suffix." + }, + "showticksuffix": { + "valType": "enumerated", + "values": [ + "all", + "first", + "last", + "none" + ], + "dflt": "all", + "role": "style", + "editType": "colorbars", + "description": "Same as `showtickprefix` but for tick suffixes." + }, + "separatethousands": { + "valType": "boolean", + "dflt": false, + "role": "style", + "editType": "colorbars", + "description": "If \"true\", even 4-digit integers are separated" + }, + "exponentformat": { + "valType": "enumerated", + "values": [ + "none", + "e", + "E", + "power", + "SI", + "B" + ], + "dflt": "B", + "role": "style", + "editType": "colorbars", + "description": "Determines a formatting rule for the tick exponents. For example, consider the number 1,000,000,000. If *none*, it appears as 1,000,000,000. If *e*, 1e+9. If *E*, 1E+9. If *power*, 1x10^9 (with 9 in a super script). If *SI*, 1G. If *B*, 1B." + }, + "showexponent": { + "valType": "enumerated", + "values": [ + "all", + "first", + "last", + "none" + ], + "dflt": "all", + "role": "style", + "editType": "colorbars", + "description": "If *all*, all exponents are shown besides their significands. If *first*, only the exponent of the first tick is shown. If *last*, only the exponent of the last tick is shown. If *none*, no exponents appear." + }, + "title": { + "valType": "string", + "role": "info", + "dflt": "Click to enter colorscale title", + "description": "Sets the title of the color bar.", + "editType": "colorbars" + }, + "titlefont": { + "family": { + "valType": "string", + "role": "style", + "noBlank": true, + "strict": true, + "description": "HTML font family - the typeface that will be applied by the web browser. The web browser will only be able to apply a font if it is available on the system which it operates. Provide multiple font families, separated by commas, to indicate the preference in which to apply fonts if they aren't available on the system. The plotly service (at https://plot.ly or on-premise) generates images on a server, where only a select number of fonts are installed and supported. These include *Arial*, *Balto*, *Courier New*, *Droid Sans*,, *Droid Serif*, *Droid Sans Mono*, *Gravitas One*, *Old Standard TT*, *Open Sans*, *Overpass*, *PT Sans Narrow*, *Raleway*, *Times New Roman*.", + "editType": "colorbars" + }, + "size": { + "valType": "number", + "role": "style", + "min": 1, + "editType": "colorbars" + }, + "color": { + "valType": "color", + "role": "style", + "editType": "colorbars" + }, + "description": "Sets this color bar's title font.", + "editType": "colorbars", + "role": "object" + }, + "titleside": { + "valType": "enumerated", + "values": [ + "right", + "top", + "bottom" + ], + "role": "style", + "dflt": "top", + "description": "Determines the location of the colorbar title with respect to the color bar.", + "editType": "colorbars" + }, + "editType": "colorbars", + "role": "object", + "tickvalssrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for tickvals .", + "editType": "none" + }, + "ticktextsrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for ticktext .", + "editType": "none" + } + }, + "xcalendar": { + "valType": "enumerated", + "values": [ + "gregorian", + "chinese", + "coptic", + "discworld", + "ethiopian", + "hebrew", + "islamic", + "julian", + "mayan", + "nanakshahi", + "nepali", + "persian", + "jalali", + "taiwan", + "thai", + "ummalqura" + ], + "role": "info", + "editType": "calc", + "dflt": "gregorian", + "description": "Sets the calendar system to use with `x` date data." + }, + "ycalendar": { + "valType": "enumerated", + "values": [ + "gregorian", + "chinese", + "coptic", + "discworld", + "ethiopian", + "hebrew", + "islamic", + "julian", + "mayan", + "nanakshahi", + "nepali", + "persian", + "jalali", + "taiwan", + "thai", + "ummalqura" + ], + "role": "info", + "editType": "calc", + "dflt": "gregorian", + "description": "Sets the calendar system to use with `y` date data." + }, + "xaxis": { + "valType": "subplotid", + "role": "info", + "dflt": "x", + "editType": "calc+clearAxisTypes", + "description": "Sets a reference between this trace's x coordinates and a 2D cartesian x axis. If *x* (the default value), the x coordinates refer to `layout.xaxis`. If *x2*, the x coordinates refer to `layout.xaxis2`, and so on." + }, + "yaxis": { + "valType": "subplotid", + "role": "info", + "dflt": "y", + "editType": "calc+clearAxisTypes", + "description": "Sets a reference between this trace's y coordinates and a 2D cartesian y axis. If *y* (the default value), the y coordinates refer to `layout.yaxis`. If *y2*, the y coordinates refer to `layout.xaxis2`, and so on." + }, + "idssrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for ids .", + "editType": "none" + }, + "customdatasrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for customdata .", + "editType": "none" + }, + "hoverinfosrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for hoverinfo .", + "editType": "none" + }, + "xsrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for x .", + "editType": "none" + }, + "ysrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for y .", + "editType": "none" + }, + "zsrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for z .", + "editType": "none" + } + } + }, + "histogram2dcontour": { + "meta": { + "hrName": "histogram_2d_contour", + "description": "The sample data from which statistics are computed is set in `x` and `y` (where `x` and `y` represent marginal distributions, binning is set in `xbins` and `ybins` in this case) or `z` (where `z` represent the 2D distribution and binning set, binning is set by `x` and `y` in this case). The resulting distribution is visualized as a contour plot." + }, + "attributes": { + "type": "histogram2dcontour", + "visible": { + "valType": "enumerated", + "values": [ + true, + false, + "legendonly" + ], + "role": "info", + "dflt": true, + "editType": "calc", + "description": "Determines whether or not this trace is visible. If *legendonly*, the trace is not drawn, but can appear as a legend item (provided that the legend itself is visible)." + }, + "showlegend": { + "valType": "boolean", + "role": "info", + "dflt": true, + "editType": "style", + "description": "Determines whether or not an item corresponding to this trace is shown in the legend." + }, + "legendgroup": { + "valType": "string", + "role": "info", + "dflt": "", + "editType": "style", + "description": "Sets the legend group for this trace. Traces part of the same legend group hide/show at the same time when toggling legend items." + }, + "opacity": { + "valType": "number", + "role": "style", + "min": 0, + "max": 1, + "dflt": 1, + "editType": "style", + "description": "Sets the opacity of the trace." + }, + "name": { + "valType": "string", + "role": "info", + "editType": "style", + "description": "Sets the trace name. The trace name appear as the legend item and on hover." + }, + "uid": { + "valType": "string", + "role": "info", + "dflt": "", + "editType": "calc" + }, + "ids": { + "valType": "data_array", + "editType": "calc", + "description": "Assigns id labels to each datum. These ids for object constancy of data points during animation.", + "role": "data" + }, + "customdata": { + "valType": "data_array", + "editType": "calc", + "description": "Assigns extra data each datum. This may be useful when listening to hover, click and selection events. Note that, *scatter* traces also appends customdata items in the markers DOM elements", + "role": "data" + }, + "selectedpoints": { + "valType": "any", + "role": "info", + "editType": "calc", + "description": "Array containing integer indices of selected points. Has an effect only for traces that support selections. Note that an empty array means an empty selection where the `unselected` are turned on for all points, whereas, any other non-array values means no selection all where the `selected` and `unselected` styles have no effect." + }, + "hoverinfo": { + "valType": "flaglist", + "role": "info", + "flags": [ + "x", + "y", + "z", + "text", + "name" + ], + "extras": [ + "all", + "none", + "skip" + ], + "arrayOk": true, + "dflt": "all", + "editType": "none", + "description": "Determines which trace information appear on hover. If `none` or `skip` are set, no information is displayed upon hovering. But, if `none` is set, click and hover events are still fired." + }, + "hoverlabel": { + "bgcolor": { + "valType": "color", + "role": "style", + "arrayOk": true, + "editType": "none", + "description": "Sets the background color of the hover labels for this trace" + }, + "bordercolor": { + "valType": "color", + "role": "style", + "arrayOk": true, + "editType": "none", + "description": "Sets the border color of the hover labels for this trace." + }, + "font": { + "family": { + "valType": "string", + "role": "style", + "noBlank": true, + "strict": true, + "editType": "none", + "description": "HTML font family - the typeface that will be applied by the web browser. The web browser will only be able to apply a font if it is available on the system which it operates. Provide multiple font families, separated by commas, to indicate the preference in which to apply fonts if they aren't available on the system. The plotly service (at https://plot.ly or on-premise) generates images on a server, where only a select number of fonts are installed and supported. These include *Arial*, *Balto*, *Courier New*, *Droid Sans*,, *Droid Serif*, *Droid Sans Mono*, *Gravitas One*, *Old Standard TT*, *Open Sans*, *Overpass*, *PT Sans Narrow*, *Raleway*, *Times New Roman*.", + "arrayOk": true + }, + "size": { + "valType": "number", + "role": "style", + "min": 1, + "editType": "none", + "arrayOk": true + }, + "color": { + "valType": "color", + "role": "style", + "editType": "none", + "arrayOk": true + }, + "editType": "none", + "description": "Sets the font used in hover labels.", + "role": "object", + "familysrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for family .", + "editType": "none" + }, + "sizesrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for size .", + "editType": "none" + }, + "colorsrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for color .", + "editType": "none" + } + }, + "namelength": { + "valType": "integer", + "min": -1, + "arrayOk": true, + "role": "style", + "editType": "none", + "description": "Sets the length (in number of characters) of the trace name in the hover labels for this trace. -1 shows the whole name regardless of length. 0-3 shows the first 0-3 characters, and an integer >3 will show the whole name if it is less than that many characters, but if it is longer, will truncate to `namelength - 3` characters and add an ellipsis." + }, + "editType": "calc", + "role": "object", + "bgcolorsrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for bgcolor .", + "editType": "none" + }, + "bordercolorsrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for bordercolor .", + "editType": "none" + }, + "namelengthsrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for namelength .", + "editType": "none" + } + }, + "stream": { + "token": { + "valType": "string", + "noBlank": true, + "strict": true, + "role": "info", + "editType": "calc", + "description": "The stream id number links a data trace on a plot with a stream. See https://plot.ly/settings for more details." + }, + "maxpoints": { + "valType": "number", + "min": 0, + "max": 10000, + "dflt": 500, + "role": "info", + "editType": "calc", + "description": "Sets the maximum number of points to keep on the plots from an incoming stream. If `maxpoints` is set to *50*, only the newest 50 points will be displayed on the plot." + }, + "editType": "calc", + "role": "object" + }, + "x": { + "valType": "data_array", + "editType": "calc+clearAxisTypes", + "description": "Sets the sample data to be binned on the x axis.", + "role": "data" + }, + "y": { + "valType": "data_array", + "editType": "calc+clearAxisTypes", + "description": "Sets the sample data to be binned on the y axis.", + "role": "data" + }, + "z": { + "valType": "data_array", + "editType": "calc", + "description": "Sets the aggregation data.", + "role": "data" + }, + "marker": { + "color": { + "valType": "data_array", + "editType": "calc", + "description": "Sets the aggregation data.", + "role": "data" + }, + "editType": "calc", + "role": "object", + "colorsrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for color .", + "editType": "none" + } + }, + "histnorm": { + "valType": "enumerated", + "values": [ + "", + "percent", + "probability", + "density", + "probability density" + ], + "dflt": "", + "role": "style", + "editType": "calc", + "description": "Specifies the type of normalization used for this histogram trace. If **, the span of each bar corresponds to the number of occurrences (i.e. the number of data points lying inside the bins). If *percent* / *probability*, the span of each bar corresponds to the percentage / fraction of occurrences with respect to the total number of sample points (here, the sum of all bin HEIGHTS equals 100% / 1). If *density*, the span of each bar corresponds to the number of occurrences in a bin divided by the size of the bin interval (here, the sum of all bin AREAS equals the total number of sample points). If *probability density*, the area of each bar corresponds to the probability that an event will fall into the corresponding bin (here, the sum of all bin AREAS equals 1)." + }, + "histfunc": { + "valType": "enumerated", + "values": [ + "count", + "sum", + "avg", + "min", + "max" + ], + "role": "style", + "dflt": "count", + "editType": "calc", + "description": "Specifies the binning function used for this histogram trace. If *count*, the histogram values are computed by counting the number of values lying inside each bin. If *sum*, *avg*, *min*, *max*, the histogram values are computed using the sum, the average, the minimum or the maximum of the values lying inside each bin respectively." + }, + "autobinx": { + "valType": "boolean", + "dflt": null, + "role": "style", + "editType": "calc", + "impliedEdits": {}, + "description": "Determines whether or not the x axis bin attributes are picked by an algorithm. Note that this should be set to false if you want to manually set the number of bins using the attributes in xbins." + }, + "nbinsx": { + "valType": "integer", + "min": 0, + "dflt": 0, + "role": "style", + "editType": "calc", + "description": "Specifies the maximum number of desired bins. This value will be used in an algorithm that will decide the optimal bin size such that the histogram best visualizes the distribution of the data." + }, + "xbins": { + "start": { + "valType": "any", + "dflt": null, + "role": "style", + "editType": "calc", + "impliedEdits": { + "^autobinx": false + }, + "description": "Sets the starting value for the x axis bins." + }, + "end": { + "valType": "any", + "dflt": null, + "role": "style", + "editType": "calc", + "impliedEdits": { + "^autobinx": false + }, + "description": "Sets the end value for the x axis bins." + }, + "size": { + "valType": "any", + "dflt": null, + "role": "style", + "editType": "calc", + "impliedEdits": { + "^autobinx": false + }, + "description": "Sets the step in-between value each x axis bin." + }, + "editType": "calc", + "impliedEdits": { + "autobinx": false, + "role": "object" + }, + "role": "object" + }, + "autobiny": { + "valType": "boolean", + "dflt": null, + "role": "style", + "editType": "calc", + "impliedEdits": {}, + "description": "Determines whether or not the y axis bin attributes are picked by an algorithm. Note that this should be set to false if you want to manually set the number of bins using the attributes in ybins." + }, + "nbinsy": { + "valType": "integer", + "min": 0, + "dflt": 0, + "role": "style", + "editType": "calc", + "description": "Specifies the maximum number of desired bins. This value will be used in an algorithm that will decide the optimal bin size such that the histogram best visualizes the distribution of the data." + }, + "ybins": { + "start": { + "valType": "any", + "dflt": null, + "role": "style", + "editType": "calc", + "impliedEdits": { + "^autobiny": false + }, + "description": "Sets the starting value for the y axis bins." + }, + "end": { + "valType": "any", + "dflt": null, + "role": "style", + "editType": "calc", + "impliedEdits": { + "^autobiny": false + }, + "description": "Sets the end value for the y axis bins." + }, + "size": { + "valType": "any", + "dflt": null, + "role": "style", + "editType": "calc", + "impliedEdits": { + "^autobiny": false + }, + "description": "Sets the step in-between value each y axis bin." + }, + "editType": "calc", + "impliedEdits": { + "autobiny": false, + "role": "object" + }, + "role": "object" + }, + "autocontour": { + "valType": "boolean", + "dflt": true, + "role": "style", + "editType": "calc", + "impliedEdits": {}, + "description": "Determines whether or not the contour level attributes are picked by an algorithm. If *true*, the number of contour levels can be set in `ncontours`. If *false*, set the contour level attributes in `contours`." + }, + "ncontours": { + "valType": "integer", + "dflt": 15, + "min": 1, + "role": "style", + "editType": "calc", + "description": "Sets the maximum number of contour levels. The actual number of contours will be chosen automatically to be less than or equal to the value of `ncontours`. Has an effect only if `autocontour` is *true* or if `contours.size` is missing." + }, + "contours": { + "start": { + "valType": "number", + "dflt": null, + "role": "style", + "editType": "plot", + "impliedEdits": { + "^autocontour": false + }, + "description": "Sets the starting contour level value. Must be less than `contours.end`" + }, + "end": { + "valType": "number", + "dflt": null, + "role": "style", + "editType": "plot", + "impliedEdits": { + "^autocontour": false + }, + "description": "Sets the end contour level value. Must be more than `contours.start`" + }, + "size": { + "valType": "number", + "dflt": null, + "min": 0, + "role": "style", + "editType": "plot", + "impliedEdits": { + "^autocontour": false + }, + "description": "Sets the step between each contour level. Must be positive." + }, + "coloring": { + "valType": "enumerated", + "values": [ + "fill", + "heatmap", + "lines", + "none" + ], + "dflt": "fill", + "role": "style", + "editType": "calc", + "description": "Determines the coloring method showing the contour values. If *fill*, coloring is done evenly between each contour level If *heatmap*, a heatmap gradient coloring is applied between each contour level. If *lines*, coloring is done on the contour lines. If *none*, no coloring is applied on this trace." + }, + "showlines": { + "valType": "boolean", + "dflt": true, + "role": "style", + "editType": "plot", + "description": "Determines whether or not the contour lines are drawn. Has an effect only if `contours.coloring` is set to *fill*." + }, + "showlabels": { + "valType": "boolean", + "dflt": false, + "role": "style", + "editType": "plot", + "description": "Determines whether to label the contour lines with their values." + }, + "labelfont": { + "family": { + "valType": "string", + "role": "style", + "noBlank": true, + "strict": true, + "editType": "plot", + "description": "HTML font family - the typeface that will be applied by the web browser. The web browser will only be able to apply a font if it is available on the system which it operates. Provide multiple font families, separated by commas, to indicate the preference in which to apply fonts if they aren't available on the system. The plotly service (at https://plot.ly or on-premise) generates images on a server, where only a select number of fonts are installed and supported. These include *Arial*, *Balto*, *Courier New*, *Droid Sans*,, *Droid Serif*, *Droid Sans Mono*, *Gravitas One*, *Old Standard TT*, *Open Sans*, *Overpass*, *PT Sans Narrow*, *Raleway*, *Times New Roman*." + }, + "size": { + "valType": "number", + "role": "style", + "min": 1, + "editType": "plot" + }, + "color": { + "valType": "color", + "role": "style", + "editType": "style" + }, + "editType": "plot", + "description": "Sets the font used for labeling the contour levels. The default color comes from the lines, if shown. The default family and size come from `layout.font`.", + "role": "object" + }, + "labelformat": { + "valType": "string", + "dflt": "", + "role": "style", + "editType": "plot", + "description": "Sets the contour label formatting rule using d3 formatting mini-language which is very similar to Python, see: https://github.com/d3/d3-format/blob/master/README.md#locale_format." + }, + "editType": "calc", + "impliedEdits": { + "autocontour": false, + "role": "object" + }, + "role": "object" + }, + "line": { + "color": { + "valType": "color", + "role": "style", + "editType": "style+colorbars", + "description": "Sets the color of the contour level. Has no effect if `contours.coloring` is set to *lines*." + }, + "width": { + "valType": "number", + "min": 0, + "dflt": 2, + "role": "style", + "editType": "style+colorbars", + "description": "Sets the line width (in px)." + }, + "dash": { + "valType": "string", + "values": [ + "solid", + "dot", + "dash", + "longdash", + "dashdot", + "longdashdot" + ], + "dflt": "solid", + "role": "style", + "editType": "style", + "description": "Sets the dash style of lines. Set to a dash type string (*solid*, *dot*, *dash*, *longdash*, *dashdot*, or *longdashdot*) or a dash length list in px (eg *5px,10px,2px,2px*)." + }, + "smoothing": { + "valType": "number", + "min": 0, + "max": 1.3, + "dflt": 1, + "role": "style", + "editType": "plot", + "description": "Sets the amount of smoothing for the contour lines, where *0* corresponds to no smoothing." + }, + "editType": "plot", + "role": "object" + }, + "zhoverformat": { + "valType": "string", + "dflt": "", + "role": "style", + "editType": "none", + "description": "Sets the hover text formatting rule using d3 formatting mini-languages which are very similar to those in Python. See: https://github.com/d3/d3-format/blob/master/README.md#locale_format" + }, + "zauto": { + "valType": "boolean", + "role": "info", + "dflt": true, + "editType": "calc", + "impliedEdits": {}, + "description": "Determines the whether or not the color domain is computed with respect to the input data." + }, + "zmin": { + "valType": "number", + "role": "info", + "dflt": null, + "editType": "calc", + "impliedEdits": { + "zauto": false + }, + "description": "Sets the lower bound of color domain." + }, + "zmax": { + "valType": "number", + "role": "info", + "dflt": null, + "editType": "calc", + "impliedEdits": { + "zauto": false + }, + "description": "Sets the upper bound of color domain." + }, + "colorscale": { + "valType": "colorscale", + "role": "style", + "editType": "calc", + "impliedEdits": { + "autocolorscale": false + }, + "description": "Sets the colorscale. The colorscale must be an array containing arrays mapping a normalized value to an rgb, rgba, hex, hsl, hsv, or named color string. At minimum, a mapping for the lowest (0) and highest (1) values are required. For example, `[[0, 'rgb(0,0,255)', [1, 'rgb(255,0,0)']]`. To control the bounds of the colorscale in z space, use zmin and zmax" + }, + "autocolorscale": { + "valType": "boolean", + "role": "style", + "dflt": true, + "editType": "calc", + "impliedEdits": {}, + "description": "Determines whether or not the colorscale is picked using the sign of the input z values." + }, + "reversescale": { + "valType": "boolean", + "role": "style", + "dflt": false, + "editType": "calc", + "description": "Reverses the colorscale." + }, + "showscale": { + "valType": "boolean", + "role": "info", + "dflt": true, + "editType": "calc", + "description": "Determines whether or not a colorbar is displayed for this trace." + }, + "colorbar": { + "thicknessmode": { + "valType": "enumerated", + "values": [ + "fraction", + "pixels" + ], + "role": "style", + "dflt": "pixels", + "description": "Determines whether this color bar's thickness (i.e. the measure in the constant color direction) is set in units of plot *fraction* or in *pixels*. Use `thickness` to set the value.", + "editType": "colorbars" + }, + "thickness": { + "valType": "number", + "role": "style", + "min": 0, + "dflt": 30, + "description": "Sets the thickness of the color bar This measure excludes the size of the padding, ticks and labels.", + "editType": "colorbars" + }, + "lenmode": { + "valType": "enumerated", + "values": [ + "fraction", + "pixels" + ], + "role": "info", + "dflt": "fraction", + "description": "Determines whether this color bar's length (i.e. the measure in the color variation direction) is set in units of plot *fraction* or in *pixels. Use `len` to set the value.", + "editType": "colorbars" + }, + "len": { + "valType": "number", + "min": 0, + "dflt": 1, + "role": "style", + "description": "Sets the length of the color bar This measure excludes the padding of both ends. That is, the color bar length is this length minus the padding on both ends.", + "editType": "colorbars" + }, + "x": { + "valType": "number", + "dflt": 1.02, + "min": -2, + "max": 3, + "role": "style", + "description": "Sets the x position of the color bar (in plot fraction).", + "editType": "colorbars" + }, + "xanchor": { + "valType": "enumerated", + "values": [ + "left", + "center", + "right" + ], + "dflt": "left", + "role": "style", + "description": "Sets this color bar's horizontal position anchor. This anchor binds the `x` position to the *left*, *center* or *right* of the color bar.", + "editType": "colorbars" + }, + "xpad": { + "valType": "number", + "role": "style", + "min": 0, + "dflt": 10, + "description": "Sets the amount of padding (in px) along the x direction.", + "editType": "colorbars" + }, + "y": { + "valType": "number", + "role": "style", + "dflt": 0.5, + "min": -2, + "max": 3, + "description": "Sets the y position of the color bar (in plot fraction).", + "editType": "colorbars" + }, + "yanchor": { + "valType": "enumerated", + "values": [ + "top", + "middle", + "bottom" + ], + "role": "style", + "dflt": "middle", + "description": "Sets this color bar's vertical position anchor This anchor binds the `y` position to the *top*, *middle* or *bottom* of the color bar.", + "editType": "colorbars" + }, + "ypad": { + "valType": "number", + "role": "style", + "min": 0, + "dflt": 10, + "description": "Sets the amount of padding (in px) along the y direction.", + "editType": "colorbars" + }, + "outlinecolor": { + "valType": "color", + "dflt": "#444", + "role": "style", + "editType": "colorbars", + "description": "Sets the axis line color." + }, + "outlinewidth": { + "valType": "number", + "min": 0, + "dflt": 1, + "role": "style", + "editType": "colorbars", + "description": "Sets the width (in px) of the axis line." + }, + "bordercolor": { + "valType": "color", + "dflt": "#444", + "role": "style", + "editType": "colorbars", + "description": "Sets the axis line color." + }, + "borderwidth": { + "valType": "number", + "role": "style", + "min": 0, + "dflt": 0, + "description": "Sets the width (in px) or the border enclosing this color bar.", + "editType": "colorbars" + }, + "bgcolor": { + "valType": "color", + "role": "style", + "dflt": "rgba(0,0,0,0)", + "description": "Sets the color of padded area.", + "editType": "colorbars" + }, + "tickmode": { + "valType": "enumerated", + "values": [ + "auto", + "linear", + "array" + ], + "role": "info", + "editType": "colorbars", + "impliedEdits": {}, + "description": "Sets the tick mode for this axis. If *auto*, the number of ticks is set via `nticks`. If *linear*, the placement of the ticks is determined by a starting position `tick0` and a tick step `dtick` (*linear* is the default value if `tick0` and `dtick` are provided). If *array*, the placement of the ticks is set via `tickvals` and the tick text is `ticktext`. (*array* is the default value if `tickvals` is provided)." + }, + "nticks": { + "valType": "integer", + "min": 0, + "dflt": 0, + "role": "style", + "editType": "colorbars", + "description": "Specifies the maximum number of ticks for the particular axis. The actual number of ticks will be chosen automatically to be less than or equal to `nticks`. Has an effect only if `tickmode` is set to *auto*." + }, + "tick0": { + "valType": "any", + "role": "style", + "editType": "colorbars", + "impliedEdits": { + "tickmode": "linear" + }, + "description": "Sets the placement of the first tick on this axis. Use with `dtick`. If the axis `type` is *log*, then you must take the log of your starting tick (e.g. to set the starting tick to 100, set the `tick0` to 2) except when `dtick`=*L* (see `dtick` for more info). If the axis `type` is *date*, it should be a date string, like date data. If the axis `type` is *category*, it should be a number, using the scale where each category is assigned a serial number from zero in the order it appears." + }, + "dtick": { + "valType": "any", + "role": "style", + "editType": "colorbars", + "impliedEdits": { + "tickmode": "linear" + }, + "description": "Sets the step in-between ticks on this axis. Use with `tick0`. Must be a positive number, or special strings available to *log* and *date* axes. If the axis `type` is *log*, then ticks are set every 10^(n*dtick) where n is the tick number. For example, to set a tick mark at 1, 10, 100, 1000, ... set dtick to 1. To set tick marks at 1, 100, 10000, ... set dtick to 2. To set tick marks at 1, 5, 25, 125, 625, 3125, ... set dtick to log_10(5), or 0.69897000433. *log* has several special values; *L*, where `f` is a positive number, gives ticks linearly spaced in value (but not position). For example `tick0` = 0.1, `dtick` = *L0.5* will put ticks at 0.1, 0.6, 1.1, 1.6 etc. To show powers of 10 plus small digits between, use *D1* (all digits) or *D2* (only 2 and 5). `tick0` is ignored for *D1* and *D2*. If the axis `type` is *date*, then you must convert the time to milliseconds. For example, to set the interval between ticks to one day, set `dtick` to 86400000.0. *date* also has special values *M* gives ticks spaced by a number of months. `n` must be a positive integer. To set ticks on the 15th of every third month, set `tick0` to *2000-01-15* and `dtick` to *M3*. To set ticks every 4 years, set `dtick` to *M48*" + }, + "tickvals": { + "valType": "data_array", + "editType": "colorbars", + "description": "Sets the values at which ticks on this axis appear. Only has an effect if `tickmode` is set to *array*. Used with `ticktext`.", + "role": "data" + }, + "ticktext": { + "valType": "data_array", + "editType": "colorbars", + "description": "Sets the text displayed at the ticks position via `tickvals`. Only has an effect if `tickmode` is set to *array*. Used with `tickvals`.", + "role": "data" + }, + "ticks": { + "valType": "enumerated", + "values": [ + "outside", + "inside", + "" + ], + "role": "style", + "editType": "colorbars", + "description": "Determines whether ticks are drawn or not. If **, this axis' ticks are not drawn. If *outside* (*inside*), this axis' are drawn outside (inside) the axis lines.", + "dflt": "" + }, + "ticklen": { + "valType": "number", + "min": 0, + "dflt": 5, + "role": "style", + "editType": "colorbars", + "description": "Sets the tick length (in px)." + }, + "tickwidth": { + "valType": "number", + "min": 0, + "dflt": 1, + "role": "style", + "editType": "colorbars", + "description": "Sets the tick width (in px)." + }, + "tickcolor": { + "valType": "color", + "dflt": "#444", + "role": "style", + "editType": "colorbars", + "description": "Sets the tick color." + }, + "showticklabels": { + "valType": "boolean", + "dflt": true, + "role": "style", + "editType": "colorbars", + "description": "Determines whether or not the tick labels are drawn." + }, + "tickfont": { + "family": { + "valType": "string", + "role": "style", + "noBlank": true, + "strict": true, + "description": "HTML font family - the typeface that will be applied by the web browser. The web browser will only be able to apply a font if it is available on the system which it operates. Provide multiple font families, separated by commas, to indicate the preference in which to apply fonts if they aren't available on the system. The plotly service (at https://plot.ly or on-premise) generates images on a server, where only a select number of fonts are installed and supported. These include *Arial*, *Balto*, *Courier New*, *Droid Sans*,, *Droid Serif*, *Droid Sans Mono*, *Gravitas One*, *Old Standard TT*, *Open Sans*, *Overpass*, *PT Sans Narrow*, *Raleway*, *Times New Roman*.", + "editType": "colorbars" + }, + "size": { + "valType": "number", + "role": "style", + "min": 1, + "editType": "colorbars" + }, + "color": { + "valType": "color", + "role": "style", + "editType": "colorbars" + }, + "description": "Sets the color bar's tick label font", + "editType": "colorbars", + "role": "object" + }, + "tickangle": { + "valType": "angle", + "dflt": "auto", + "role": "style", + "editType": "colorbars", + "description": "Sets the angle of the tick labels with respect to the horizontal. For example, a `tickangle` of -90 draws the tick labels vertically." + }, + "tickformat": { + "valType": "string", + "dflt": "", + "role": "style", + "editType": "colorbars", + "description": "Sets the tick label formatting rule using d3 formatting mini-languages which are very similar to those in Python. For numbers, see: https://github.com/d3/d3-format/blob/master/README.md#locale_format And for dates see: https://github.com/d3/d3-time-format/blob/master/README.md#locale_format We add one item to d3's date formatter: *%{n}f* for fractional seconds with n digits. For example, *2016-10-13 09:15:23.456* with tickformat *%H~%M~%S.%2f* would display *09~15~23.46*" + }, + "tickformatstops": { + "items": { + "tickformatstop": { + "dtickrange": { + "valType": "info_array", + "role": "info", + "items": [ + { + "valType": "any", + "editType": "colorbars" + }, + { + "valType": "any", + "editType": "colorbars" + } + ], + "editType": "colorbars", + "description": "range [*min*, *max*], where *min*, *max* - dtick values which describe some zoom level, it is possible to omit *min* or *max* value by passing *null*" + }, + "value": { + "valType": "string", + "dflt": "", + "role": "style", + "editType": "colorbars", + "description": "string - dtickformat for described zoom level, the same as *tickformat*" + }, + "editType": "colorbars", + "role": "object" + } + }, + "role": "object" + }, + "tickprefix": { + "valType": "string", + "dflt": "", + "role": "style", + "editType": "colorbars", + "description": "Sets a tick label prefix." + }, + "showtickprefix": { + "valType": "enumerated", + "values": [ + "all", + "first", + "last", + "none" + ], + "dflt": "all", + "role": "style", + "editType": "colorbars", + "description": "If *all*, all tick labels are displayed with a prefix. If *first*, only the first tick is displayed with a prefix. If *last*, only the last tick is displayed with a suffix. If *none*, tick prefixes are hidden." + }, + "ticksuffix": { + "valType": "string", + "dflt": "", + "role": "style", + "editType": "colorbars", + "description": "Sets a tick label suffix." + }, + "showticksuffix": { + "valType": "enumerated", + "values": [ + "all", + "first", + "last", + "none" + ], + "dflt": "all", + "role": "style", + "editType": "colorbars", + "description": "Same as `showtickprefix` but for tick suffixes." + }, + "separatethousands": { + "valType": "boolean", + "dflt": false, + "role": "style", + "editType": "colorbars", + "description": "If \"true\", even 4-digit integers are separated" + }, + "exponentformat": { + "valType": "enumerated", + "values": [ + "none", + "e", + "E", + "power", + "SI", + "B" + ], + "dflt": "B", + "role": "style", + "editType": "colorbars", + "description": "Determines a formatting rule for the tick exponents. For example, consider the number 1,000,000,000. If *none*, it appears as 1,000,000,000. If *e*, 1e+9. If *E*, 1E+9. If *power*, 1x10^9 (with 9 in a super script). If *SI*, 1G. If *B*, 1B." + }, + "showexponent": { + "valType": "enumerated", + "values": [ + "all", + "first", + "last", + "none" + ], + "dflt": "all", + "role": "style", + "editType": "colorbars", + "description": "If *all*, all exponents are shown besides their significands. If *first*, only the exponent of the first tick is shown. If *last*, only the exponent of the last tick is shown. If *none*, no exponents appear." + }, + "title": { + "valType": "string", + "role": "info", + "dflt": "Click to enter colorscale title", + "description": "Sets the title of the color bar.", + "editType": "colorbars" + }, + "titlefont": { + "family": { + "valType": "string", + "role": "style", + "noBlank": true, + "strict": true, + "description": "HTML font family - the typeface that will be applied by the web browser. The web browser will only be able to apply a font if it is available on the system which it operates. Provide multiple font families, separated by commas, to indicate the preference in which to apply fonts if they aren't available on the system. The plotly service (at https://plot.ly or on-premise) generates images on a server, where only a select number of fonts are installed and supported. These include *Arial*, *Balto*, *Courier New*, *Droid Sans*,, *Droid Serif*, *Droid Sans Mono*, *Gravitas One*, *Old Standard TT*, *Open Sans*, *Overpass*, *PT Sans Narrow*, *Raleway*, *Times New Roman*.", + "editType": "colorbars" + }, + "size": { + "valType": "number", + "role": "style", + "min": 1, + "editType": "colorbars" + }, + "color": { + "valType": "color", + "role": "style", + "editType": "colorbars" + }, + "description": "Sets this color bar's title font.", + "editType": "colorbars", + "role": "object" + }, + "titleside": { + "valType": "enumerated", + "values": [ + "right", + "top", + "bottom" + ], + "role": "style", + "dflt": "top", + "description": "Determines the location of the colorbar title with respect to the color bar.", + "editType": "colorbars" + }, + "editType": "colorbars", + "role": "object", + "tickvalssrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for tickvals .", + "editType": "none" + }, + "ticktextsrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for ticktext .", + "editType": "none" + } + }, + "xcalendar": { + "valType": "enumerated", + "values": [ + "gregorian", + "chinese", + "coptic", + "discworld", + "ethiopian", + "hebrew", + "islamic", + "julian", + "mayan", + "nanakshahi", + "nepali", + "persian", + "jalali", + "taiwan", + "thai", + "ummalqura" + ], + "role": "info", + "editType": "calc", + "dflt": "gregorian", + "description": "Sets the calendar system to use with `x` date data." + }, + "ycalendar": { + "valType": "enumerated", + "values": [ + "gregorian", + "chinese", + "coptic", + "discworld", + "ethiopian", + "hebrew", + "islamic", + "julian", + "mayan", + "nanakshahi", + "nepali", + "persian", + "jalali", + "taiwan", + "thai", + "ummalqura" + ], + "role": "info", + "editType": "calc", + "dflt": "gregorian", + "description": "Sets the calendar system to use with `y` date data." + }, + "xaxis": { + "valType": "subplotid", + "role": "info", + "dflt": "x", + "editType": "calc+clearAxisTypes", + "description": "Sets a reference between this trace's x coordinates and a 2D cartesian x axis. If *x* (the default value), the x coordinates refer to `layout.xaxis`. If *x2*, the x coordinates refer to `layout.xaxis2`, and so on." + }, + "yaxis": { + "valType": "subplotid", + "role": "info", + "dflt": "y", + "editType": "calc+clearAxisTypes", + "description": "Sets a reference between this trace's y coordinates and a 2D cartesian y axis. If *y* (the default value), the y coordinates refer to `layout.yaxis`. If *y2*, the y coordinates refer to `layout.xaxis2`, and so on." + }, + "idssrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for ids .", + "editType": "none" + }, + "customdatasrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for customdata .", + "editType": "none" + }, + "hoverinfosrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for hoverinfo .", + "editType": "none" + }, + "xsrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for x .", + "editType": "none" + }, + "ysrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for y .", + "editType": "none" + }, + "zsrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for z .", + "editType": "none" + } + } + }, + "pie": { + "meta": { + "description": "A data visualized by the sectors of the pie is set in `values`. The sector labels are set in `labels`. The sector colors are set in `marker.colors`" + }, + "attributes": { + "type": "pie", + "visible": { + "valType": "enumerated", + "values": [ + true, + false, + "legendonly" + ], + "role": "info", + "dflt": true, + "editType": "calc", + "description": "Determines whether or not this trace is visible. If *legendonly*, the trace is not drawn, but can appear as a legend item (provided that the legend itself is visible)." + }, + "showlegend": { + "valType": "boolean", + "role": "info", + "dflt": true, + "editType": "style", + "description": "Determines whether or not an item corresponding to this trace is shown in the legend." + }, + "legendgroup": { + "valType": "string", + "role": "info", + "dflt": "", + "editType": "style", + "description": "Sets the legend group for this trace. Traces part of the same legend group hide/show at the same time when toggling legend items." + }, + "opacity": { + "valType": "number", + "role": "style", + "min": 0, + "max": 1, + "dflt": 1, + "editType": "style", + "description": "Sets the opacity of the trace." + }, + "name": { + "valType": "string", + "role": "info", + "editType": "style", + "description": "Sets the trace name. The trace name appear as the legend item and on hover." + }, + "uid": { + "valType": "string", + "role": "info", + "dflt": "", + "editType": "calc" + }, + "ids": { + "valType": "data_array", + "editType": "calc", + "description": "Assigns id labels to each datum. These ids for object constancy of data points during animation.", + "role": "data" + }, + "customdata": { + "valType": "data_array", + "editType": "calc", + "description": "Assigns extra data each datum. This may be useful when listening to hover, click and selection events. Note that, *scatter* traces also appends customdata items in the markers DOM elements", + "role": "data" + }, + "selectedpoints": { + "valType": "any", + "role": "info", + "editType": "calc", + "description": "Array containing integer indices of selected points. Has an effect only for traces that support selections. Note that an empty array means an empty selection where the `unselected` are turned on for all points, whereas, any other non-array values means no selection all where the `selected` and `unselected` styles have no effect." + }, + "hoverinfo": { + "valType": "flaglist", + "role": "info", + "flags": [ + "label", + "text", + "value", + "percent", + "name" + ], + "extras": [ + "all", + "none", + "skip" + ], + "arrayOk": true, + "dflt": "all", + "editType": "none", + "description": "Determines which trace information appear on hover. If `none` or `skip` are set, no information is displayed upon hovering. But, if `none` is set, click and hover events are still fired." + }, + "hoverlabel": { + "bgcolor": { + "valType": "color", + "role": "style", + "arrayOk": true, + "editType": "none", + "description": "Sets the background color of the hover labels for this trace" + }, + "bordercolor": { + "valType": "color", + "role": "style", + "arrayOk": true, + "editType": "none", + "description": "Sets the border color of the hover labels for this trace." + }, + "font": { + "family": { + "valType": "string", + "role": "style", + "noBlank": true, + "strict": true, + "editType": "none", + "description": "HTML font family - the typeface that will be applied by the web browser. The web browser will only be able to apply a font if it is available on the system which it operates. Provide multiple font families, separated by commas, to indicate the preference in which to apply fonts if they aren't available on the system. The plotly service (at https://plot.ly or on-premise) generates images on a server, where only a select number of fonts are installed and supported. These include *Arial*, *Balto*, *Courier New*, *Droid Sans*,, *Droid Serif*, *Droid Sans Mono*, *Gravitas One*, *Old Standard TT*, *Open Sans*, *Overpass*, *PT Sans Narrow*, *Raleway*, *Times New Roman*.", + "arrayOk": true + }, + "size": { + "valType": "number", + "role": "style", + "min": 1, + "editType": "none", + "arrayOk": true + }, + "color": { + "valType": "color", + "role": "style", + "editType": "none", + "arrayOk": true + }, + "editType": "none", + "description": "Sets the font used in hover labels.", + "role": "object", + "familysrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for family .", + "editType": "none" + }, + "sizesrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for size .", + "editType": "none" + }, + "colorsrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for color .", + "editType": "none" + } + }, + "namelength": { + "valType": "integer", + "min": -1, + "arrayOk": true, + "role": "style", + "editType": "none", + "description": "Sets the length (in number of characters) of the trace name in the hover labels for this trace. -1 shows the whole name regardless of length. 0-3 shows the first 0-3 characters, and an integer >3 will show the whole name if it is less than that many characters, but if it is longer, will truncate to `namelength - 3` characters and add an ellipsis." + }, + "editType": "calc", + "role": "object", + "bgcolorsrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for bgcolor .", + "editType": "none" + }, + "bordercolorsrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for bordercolor .", + "editType": "none" + }, + "namelengthsrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for namelength .", + "editType": "none" + } + }, + "stream": { + "token": { + "valType": "string", + "noBlank": true, + "strict": true, + "role": "info", + "editType": "calc", + "description": "The stream id number links a data trace on a plot with a stream. See https://plot.ly/settings for more details." + }, + "maxpoints": { + "valType": "number", + "min": 0, + "max": 10000, + "dflt": 500, + "role": "info", + "editType": "calc", + "description": "Sets the maximum number of points to keep on the plots from an incoming stream. If `maxpoints` is set to *50*, only the newest 50 points will be displayed on the plot." + }, + "editType": "calc", + "role": "object" + }, + "labels": { + "valType": "data_array", + "editType": "calc", + "description": "Sets the sector labels. If `labels` entries are duplicated, we sum associated `values` or simply count occurrences if `values` is not provided. For other array attributes (including color) we use the first non-empty entry among all occurrences of the label.", + "role": "data" + }, + "label0": { + "valType": "number", + "role": "info", + "dflt": 0, + "editType": "calc", + "description": "Alternate to `labels`. Builds a numeric set of labels. Use with `dlabel` where `label0` is the starting label and `dlabel` the step." + }, + "dlabel": { + "valType": "number", + "role": "info", + "dflt": 1, + "editType": "calc", + "description": "Sets the label step. See `label0` for more info." + }, + "values": { + "valType": "data_array", + "editType": "calc", + "description": "Sets the values of the sectors of this pie chart. If omitted, we count occurrences of each label.", + "role": "data" + }, + "marker": { + "colors": { + "valType": "data_array", + "editType": "calc", + "description": "Sets the color of each sector of this pie chart. If not specified, the default trace color set is used to pick the sector colors.", + "role": "data" + }, + "line": { + "color": { + "valType": "color", + "role": "style", + "dflt": "#444", + "arrayOk": true, + "editType": "style", + "description": "Sets the color of the line enclosing each sector." + }, + "width": { + "valType": "number", + "role": "style", + "min": 0, + "dflt": 0, + "arrayOk": true, + "editType": "style", + "description": "Sets the width (in px) of the line enclosing each sector." + }, + "editType": "calc", + "role": "object", + "colorsrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for color .", + "editType": "none" + }, + "widthsrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for width .", + "editType": "none" + } + }, + "editType": "calc", + "role": "object", + "colorssrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for colors .", + "editType": "none" + } + }, + "text": { + "valType": "data_array", + "editType": "calc", + "description": "Sets text elements associated with each sector. If trace `textinfo` contains a *text* flag, these elements will seen on the chart. If trace `hoverinfo` contains a *text* flag and *hovertext* is not set, these elements will be seen in the hover labels.", + "role": "data" + }, + "hovertext": { + "valType": "string", + "role": "info", + "dflt": "", + "arrayOk": true, + "editType": "style", + "description": "Sets hover text elements associated with each sector. If a single string, the same string appears for all data points. If an array of string, the items are mapped in order of this trace's sectors. To be seen, trace `hoverinfo` must contain a *text* flag." + }, + "scalegroup": { + "valType": "string", + "role": "info", + "dflt": "", + "editType": "calc", + "description": "If there are multiple pies that should be sized according to their totals, link them by providing a non-empty group id here shared by every trace in the same group." + }, + "textinfo": { + "valType": "flaglist", + "role": "info", + "flags": [ + "label", + "text", + "value", + "percent" + ], + "extras": [ + "none" + ], + "editType": "calc", + "description": "Determines which trace information appear on the graph." + }, + "textposition": { + "valType": "enumerated", + "role": "info", + "values": [ + "inside", + "outside", + "auto", + "none" + ], + "dflt": "auto", + "arrayOk": true, + "editType": "calc", + "description": "Specifies the location of the `textinfo`." + }, + "textfont": { + "family": { + "valType": "string", + "role": "style", + "noBlank": true, + "strict": true, + "editType": "calc", + "description": "HTML font family - the typeface that will be applied by the web browser. The web browser will only be able to apply a font if it is available on the system which it operates. Provide multiple font families, separated by commas, to indicate the preference in which to apply fonts if they aren't available on the system. The plotly service (at https://plot.ly or on-premise) generates images on a server, where only a select number of fonts are installed and supported. These include *Arial*, *Balto*, *Courier New*, *Droid Sans*,, *Droid Serif*, *Droid Sans Mono*, *Gravitas One*, *Old Standard TT*, *Open Sans*, *Overpass*, *PT Sans Narrow*, *Raleway*, *Times New Roman*." + }, + "size": { + "valType": "number", + "role": "style", + "min": 1, + "editType": "calc" + }, + "color": { + "valType": "color", + "role": "style", + "editType": "style" + }, + "editType": "calc", + "description": "Sets the font used for `textinfo`.", + "role": "object" + }, + "insidetextfont": { + "family": { + "valType": "string", + "role": "style", + "noBlank": true, + "strict": true, + "editType": "calc", + "description": "HTML font family - the typeface that will be applied by the web browser. The web browser will only be able to apply a font if it is available on the system which it operates. Provide multiple font families, separated by commas, to indicate the preference in which to apply fonts if they aren't available on the system. The plotly service (at https://plot.ly or on-premise) generates images on a server, where only a select number of fonts are installed and supported. These include *Arial*, *Balto*, *Courier New*, *Droid Sans*,, *Droid Serif*, *Droid Sans Mono*, *Gravitas One*, *Old Standard TT*, *Open Sans*, *Overpass*, *PT Sans Narrow*, *Raleway*, *Times New Roman*." + }, + "size": { + "valType": "number", + "role": "style", + "min": 1, + "editType": "calc" + }, + "color": { + "valType": "color", + "role": "style", + "editType": "style" + }, + "editType": "calc", + "description": "Sets the font used for `textinfo` lying inside the pie.", + "role": "object" + }, + "outsidetextfont": { + "family": { + "valType": "string", + "role": "style", + "noBlank": true, + "strict": true, + "editType": "calc", + "description": "HTML font family - the typeface that will be applied by the web browser. The web browser will only be able to apply a font if it is available on the system which it operates. Provide multiple font families, separated by commas, to indicate the preference in which to apply fonts if they aren't available on the system. The plotly service (at https://plot.ly or on-premise) generates images on a server, where only a select number of fonts are installed and supported. These include *Arial*, *Balto*, *Courier New*, *Droid Sans*,, *Droid Serif*, *Droid Sans Mono*, *Gravitas One*, *Old Standard TT*, *Open Sans*, *Overpass*, *PT Sans Narrow*, *Raleway*, *Times New Roman*." + }, + "size": { + "valType": "number", + "role": "style", + "min": 1, + "editType": "calc" + }, + "color": { + "valType": "color", + "role": "style", + "editType": "style" + }, + "editType": "calc", + "description": "Sets the font used for `textinfo` lying outside the pie.", + "role": "object" + }, + "domain": { + "x": { + "valType": "info_array", + "role": "info", + "items": [ + { + "valType": "number", + "min": 0, + "max": 1, + "editType": "calc" + }, + { + "valType": "number", + "min": 0, + "max": 1, + "editType": "calc" + } + ], + "dflt": [ + 0, + 1 + ], + "editType": "calc", + "description": "Sets the horizontal domain of this pie trace (in plot fraction)." + }, + "y": { + "valType": "info_array", + "role": "info", + "items": [ + { + "valType": "number", + "min": 0, + "max": 1, + "editType": "calc" + }, + { + "valType": "number", + "min": 0, + "max": 1, + "editType": "calc" + } + ], + "dflt": [ + 0, + 1 + ], + "editType": "calc", + "description": "Sets the vertical domain of this pie trace (in plot fraction)." + }, + "editType": "calc", + "role": "object" + }, + "hole": { + "valType": "number", + "role": "style", + "min": 0, + "max": 1, + "dflt": 0, + "editType": "calc", + "description": "Sets the fraction of the radius to cut out of the pie. Use this to make a donut chart." + }, + "sort": { + "valType": "boolean", + "role": "style", + "dflt": true, + "editType": "calc", + "description": "Determines whether or not the sectors are reordered from largest to smallest." + }, + "direction": { + "valType": "enumerated", + "values": [ + "clockwise", + "counterclockwise" + ], + "role": "style", + "dflt": "counterclockwise", + "editType": "calc", + "description": "Specifies the direction at which succeeding sectors follow one another." + }, + "rotation": { + "valType": "number", + "role": "style", + "min": -360, + "max": 360, + "dflt": 0, + "editType": "calc", + "description": "Instead of the first slice starting at 12 o'clock, rotate to some other angle." + }, + "pull": { + "valType": "number", + "role": "style", + "min": 0, + "max": 1, + "dflt": 0, + "arrayOk": true, + "editType": "calc", + "description": "Sets the fraction of larger radius to pull the sectors out from the center. This can be a constant to pull all slices apart from each other equally or an array to highlight one or more slices." + }, + "idssrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for ids .", + "editType": "none" + }, + "customdatasrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for customdata .", + "editType": "none" + }, + "hoverinfosrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for hoverinfo .", + "editType": "none" + }, + "labelssrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for labels .", + "editType": "none" + }, + "valuessrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for values .", + "editType": "none" + }, + "textsrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for text .", + "editType": "none" + }, + "hovertextsrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for hovertext .", + "editType": "none" + }, + "textpositionsrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for textposition .", + "editType": "none" + }, + "pullsrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for pull .", + "editType": "none" + } + }, + "layoutAttributes": { + "hiddenlabels": { + "valType": "data_array", + "editType": "calc", + "role": "data" + }, + "hiddenlabelssrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for hiddenlabels .", + "editType": "none" + } + } + }, + "contour": { + "meta": { + "description": "The data from which contour lines are computed is set in `z`. Data in `z` must be a {2D array} of numbers. Say that `z` has N rows and M columns, then by default, these N rows correspond to N y coordinates (set in `y` or auto-generated) and the M columns correspond to M x coordinates (set in `x` or auto-generated). By setting `transpose` to *true*, the above behavior is flipped." + }, + "attributes": { + "type": "contour", + "visible": { + "valType": "enumerated", + "values": [ + true, + false, + "legendonly" + ], + "role": "info", + "dflt": true, + "editType": "calc", + "description": "Determines whether or not this trace is visible. If *legendonly*, the trace is not drawn, but can appear as a legend item (provided that the legend itself is visible)." + }, + "showlegend": { + "valType": "boolean", + "role": "info", + "dflt": true, + "editType": "style", + "description": "Determines whether or not an item corresponding to this trace is shown in the legend." + }, + "legendgroup": { + "valType": "string", + "role": "info", + "dflt": "", + "editType": "style", + "description": "Sets the legend group for this trace. Traces part of the same legend group hide/show at the same time when toggling legend items." + }, + "opacity": { + "valType": "number", + "role": "style", + "min": 0, + "max": 1, + "dflt": 1, + "editType": "style", + "description": "Sets the opacity of the trace." + }, + "name": { + "valType": "string", + "role": "info", + "editType": "style", + "description": "Sets the trace name. The trace name appear as the legend item and on hover." + }, + "uid": { + "valType": "string", + "role": "info", + "dflt": "", + "editType": "calc" + }, + "ids": { + "valType": "data_array", + "editType": "calc", + "description": "Assigns id labels to each datum. These ids for object constancy of data points during animation.", + "role": "data" + }, + "customdata": { + "valType": "data_array", + "editType": "calc", + "description": "Assigns extra data each datum. This may be useful when listening to hover, click and selection events. Note that, *scatter* traces also appends customdata items in the markers DOM elements", + "role": "data" + }, + "selectedpoints": { + "valType": "any", + "role": "info", + "editType": "calc", + "description": "Array containing integer indices of selected points. Has an effect only for traces that support selections. Note that an empty array means an empty selection where the `unselected` are turned on for all points, whereas, any other non-array values means no selection all where the `selected` and `unselected` styles have no effect." + }, + "hoverinfo": { + "valType": "flaglist", + "role": "info", + "flags": [ + "x", + "y", + "z", + "text", + "name" + ], + "extras": [ + "all", + "none", + "skip" + ], + "arrayOk": true, + "dflt": "all", + "editType": "none", + "description": "Determines which trace information appear on hover. If `none` or `skip` are set, no information is displayed upon hovering. But, if `none` is set, click and hover events are still fired." + }, + "hoverlabel": { + "bgcolor": { + "valType": "color", + "role": "style", + "arrayOk": true, + "editType": "none", + "description": "Sets the background color of the hover labels for this trace" + }, + "bordercolor": { + "valType": "color", + "role": "style", + "arrayOk": true, + "editType": "none", + "description": "Sets the border color of the hover labels for this trace." + }, + "font": { + "family": { + "valType": "string", + "role": "style", + "noBlank": true, + "strict": true, + "editType": "none", + "description": "HTML font family - the typeface that will be applied by the web browser. The web browser will only be able to apply a font if it is available on the system which it operates. Provide multiple font families, separated by commas, to indicate the preference in which to apply fonts if they aren't available on the system. The plotly service (at https://plot.ly or on-premise) generates images on a server, where only a select number of fonts are installed and supported. These include *Arial*, *Balto*, *Courier New*, *Droid Sans*,, *Droid Serif*, *Droid Sans Mono*, *Gravitas One*, *Old Standard TT*, *Open Sans*, *Overpass*, *PT Sans Narrow*, *Raleway*, *Times New Roman*.", + "arrayOk": true + }, + "size": { + "valType": "number", + "role": "style", + "min": 1, + "editType": "none", + "arrayOk": true + }, + "color": { + "valType": "color", + "role": "style", + "editType": "none", + "arrayOk": true + }, + "editType": "none", + "description": "Sets the font used in hover labels.", + "role": "object", + "familysrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for family .", + "editType": "none" + }, + "sizesrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for size .", + "editType": "none" + }, + "colorsrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for color .", + "editType": "none" + } + }, + "namelength": { + "valType": "integer", + "min": -1, + "arrayOk": true, + "role": "style", + "editType": "none", + "description": "Sets the length (in number of characters) of the trace name in the hover labels for this trace. -1 shows the whole name regardless of length. 0-3 shows the first 0-3 characters, and an integer >3 will show the whole name if it is less than that many characters, but if it is longer, will truncate to `namelength - 3` characters and add an ellipsis." + }, + "editType": "calc", + "role": "object", + "bgcolorsrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for bgcolor .", + "editType": "none" + }, + "bordercolorsrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for bordercolor .", + "editType": "none" + }, + "namelengthsrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for namelength .", + "editType": "none" + } + }, + "stream": { + "token": { + "valType": "string", + "noBlank": true, + "strict": true, + "role": "info", + "editType": "calc", + "description": "The stream id number links a data trace on a plot with a stream. See https://plot.ly/settings for more details." + }, + "maxpoints": { + "valType": "number", + "min": 0, + "max": 10000, + "dflt": 500, + "role": "info", + "editType": "calc", + "description": "Sets the maximum number of points to keep on the plots from an incoming stream. If `maxpoints` is set to *50*, only the newest 50 points will be displayed on the plot." + }, + "editType": "calc", + "role": "object" + }, + "z": { + "valType": "data_array", + "editType": "calc", + "description": "Sets the z data.", + "role": "data" + }, + "x": { + "valType": "data_array", + "editType": "calc+clearAxisTypes", + "description": "Sets the x coordinates.", + "impliedEdits": { + "xtype": "array" + }, + "role": "data" + }, + "x0": { + "valType": "any", + "dflt": 0, + "role": "info", + "editType": "calc+clearAxisTypes", + "description": "Alternate to `x`. Builds a linear space of x coordinates. Use with `dx` where `x0` is the starting coordinate and `dx` the step.", + "impliedEdits": { + "xtype": "scaled" + } + }, + "dx": { + "valType": "number", + "dflt": 1, + "role": "info", + "editType": "calc", + "description": "Sets the x coordinate step. See `x0` for more info.", + "impliedEdits": { + "xtype": "scaled" + } + }, + "y": { + "valType": "data_array", + "editType": "calc+clearAxisTypes", + "description": "Sets the y coordinates.", + "impliedEdits": { + "ytype": "array" + }, + "role": "data" + }, + "y0": { + "valType": "any", + "dflt": 0, + "role": "info", + "editType": "calc+clearAxisTypes", + "description": "Alternate to `y`. Builds a linear space of y coordinates. Use with `dy` where `y0` is the starting coordinate and `dy` the step.", + "impliedEdits": { + "ytype": "scaled" + } + }, + "dy": { + "valType": "number", + "dflt": 1, + "role": "info", + "editType": "calc", + "description": "Sets the y coordinate step. See `y0` for more info.", + "impliedEdits": { + "ytype": "scaled" + } + }, + "text": { + "valType": "data_array", + "editType": "calc", + "description": "Sets the text elements associated with each z value.", + "role": "data" + }, + "transpose": { + "valType": "boolean", + "dflt": false, + "role": "info", + "editType": "calc", + "description": "Transposes the z data." + }, + "xtype": { + "valType": "enumerated", + "values": [ + "array", + "scaled" + ], + "role": "info", + "editType": "calc+clearAxisTypes", + "description": "If *array*, the heatmap's x coordinates are given by *x* (the default behavior when `x` is provided). If *scaled*, the heatmap's x coordinates are given by *x0* and *dx* (the default behavior when `x` is not provided)." + }, + "ytype": { + "valType": "enumerated", + "values": [ + "array", + "scaled" + ], + "role": "info", + "editType": "calc+clearAxisTypes", + "description": "If *array*, the heatmap's y coordinates are given by *y* (the default behavior when `y` is provided) If *scaled*, the heatmap's y coordinates are given by *y0* and *dy* (the default behavior when `y` is not provided)" + }, + "zhoverformat": { + "valType": "string", + "dflt": "", + "role": "style", + "editType": "none", + "description": "Sets the hover text formatting rule using d3 formatting mini-languages which are very similar to those in Python. See: https://github.com/d3/d3-format/blob/master/README.md#locale_format" + }, + "connectgaps": { + "valType": "boolean", + "dflt": false, + "role": "info", + "editType": "calc", + "description": "Determines whether or not gaps (i.e. {nan} or missing values) in the `z` data are filled in." + }, + "autocontour": { + "valType": "boolean", + "dflt": true, + "role": "style", + "editType": "calc", + "impliedEdits": {}, + "description": "Determines whether or not the contour level attributes are picked by an algorithm. If *true*, the number of contour levels can be set in `ncontours`. If *false*, set the contour level attributes in `contours`." + }, + "ncontours": { + "valType": "integer", + "dflt": 15, + "min": 1, + "role": "style", + "editType": "calc", + "description": "Sets the maximum number of contour levels. The actual number of contours will be chosen automatically to be less than or equal to the value of `ncontours`. Has an effect only if `autocontour` is *true* or if `contours.size` is missing." + }, + "contours": { + "start": { + "valType": "number", + "dflt": null, + "role": "style", + "editType": "plot", + "impliedEdits": { + "^autocontour": false + }, + "description": "Sets the starting contour level value. Must be less than `contours.end`" + }, + "end": { + "valType": "number", + "dflt": null, + "role": "style", + "editType": "plot", + "impliedEdits": { + "^autocontour": false + }, + "description": "Sets the end contour level value. Must be more than `contours.start`" + }, + "size": { + "valType": "number", + "dflt": null, + "min": 0, + "role": "style", + "editType": "plot", + "impliedEdits": { + "^autocontour": false + }, + "description": "Sets the step between each contour level. Must be positive." + }, + "coloring": { + "valType": "enumerated", + "values": [ + "fill", + "heatmap", + "lines", + "none" + ], + "dflt": "fill", + "role": "style", + "editType": "calc", + "description": "Determines the coloring method showing the contour values. If *fill*, coloring is done evenly between each contour level If *heatmap*, a heatmap gradient coloring is applied between each contour level. If *lines*, coloring is done on the contour lines. If *none*, no coloring is applied on this trace." + }, + "showlines": { + "valType": "boolean", + "dflt": true, + "role": "style", + "editType": "plot", + "description": "Determines whether or not the contour lines are drawn. Has an effect only if `contours.coloring` is set to *fill*." + }, + "showlabels": { + "valType": "boolean", + "dflt": false, + "role": "style", + "editType": "plot", + "description": "Determines whether to label the contour lines with their values." + }, + "labelfont": { + "family": { + "valType": "string", + "role": "style", + "noBlank": true, + "strict": true, + "editType": "plot", + "description": "HTML font family - the typeface that will be applied by the web browser. The web browser will only be able to apply a font if it is available on the system which it operates. Provide multiple font families, separated by commas, to indicate the preference in which to apply fonts if they aren't available on the system. The plotly service (at https://plot.ly or on-premise) generates images on a server, where only a select number of fonts are installed and supported. These include *Arial*, *Balto*, *Courier New*, *Droid Sans*,, *Droid Serif*, *Droid Sans Mono*, *Gravitas One*, *Old Standard TT*, *Open Sans*, *Overpass*, *PT Sans Narrow*, *Raleway*, *Times New Roman*." + }, + "size": { + "valType": "number", + "role": "style", + "min": 1, + "editType": "plot" + }, + "color": { + "valType": "color", + "role": "style", + "editType": "style" + }, + "editType": "plot", + "description": "Sets the font used for labeling the contour levels. The default color comes from the lines, if shown. The default family and size come from `layout.font`.", + "role": "object" + }, + "labelformat": { + "valType": "string", + "dflt": "", + "role": "style", + "editType": "plot", + "description": "Sets the contour label formatting rule using d3 formatting mini-language which is very similar to Python, see: https://github.com/d3/d3-format/blob/master/README.md#locale_format." + }, + "editType": "calc", + "impliedEdits": { + "autocontour": false, + "role": "object" + }, + "role": "object" + }, + "line": { + "color": { + "valType": "color", + "role": "style", + "editType": "style+colorbars", + "description": "Sets the color of the contour level. Has no effect if `contours.coloring` is set to *lines*." + }, + "width": { + "valType": "number", + "min": 0, + "dflt": 2, + "role": "style", + "editType": "style+colorbars", + "description": "Sets the line width (in px)." + }, + "dash": { + "valType": "string", + "values": [ + "solid", + "dot", + "dash", + "longdash", + "dashdot", + "longdashdot" + ], + "dflt": "solid", + "role": "style", + "editType": "style", + "description": "Sets the dash style of lines. Set to a dash type string (*solid*, *dot*, *dash*, *longdash*, *dashdot*, or *longdashdot*) or a dash length list in px (eg *5px,10px,2px,2px*)." + }, + "smoothing": { + "valType": "number", + "min": 0, + "max": 1.3, + "dflt": 1, + "role": "style", + "editType": "plot", + "description": "Sets the amount of smoothing for the contour lines, where *0* corresponds to no smoothing." + }, + "editType": "plot", + "role": "object" + }, + "zauto": { + "valType": "boolean", + "role": "info", + "dflt": true, + "editType": "calc", + "impliedEdits": {}, + "description": "Determines the whether or not the color domain is computed with respect to the input data." + }, + "zmin": { + "valType": "number", + "role": "info", + "dflt": null, + "editType": "calc", + "impliedEdits": { + "zauto": false + }, + "description": "Sets the lower bound of color domain." + }, + "zmax": { + "valType": "number", + "role": "info", + "dflt": null, + "editType": "calc", + "impliedEdits": { + "zauto": false + }, + "description": "Sets the upper bound of color domain." + }, + "colorscale": { + "valType": "colorscale", + "role": "style", + "editType": "calc", + "impliedEdits": { + "autocolorscale": false + }, + "description": "Sets the colorscale. The colorscale must be an array containing arrays mapping a normalized value to an rgb, rgba, hex, hsl, hsv, or named color string. At minimum, a mapping for the lowest (0) and highest (1) values are required. For example, `[[0, 'rgb(0,0,255)', [1, 'rgb(255,0,0)']]`. To control the bounds of the colorscale in z space, use zmin and zmax" + }, + "autocolorscale": { + "valType": "boolean", + "role": "style", + "dflt": false, + "editType": "calc", + "impliedEdits": {}, + "description": "Determines whether or not the colorscale is picked using the sign of the input z values." + }, + "reversescale": { + "valType": "boolean", + "role": "style", + "dflt": false, + "editType": "calc", + "description": "Reverses the colorscale." + }, + "showscale": { + "valType": "boolean", + "role": "info", + "dflt": true, + "editType": "calc", + "description": "Determines whether or not a colorbar is displayed for this trace." + }, + "colorbar": { + "thicknessmode": { + "valType": "enumerated", + "values": [ + "fraction", + "pixels" + ], + "role": "style", + "dflt": "pixels", + "description": "Determines whether this color bar's thickness (i.e. the measure in the constant color direction) is set in units of plot *fraction* or in *pixels*. Use `thickness` to set the value.", + "editType": "colorbars" + }, + "thickness": { + "valType": "number", + "role": "style", + "min": 0, + "dflt": 30, + "description": "Sets the thickness of the color bar This measure excludes the size of the padding, ticks and labels.", + "editType": "colorbars" + }, + "lenmode": { + "valType": "enumerated", + "values": [ + "fraction", + "pixels" + ], + "role": "info", + "dflt": "fraction", + "description": "Determines whether this color bar's length (i.e. the measure in the color variation direction) is set in units of plot *fraction* or in *pixels. Use `len` to set the value.", + "editType": "colorbars" + }, + "len": { + "valType": "number", + "min": 0, + "dflt": 1, + "role": "style", + "description": "Sets the length of the color bar This measure excludes the padding of both ends. That is, the color bar length is this length minus the padding on both ends.", + "editType": "colorbars" + }, + "x": { + "valType": "number", + "dflt": 1.02, + "min": -2, + "max": 3, + "role": "style", + "description": "Sets the x position of the color bar (in plot fraction).", + "editType": "colorbars" + }, + "xanchor": { + "valType": "enumerated", + "values": [ + "left", + "center", + "right" + ], + "dflt": "left", + "role": "style", + "description": "Sets this color bar's horizontal position anchor. This anchor binds the `x` position to the *left*, *center* or *right* of the color bar.", + "editType": "colorbars" + }, + "xpad": { + "valType": "number", + "role": "style", + "min": 0, + "dflt": 10, + "description": "Sets the amount of padding (in px) along the x direction.", + "editType": "colorbars" + }, + "y": { + "valType": "number", + "role": "style", + "dflt": 0.5, + "min": -2, + "max": 3, + "description": "Sets the y position of the color bar (in plot fraction).", + "editType": "colorbars" + }, + "yanchor": { + "valType": "enumerated", + "values": [ + "top", + "middle", + "bottom" + ], + "role": "style", + "dflt": "middle", + "description": "Sets this color bar's vertical position anchor This anchor binds the `y` position to the *top*, *middle* or *bottom* of the color bar.", + "editType": "colorbars" + }, + "ypad": { + "valType": "number", + "role": "style", + "min": 0, + "dflt": 10, + "description": "Sets the amount of padding (in px) along the y direction.", + "editType": "colorbars" + }, + "outlinecolor": { + "valType": "color", + "dflt": "#444", + "role": "style", + "editType": "colorbars", + "description": "Sets the axis line color." + }, + "outlinewidth": { + "valType": "number", + "min": 0, + "dflt": 1, + "role": "style", + "editType": "colorbars", + "description": "Sets the width (in px) of the axis line." + }, + "bordercolor": { + "valType": "color", + "dflt": "#444", + "role": "style", + "editType": "colorbars", + "description": "Sets the axis line color." + }, + "borderwidth": { + "valType": "number", + "role": "style", + "min": 0, + "dflt": 0, + "description": "Sets the width (in px) or the border enclosing this color bar.", + "editType": "colorbars" + }, + "bgcolor": { + "valType": "color", + "role": "style", + "dflt": "rgba(0,0,0,0)", + "description": "Sets the color of padded area.", + "editType": "colorbars" + }, + "tickmode": { + "valType": "enumerated", + "values": [ + "auto", + "linear", + "array" + ], + "role": "info", + "editType": "colorbars", + "impliedEdits": {}, + "description": "Sets the tick mode for this axis. If *auto*, the number of ticks is set via `nticks`. If *linear*, the placement of the ticks is determined by a starting position `tick0` and a tick step `dtick` (*linear* is the default value if `tick0` and `dtick` are provided). If *array*, the placement of the ticks is set via `tickvals` and the tick text is `ticktext`. (*array* is the default value if `tickvals` is provided)." + }, + "nticks": { + "valType": "integer", + "min": 0, + "dflt": 0, + "role": "style", + "editType": "colorbars", + "description": "Specifies the maximum number of ticks for the particular axis. The actual number of ticks will be chosen automatically to be less than or equal to `nticks`. Has an effect only if `tickmode` is set to *auto*." + }, + "tick0": { + "valType": "any", + "role": "style", + "editType": "colorbars", + "impliedEdits": { + "tickmode": "linear" + }, + "description": "Sets the placement of the first tick on this axis. Use with `dtick`. If the axis `type` is *log*, then you must take the log of your starting tick (e.g. to set the starting tick to 100, set the `tick0` to 2) except when `dtick`=*L* (see `dtick` for more info). If the axis `type` is *date*, it should be a date string, like date data. If the axis `type` is *category*, it should be a number, using the scale where each category is assigned a serial number from zero in the order it appears." + }, + "dtick": { + "valType": "any", + "role": "style", + "editType": "colorbars", + "impliedEdits": { + "tickmode": "linear" + }, + "description": "Sets the step in-between ticks on this axis. Use with `tick0`. Must be a positive number, or special strings available to *log* and *date* axes. If the axis `type` is *log*, then ticks are set every 10^(n*dtick) where n is the tick number. For example, to set a tick mark at 1, 10, 100, 1000, ... set dtick to 1. To set tick marks at 1, 100, 10000, ... set dtick to 2. To set tick marks at 1, 5, 25, 125, 625, 3125, ... set dtick to log_10(5), or 0.69897000433. *log* has several special values; *L*, where `f` is a positive number, gives ticks linearly spaced in value (but not position). For example `tick0` = 0.1, `dtick` = *L0.5* will put ticks at 0.1, 0.6, 1.1, 1.6 etc. To show powers of 10 plus small digits between, use *D1* (all digits) or *D2* (only 2 and 5). `tick0` is ignored for *D1* and *D2*. If the axis `type` is *date*, then you must convert the time to milliseconds. For example, to set the interval between ticks to one day, set `dtick` to 86400000.0. *date* also has special values *M* gives ticks spaced by a number of months. `n` must be a positive integer. To set ticks on the 15th of every third month, set `tick0` to *2000-01-15* and `dtick` to *M3*. To set ticks every 4 years, set `dtick` to *M48*" + }, + "tickvals": { + "valType": "data_array", + "editType": "colorbars", + "description": "Sets the values at which ticks on this axis appear. Only has an effect if `tickmode` is set to *array*. Used with `ticktext`.", + "role": "data" + }, + "ticktext": { + "valType": "data_array", + "editType": "colorbars", + "description": "Sets the text displayed at the ticks position via `tickvals`. Only has an effect if `tickmode` is set to *array*. Used with `tickvals`.", + "role": "data" + }, + "ticks": { + "valType": "enumerated", + "values": [ + "outside", + "inside", + "" + ], + "role": "style", + "editType": "colorbars", + "description": "Determines whether ticks are drawn or not. If **, this axis' ticks are not drawn. If *outside* (*inside*), this axis' are drawn outside (inside) the axis lines.", + "dflt": "" + }, + "ticklen": { + "valType": "number", + "min": 0, + "dflt": 5, + "role": "style", + "editType": "colorbars", + "description": "Sets the tick length (in px)." + }, + "tickwidth": { + "valType": "number", + "min": 0, + "dflt": 1, + "role": "style", + "editType": "colorbars", + "description": "Sets the tick width (in px)." + }, + "tickcolor": { + "valType": "color", + "dflt": "#444", + "role": "style", + "editType": "colorbars", + "description": "Sets the tick color." + }, + "showticklabels": { + "valType": "boolean", + "dflt": true, + "role": "style", + "editType": "colorbars", + "description": "Determines whether or not the tick labels are drawn." + }, + "tickfont": { + "family": { + "valType": "string", + "role": "style", + "noBlank": true, + "strict": true, + "description": "HTML font family - the typeface that will be applied by the web browser. The web browser will only be able to apply a font if it is available on the system which it operates. Provide multiple font families, separated by commas, to indicate the preference in which to apply fonts if they aren't available on the system. The plotly service (at https://plot.ly or on-premise) generates images on a server, where only a select number of fonts are installed and supported. These include *Arial*, *Balto*, *Courier New*, *Droid Sans*,, *Droid Serif*, *Droid Sans Mono*, *Gravitas One*, *Old Standard TT*, *Open Sans*, *Overpass*, *PT Sans Narrow*, *Raleway*, *Times New Roman*.", + "editType": "colorbars" + }, + "size": { + "valType": "number", + "role": "style", + "min": 1, + "editType": "colorbars" + }, + "color": { + "valType": "color", + "role": "style", + "editType": "colorbars" + }, + "description": "Sets the color bar's tick label font", + "editType": "colorbars", + "role": "object" + }, + "tickangle": { + "valType": "angle", + "dflt": "auto", + "role": "style", + "editType": "colorbars", + "description": "Sets the angle of the tick labels with respect to the horizontal. For example, a `tickangle` of -90 draws the tick labels vertically." + }, + "tickformat": { + "valType": "string", + "dflt": "", + "role": "style", + "editType": "colorbars", + "description": "Sets the tick label formatting rule using d3 formatting mini-languages which are very similar to those in Python. For numbers, see: https://github.com/d3/d3-format/blob/master/README.md#locale_format And for dates see: https://github.com/d3/d3-time-format/blob/master/README.md#locale_format We add one item to d3's date formatter: *%{n}f* for fractional seconds with n digits. For example, *2016-10-13 09:15:23.456* with tickformat *%H~%M~%S.%2f* would display *09~15~23.46*" + }, + "tickformatstops": { + "items": { + "tickformatstop": { + "dtickrange": { + "valType": "info_array", + "role": "info", + "items": [ + { + "valType": "any", + "editType": "colorbars" + }, + { + "valType": "any", + "editType": "colorbars" + } + ], + "editType": "colorbars", + "description": "range [*min*, *max*], where *min*, *max* - dtick values which describe some zoom level, it is possible to omit *min* or *max* value by passing *null*" + }, + "value": { + "valType": "string", + "dflt": "", + "role": "style", + "editType": "colorbars", + "description": "string - dtickformat for described zoom level, the same as *tickformat*" + }, + "editType": "colorbars", + "role": "object" + } + }, + "role": "object" + }, + "tickprefix": { + "valType": "string", + "dflt": "", + "role": "style", + "editType": "colorbars", + "description": "Sets a tick label prefix." + }, + "showtickprefix": { + "valType": "enumerated", + "values": [ + "all", + "first", + "last", + "none" + ], + "dflt": "all", + "role": "style", + "editType": "colorbars", + "description": "If *all*, all tick labels are displayed with a prefix. If *first*, only the first tick is displayed with a prefix. If *last*, only the last tick is displayed with a suffix. If *none*, tick prefixes are hidden." + }, + "ticksuffix": { + "valType": "string", + "dflt": "", + "role": "style", + "editType": "colorbars", + "description": "Sets a tick label suffix." + }, + "showticksuffix": { + "valType": "enumerated", + "values": [ + "all", + "first", + "last", + "none" + ], + "dflt": "all", + "role": "style", + "editType": "colorbars", + "description": "Same as `showtickprefix` but for tick suffixes." + }, + "separatethousands": { + "valType": "boolean", + "dflt": false, + "role": "style", + "editType": "colorbars", + "description": "If \"true\", even 4-digit integers are separated" + }, + "exponentformat": { + "valType": "enumerated", + "values": [ + "none", + "e", + "E", + "power", + "SI", + "B" + ], + "dflt": "B", + "role": "style", + "editType": "colorbars", + "description": "Determines a formatting rule for the tick exponents. For example, consider the number 1,000,000,000. If *none*, it appears as 1,000,000,000. If *e*, 1e+9. If *E*, 1E+9. If *power*, 1x10^9 (with 9 in a super script). If *SI*, 1G. If *B*, 1B." + }, + "showexponent": { + "valType": "enumerated", + "values": [ + "all", + "first", + "last", + "none" + ], + "dflt": "all", + "role": "style", + "editType": "colorbars", + "description": "If *all*, all exponents are shown besides their significands. If *first*, only the exponent of the first tick is shown. If *last*, only the exponent of the last tick is shown. If *none*, no exponents appear." + }, + "title": { + "valType": "string", + "role": "info", + "dflt": "Click to enter colorscale title", + "description": "Sets the title of the color bar.", + "editType": "colorbars" + }, + "titlefont": { + "family": { + "valType": "string", + "role": "style", + "noBlank": true, + "strict": true, + "description": "HTML font family - the typeface that will be applied by the web browser. The web browser will only be able to apply a font if it is available on the system which it operates. Provide multiple font families, separated by commas, to indicate the preference in which to apply fonts if they aren't available on the system. The plotly service (at https://plot.ly or on-premise) generates images on a server, where only a select number of fonts are installed and supported. These include *Arial*, *Balto*, *Courier New*, *Droid Sans*,, *Droid Serif*, *Droid Sans Mono*, *Gravitas One*, *Old Standard TT*, *Open Sans*, *Overpass*, *PT Sans Narrow*, *Raleway*, *Times New Roman*.", + "editType": "colorbars" + }, + "size": { + "valType": "number", + "role": "style", + "min": 1, + "editType": "colorbars" + }, + "color": { + "valType": "color", + "role": "style", + "editType": "colorbars" + }, + "description": "Sets this color bar's title font.", + "editType": "colorbars", + "role": "object" + }, + "titleside": { + "valType": "enumerated", + "values": [ + "right", + "top", + "bottom" + ], + "role": "style", + "dflt": "top", + "description": "Determines the location of the colorbar title with respect to the color bar.", + "editType": "colorbars" + }, + "editType": "colorbars", + "role": "object", + "tickvalssrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for tickvals .", + "editType": "none" + }, + "ticktextsrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for ticktext .", + "editType": "none" + } + }, + "xcalendar": { + "valType": "enumerated", + "values": [ + "gregorian", + "chinese", + "coptic", + "discworld", + "ethiopian", + "hebrew", + "islamic", + "julian", + "mayan", + "nanakshahi", + "nepali", + "persian", + "jalali", + "taiwan", + "thai", + "ummalqura" + ], + "role": "info", + "editType": "calc", + "dflt": "gregorian", + "description": "Sets the calendar system to use with `x` date data." + }, + "ycalendar": { + "valType": "enumerated", + "values": [ + "gregorian", + "chinese", + "coptic", + "discworld", + "ethiopian", + "hebrew", + "islamic", + "julian", + "mayan", + "nanakshahi", + "nepali", + "persian", + "jalali", + "taiwan", + "thai", + "ummalqura" + ], + "role": "info", + "editType": "calc", + "dflt": "gregorian", + "description": "Sets the calendar system to use with `y` date data." + }, + "xaxis": { + "valType": "subplotid", + "role": "info", + "dflt": "x", + "editType": "calc+clearAxisTypes", + "description": "Sets a reference between this trace's x coordinates and a 2D cartesian x axis. If *x* (the default value), the x coordinates refer to `layout.xaxis`. If *x2*, the x coordinates refer to `layout.xaxis2`, and so on." + }, + "yaxis": { + "valType": "subplotid", + "role": "info", + "dflt": "y", + "editType": "calc+clearAxisTypes", + "description": "Sets a reference between this trace's y coordinates and a 2D cartesian y axis. If *y* (the default value), the y coordinates refer to `layout.yaxis`. If *y2*, the y coordinates refer to `layout.xaxis2`, and so on." + }, + "idssrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for ids .", + "editType": "none" + }, + "customdatasrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for customdata .", + "editType": "none" + }, + "hoverinfosrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for hoverinfo .", + "editType": "none" + }, + "zsrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for z .", + "editType": "none" + }, + "xsrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for x .", + "editType": "none" + }, + "ysrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for y .", + "editType": "none" + }, + "textsrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for text .", + "editType": "none" + } + } + }, + "scatterternary": { + "meta": { + "hrName": "scatter_ternary", + "description": "Provides similar functionality to the *scatter* type but on a ternary phase diagram. The data is provided by at least two arrays out of `a`, `b`, `c` triplets." + }, + "attributes": { + "type": "scatterternary", + "visible": { + "valType": "enumerated", + "values": [ + true, + false, + "legendonly" + ], + "role": "info", + "dflt": true, + "editType": "calc", + "description": "Determines whether or not this trace is visible. If *legendonly*, the trace is not drawn, but can appear as a legend item (provided that the legend itself is visible)." + }, + "showlegend": { + "valType": "boolean", + "role": "info", + "dflt": true, + "editType": "style", + "description": "Determines whether or not an item corresponding to this trace is shown in the legend." + }, + "legendgroup": { + "valType": "string", + "role": "info", + "dflt": "", + "editType": "style", + "description": "Sets the legend group for this trace. Traces part of the same legend group hide/show at the same time when toggling legend items." + }, + "opacity": { + "valType": "number", + "role": "style", + "min": 0, + "max": 1, + "dflt": 1, + "editType": "style", + "description": "Sets the opacity of the trace." + }, + "name": { + "valType": "string", + "role": "info", + "editType": "style", + "description": "Sets the trace name. The trace name appear as the legend item and on hover." + }, + "uid": { + "valType": "string", + "role": "info", + "dflt": "", + "editType": "calc" + }, + "ids": { + "valType": "data_array", + "editType": "calc", + "description": "Assigns id labels to each datum. These ids for object constancy of data points during animation.", + "role": "data" + }, + "customdata": { + "valType": "data_array", + "editType": "calc", + "description": "Assigns extra data each datum. This may be useful when listening to hover, click and selection events. Note that, *scatter* traces also appends customdata items in the markers DOM elements", + "role": "data" + }, + "selectedpoints": { + "valType": "any", + "role": "info", + "editType": "calc", + "description": "Array containing integer indices of selected points. Has an effect only for traces that support selections. Note that an empty array means an empty selection where the `unselected` are turned on for all points, whereas, any other non-array values means no selection all where the `selected` and `unselected` styles have no effect." + }, + "hoverinfo": { + "valType": "flaglist", + "role": "info", + "flags": [ + "a", + "b", + "c", + "text", + "name" + ], + "extras": [ + "all", + "none", + "skip" + ], + "arrayOk": true, + "dflt": "all", + "editType": "none", + "description": "Determines which trace information appear on hover. If `none` or `skip` are set, no information is displayed upon hovering. But, if `none` is set, click and hover events are still fired." + }, + "hoverlabel": { + "bgcolor": { + "valType": "color", + "role": "style", + "arrayOk": true, + "editType": "none", + "description": "Sets the background color of the hover labels for this trace" + }, + "bordercolor": { + "valType": "color", + "role": "style", + "arrayOk": true, + "editType": "none", + "description": "Sets the border color of the hover labels for this trace." + }, + "font": { + "family": { + "valType": "string", + "role": "style", + "noBlank": true, + "strict": true, + "editType": "none", + "description": "HTML font family - the typeface that will be applied by the web browser. The web browser will only be able to apply a font if it is available on the system which it operates. Provide multiple font families, separated by commas, to indicate the preference in which to apply fonts if they aren't available on the system. The plotly service (at https://plot.ly or on-premise) generates images on a server, where only a select number of fonts are installed and supported. These include *Arial*, *Balto*, *Courier New*, *Droid Sans*,, *Droid Serif*, *Droid Sans Mono*, *Gravitas One*, *Old Standard TT*, *Open Sans*, *Overpass*, *PT Sans Narrow*, *Raleway*, *Times New Roman*.", + "arrayOk": true + }, + "size": { + "valType": "number", + "role": "style", + "min": 1, + "editType": "none", + "arrayOk": true + }, + "color": { + "valType": "color", + "role": "style", + "editType": "none", + "arrayOk": true + }, + "editType": "none", + "description": "Sets the font used in hover labels.", + "role": "object", + "familysrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for family .", + "editType": "none" + }, + "sizesrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for size .", + "editType": "none" + }, + "colorsrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for color .", + "editType": "none" + } + }, + "namelength": { + "valType": "integer", + "min": -1, + "arrayOk": true, + "role": "style", + "editType": "none", + "description": "Sets the length (in number of characters) of the trace name in the hover labels for this trace. -1 shows the whole name regardless of length. 0-3 shows the first 0-3 characters, and an integer >3 will show the whole name if it is less than that many characters, but if it is longer, will truncate to `namelength - 3` characters and add an ellipsis." + }, + "editType": "calc", + "role": "object", + "bgcolorsrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for bgcolor .", + "editType": "none" + }, + "bordercolorsrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for bordercolor .", + "editType": "none" + }, + "namelengthsrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for namelength .", + "editType": "none" + } + }, + "stream": { + "token": { + "valType": "string", + "noBlank": true, + "strict": true, + "role": "info", + "editType": "calc", + "description": "The stream id number links a data trace on a plot with a stream. See https://plot.ly/settings for more details." + }, + "maxpoints": { + "valType": "number", + "min": 0, + "max": 10000, + "dflt": 500, + "role": "info", + "editType": "calc", + "description": "Sets the maximum number of points to keep on the plots from an incoming stream. If `maxpoints` is set to *50*, only the newest 50 points will be displayed on the plot." + }, + "editType": "calc", + "role": "object" + }, + "a": { + "valType": "data_array", + "editType": "calc", + "description": "Sets the quantity of component `a` in each data point. If `a`, `b`, and `c` are all provided, they need not be normalized, only the relative values matter. If only two arrays are provided they must be normalized to match `ternary.sum`.", + "role": "data" + }, + "b": { + "valType": "data_array", + "editType": "calc", + "description": "Sets the quantity of component `a` in each data point. If `a`, `b`, and `c` are all provided, they need not be normalized, only the relative values matter. If only two arrays are provided they must be normalized to match `ternary.sum`.", + "role": "data" + }, + "c": { + "valType": "data_array", + "editType": "calc", + "description": "Sets the quantity of component `a` in each data point. If `a`, `b`, and `c` are all provided, they need not be normalized, only the relative values matter. If only two arrays are provided they must be normalized to match `ternary.sum`.", + "role": "data" + }, + "sum": { + "valType": "number", + "role": "info", + "dflt": 0, + "min": 0, + "editType": "calc", + "description": "The number each triplet should sum to, if only two of `a`, `b`, and `c` are provided. This overrides `ternary.sum` to normalize this specific trace, but does not affect the values displayed on the axes. 0 (or missing) means to use ternary.sum" + }, + "mode": { + "valType": "flaglist", + "flags": [ + "lines", + "markers", + "text" + ], + "extras": [ + "none" + ], + "role": "info", + "editType": "calc", + "description": "Determines the drawing mode for this scatter trace. If the provided `mode` includes *text* then the `text` elements appear at the coordinates. Otherwise, the `text` elements appear on hover. If there are less than 20 points, then the default is *lines+markers*. Otherwise, *lines*.", + "dflt": "markers" + }, + "text": { + "valType": "string", + "role": "info", + "dflt": "", + "arrayOk": true, + "editType": "calc", + "description": "Sets text elements associated with each (a,b,c) point. If a single string, the same string appears over all the data points. If an array of strings, the items are mapped in order to the the data points in (a,b,c). If trace `hoverinfo` contains a *text* flag and *hovertext* is not set, these elements will be seen in the hover labels." + }, + "hovertext": { + "valType": "string", + "role": "info", + "dflt": "", + "arrayOk": true, + "editType": "style", + "description": "Sets hover text elements associated with each (a,b,c) point. If a single string, the same string appears over all the data points. If an array of strings, the items are mapped in order to the the data points in (a,b,c). To be seen, trace `hoverinfo` must contain a *text* flag." + }, + "line": { + "color": { + "valType": "color", + "role": "style", + "editType": "style", + "description": "Sets the line color." + }, + "width": { + "valType": "number", + "min": 0, + "dflt": 2, + "role": "style", + "editType": "style", + "description": "Sets the line width (in px)." + }, + "dash": { + "valType": "string", + "values": [ + "solid", + "dot", + "dash", + "longdash", + "dashdot", + "longdashdot" + ], + "dflt": "solid", + "role": "style", + "editType": "style", + "description": "Sets the dash style of lines. Set to a dash type string (*solid*, *dot*, *dash*, *longdash*, *dashdot*, or *longdashdot*) or a dash length list in px (eg *5px,10px,2px,2px*)." + }, + "shape": { + "valType": "enumerated", + "values": [ + "linear", + "spline" + ], + "dflt": "linear", + "role": "style", + "editType": "plot", + "description": "Determines the line shape. With *spline* the lines are drawn using spline interpolation. The other available values correspond to step-wise line shapes." + }, + "smoothing": { + "valType": "number", + "min": 0, + "max": 1.3, + "dflt": 1, + "role": "style", + "editType": "plot", + "description": "Has an effect only if `shape` is set to *spline* Sets the amount of smoothing. *0* corresponds to no smoothing (equivalent to a *linear* shape)." + }, + "editType": "calc", + "role": "object" + }, + "connectgaps": { + "valType": "boolean", + "dflt": false, + "role": "info", + "editType": "calc", + "description": "Determines whether or not gaps (i.e. {nan} or missing values) in the provided data arrays are connected." + }, + "cliponaxis": { + "valType": "boolean", + "dflt": true, + "role": "info", + "editType": "plot", + "description": "Determines whether or not markers and text nodes are clipped about the subplot axes. To show markers and text nodes above axis lines and tick labels, make sure to set `xaxis.layer` and `yaxis.layer` to *below traces*." + }, + "fill": { + "valType": "enumerated", + "values": [ + "none", + "toself", + "tonext" + ], + "dflt": "none", + "role": "style", + "editType": "calc", + "description": "Sets the area to fill with a solid color. Use with `fillcolor` if not *none*. scatterternary has a subset of the options available to scatter. *toself* connects the endpoints of the trace (or each segment of the trace if it has gaps) into a closed shape. *tonext* fills the space between two traces if one completely encloses the other (eg consecutive contour lines), and behaves like *toself* if there is no trace before it. *tonext* should not be used if one trace does not enclose the other." + }, + "fillcolor": { + "valType": "color", + "role": "style", + "editType": "style", + "description": "Sets the fill color. Defaults to a half-transparent variant of the line color, marker color, or marker line color, whichever is available." + }, + "marker": { + "symbol": { + "valType": "enumerated", + "values": [ + 0, + "circle", + 100, + "circle-open", + 200, + "circle-dot", + 300, + "circle-open-dot", + 1, + "square", + 101, + "square-open", + 201, + "square-dot", + 301, + "square-open-dot", + 2, + "diamond", + 102, + "diamond-open", + 202, + "diamond-dot", + 302, + "diamond-open-dot", + 3, + "cross", + 103, + "cross-open", + 203, + "cross-dot", + 303, + "cross-open-dot", + 4, + "x", + 104, + "x-open", + 204, + "x-dot", + 304, + "x-open-dot", + 5, + "triangle-up", + 105, + "triangle-up-open", + 205, + "triangle-up-dot", + 305, + "triangle-up-open-dot", + 6, + "triangle-down", + 106, + "triangle-down-open", + 206, + "triangle-down-dot", + 306, + "triangle-down-open-dot", + 7, + "triangle-left", + 107, + "triangle-left-open", + 207, + "triangle-left-dot", + 307, + "triangle-left-open-dot", + 8, + "triangle-right", + 108, + "triangle-right-open", + 208, + "triangle-right-dot", + 308, + "triangle-right-open-dot", + 9, + "triangle-ne", + 109, + "triangle-ne-open", + 209, + "triangle-ne-dot", + 309, + "triangle-ne-open-dot", + 10, + "triangle-se", + 110, + "triangle-se-open", + 210, + "triangle-se-dot", + 310, + "triangle-se-open-dot", + 11, + "triangle-sw", + 111, + "triangle-sw-open", + 211, + "triangle-sw-dot", + 311, + "triangle-sw-open-dot", + 12, + "triangle-nw", + 112, + "triangle-nw-open", + 212, + "triangle-nw-dot", + 312, + "triangle-nw-open-dot", + 13, + "pentagon", + 113, + "pentagon-open", + 213, + "pentagon-dot", + 313, + "pentagon-open-dot", + 14, + "hexagon", + 114, + "hexagon-open", + 214, + "hexagon-dot", + 314, + "hexagon-open-dot", + 15, + "hexagon2", + 115, + "hexagon2-open", + 215, + "hexagon2-dot", + 315, + "hexagon2-open-dot", + 16, + "octagon", + 116, + "octagon-open", + 216, + "octagon-dot", + 316, + "octagon-open-dot", + 17, + "star", + 117, + "star-open", + 217, + "star-dot", + 317, + "star-open-dot", + 18, + "hexagram", + 118, + "hexagram-open", + 218, + "hexagram-dot", + 318, + "hexagram-open-dot", + 19, + "star-triangle-up", + 119, + "star-triangle-up-open", + 219, + "star-triangle-up-dot", + 319, + "star-triangle-up-open-dot", + 20, + "star-triangle-down", + 120, + "star-triangle-down-open", + 220, + "star-triangle-down-dot", + 320, + "star-triangle-down-open-dot", + 21, + "star-square", + 121, + "star-square-open", + 221, + "star-square-dot", + 321, + "star-square-open-dot", + 22, + "star-diamond", + 122, + "star-diamond-open", + 222, + "star-diamond-dot", + 322, + "star-diamond-open-dot", + 23, + "diamond-tall", + 123, + "diamond-tall-open", + 223, + "diamond-tall-dot", + 323, + "diamond-tall-open-dot", + 24, + "diamond-wide", + 124, + "diamond-wide-open", + 224, + "diamond-wide-dot", + 324, + "diamond-wide-open-dot", + 25, + "hourglass", + 125, + "hourglass-open", + 26, + "bowtie", + 126, + "bowtie-open", + 27, + "circle-cross", + 127, + "circle-cross-open", + 28, + "circle-x", + 128, + "circle-x-open", + 29, + "square-cross", + 129, + "square-cross-open", + 30, + "square-x", + 130, + "square-x-open", + 31, + "diamond-cross", + 131, + "diamond-cross-open", + 32, + "diamond-x", + 132, + "diamond-x-open", + 33, + "cross-thin", + 133, + "cross-thin-open", + 34, + "x-thin", + 134, + "x-thin-open", + 35, + "asterisk", + 135, + "asterisk-open", + 36, + "hash", + 136, + "hash-open", + 236, + "hash-dot", + 336, + "hash-open-dot", + 37, + "y-up", + 137, + "y-up-open", + 38, + "y-down", + 138, + "y-down-open", + 39, + "y-left", + 139, + "y-left-open", + 40, + "y-right", + 140, + "y-right-open", + 41, + "line-ew", + 141, + "line-ew-open", + 42, + "line-ns", + 142, + "line-ns-open", + 43, + "line-ne", + 143, + "line-ne-open", + 44, + "line-nw", + 144, + "line-nw-open" + ], + "dflt": "circle", + "arrayOk": true, + "role": "style", + "editType": "style", + "description": "Sets the marker symbol type. Adding 100 is equivalent to appending *-open* to a symbol name. Adding 200 is equivalent to appending *-dot* to a symbol name. Adding 300 is equivalent to appending *-open-dot* or *dot-open* to a symbol name." + }, + "opacity": { + "valType": "number", + "min": 0, + "max": 1, + "arrayOk": true, + "role": "style", + "editType": "style", + "description": "Sets the marker opacity." + }, + "maxdisplayed": { + "valType": "number", + "min": 0, + "dflt": 0, + "role": "style", + "editType": "plot", + "description": "Sets a maximum number of points to be drawn on the graph. *0* corresponds to no limit." + }, + "size": { + "valType": "number", + "min": 0, + "dflt": 6, + "arrayOk": true, + "role": "style", + "editType": "calcIfAutorange", + "description": "Sets the marker size (in px)." + }, + "sizeref": { + "valType": "number", + "dflt": 1, + "role": "style", + "editType": "calc", + "description": "Has an effect only if `marker.size` is set to a numerical array. Sets the scale factor used to determine the rendered size of marker points. Use with `sizemin` and `sizemode`." + }, + "sizemin": { + "valType": "number", + "min": 0, + "dflt": 0, + "role": "style", + "editType": "calc", + "description": "Has an effect only if `marker.size` is set to a numerical array. Sets the minimum size (in px) of the rendered marker points." + }, + "sizemode": { + "valType": "enumerated", + "values": [ + "diameter", + "area" + ], + "dflt": "diameter", + "role": "info", + "editType": "calc", + "description": "Has an effect only if `marker.size` is set to a numerical array. Sets the rule for which the data in `size` is converted to pixels." + }, + "line": { + "width": { + "valType": "number", + "min": 0, + "arrayOk": true, + "role": "style", + "editType": "style", + "description": "Sets the width (in px) of the lines bounding the marker points." + }, + "editType": "calc", + "color": { + "valType": "color", + "arrayOk": true, + "role": "style", + "editType": "style", + "description": "Sets the marker.line color. It accepts either a specific color or an array of numbers that are mapped to the colorscale relative to the max and min values of the array or relative to `cmin` and `cmax` if set." + }, + "colorscale": { + "valType": "colorscale", + "role": "style", + "editType": "calc", + "impliedEdits": { + "autocolorscale": false + }, + "description": "Sets the colorscale and only has an effect if `marker.line.color` is set to a numerical array. The colorscale must be an array containing arrays mapping a normalized value to an rgb, rgba, hex, hsl, hsv, or named color string. At minimum, a mapping for the lowest (0) and highest (1) values are required. For example, `[[0, 'rgb(0,0,255)', [1, 'rgb(255,0,0)']]`. To control the bounds of the colorscale in color space, use `marker.line.cmin` and `marker.line.cmax`. Alternatively, `colorscale` may be a palette name string of the following list: Greys, YlGnBu, Greens, YlOrRd, Bluered, RdBu, Reds, Blues, Picnic, Rainbow, Portland, Jet, Hot, Blackbody, Earth, Electric, Viridis" + }, + "cauto": { + "valType": "boolean", + "role": "info", + "dflt": true, + "editType": "calc", + "impliedEdits": {}, + "description": "Has an effect only if `marker.line.color` is set to a numerical array and `cmin`, `cmax` are set by the user. In this case, it controls whether the range of colors in `colorscale` is mapped to the range of values in the `color` array (`cauto: true`), or the `cmin`/`cmax` values (`cauto: false`). Defaults to `false` when `cmin`, `cmax` are set by the user." + }, + "cmax": { + "valType": "number", + "role": "info", + "dflt": null, + "editType": "plot", + "impliedEdits": { + "cauto": false + }, + "description": "Has an effect only if `marker.line.color` is set to a numerical array. Sets the upper bound of the color domain. Value should be associated to the `marker.line.color` array index, and if set, `marker.line.cmin` must be set as well." + }, + "cmin": { + "valType": "number", + "role": "info", + "dflt": null, + "editType": "plot", + "impliedEdits": { + "cauto": false + }, + "description": "Has an effect only if `marker.line.color` is set to a numerical array. Sets the lower bound of the color domain. Value should be associated to the `marker.line.color` array index, and if set, `marker.line.cmax` must be set as well." + }, + "autocolorscale": { + "valType": "boolean", + "role": "style", + "dflt": true, + "editType": "calc", + "impliedEdits": {}, + "description": "Has an effect only if `marker.line.color` is set to a numerical array. Determines whether the colorscale is a default palette (`autocolorscale: true`) or the palette determined by `marker.line.colorscale`. In case `colorscale` is unspecified or `autocolorscale` is true, the default palette will be chosen according to whether numbers in the `color` array are all positive, all negative or mixed." + }, + "reversescale": { + "valType": "boolean", + "role": "style", + "dflt": false, + "editType": "calc", + "description": "Has an effect only if `marker.line.color` is set to a numerical array. Reverses the color mapping if true (`cmin` will correspond to the last color in the array and `cmax` will correspond to the first color)." + }, + "role": "object", + "widthsrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for width .", + "editType": "none" + }, + "colorsrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for color .", + "editType": "none" + } + }, + "gradient": { + "type": { + "valType": "enumerated", + "values": [ + "radial", + "horizontal", + "vertical", + "none" + ], + "arrayOk": true, + "dflt": "none", + "role": "style", + "editType": "calc", + "description": "Sets the type of gradient used to fill the markers" + }, + "color": { + "valType": "color", + "arrayOk": true, + "role": "style", + "editType": "calc", + "description": "Sets the final color of the gradient fill: the center color for radial, the right for horizontal, or the bottom for vertical." + }, + "editType": "calc", + "role": "object", + "typesrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for type .", + "editType": "none" + }, + "colorsrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for color .", + "editType": "none" + } + }, + "editType": "calc", + "color": { + "valType": "color", + "arrayOk": true, + "role": "style", + "editType": "style", + "description": "Sets the marker color. It accepts either a specific color or an array of numbers that are mapped to the colorscale relative to the max and min values of the array or relative to `cmin` and `cmax` if set." + }, + "colorscale": { + "valType": "colorscale", + "role": "style", + "editType": "calc", + "impliedEdits": { + "autocolorscale": false + }, + "description": "Sets the colorscale and only has an effect if `marker.color` is set to a numerical array. The colorscale must be an array containing arrays mapping a normalized value to an rgb, rgba, hex, hsl, hsv, or named color string. At minimum, a mapping for the lowest (0) and highest (1) values are required. For example, `[[0, 'rgb(0,0,255)', [1, 'rgb(255,0,0)']]`. To control the bounds of the colorscale in color space, use `marker.cmin` and `marker.cmax`. Alternatively, `colorscale` may be a palette name string of the following list: Greys, YlGnBu, Greens, YlOrRd, Bluered, RdBu, Reds, Blues, Picnic, Rainbow, Portland, Jet, Hot, Blackbody, Earth, Electric, Viridis" + }, + "cauto": { + "valType": "boolean", + "role": "info", + "dflt": true, + "editType": "calc", + "impliedEdits": {}, + "description": "Has an effect only if `marker.color` is set to a numerical array and `cmin`, `cmax` are set by the user. In this case, it controls whether the range of colors in `colorscale` is mapped to the range of values in the `color` array (`cauto: true`), or the `cmin`/`cmax` values (`cauto: false`). Defaults to `false` when `cmin`, `cmax` are set by the user." + }, + "cmax": { + "valType": "number", + "role": "info", + "dflt": null, + "editType": "plot", + "impliedEdits": { + "cauto": false + }, + "description": "Has an effect only if `marker.color` is set to a numerical array. Sets the upper bound of the color domain. Value should be associated to the `marker.color` array index, and if set, `marker.cmin` must be set as well." + }, + "cmin": { + "valType": "number", + "role": "info", + "dflt": null, + "editType": "plot", + "impliedEdits": { + "cauto": false + }, + "description": "Has an effect only if `marker.color` is set to a numerical array. Sets the lower bound of the color domain. Value should be associated to the `marker.color` array index, and if set, `marker.cmax` must be set as well." + }, + "autocolorscale": { + "valType": "boolean", + "role": "style", + "dflt": true, + "editType": "calc", + "impliedEdits": {}, + "description": "Has an effect only if `marker.color` is set to a numerical array. Determines whether the colorscale is a default palette (`autocolorscale: true`) or the palette determined by `marker.colorscale`. In case `colorscale` is unspecified or `autocolorscale` is true, the default palette will be chosen according to whether numbers in the `color` array are all positive, all negative or mixed." + }, + "reversescale": { + "valType": "boolean", + "role": "style", + "dflt": false, + "editType": "calc", + "description": "Has an effect only if `marker.color` is set to a numerical array. Reverses the color mapping if true (`cmin` will correspond to the last color in the array and `cmax` will correspond to the first color)." + }, + "showscale": { + "valType": "boolean", + "role": "info", + "dflt": false, + "editType": "calc", + "description": "Has an effect only if `marker.color` is set to a numerical array. Determines whether or not a colorbar is displayed." + }, + "colorbar": { + "thicknessmode": { + "valType": "enumerated", + "values": [ + "fraction", + "pixels" + ], + "role": "style", + "dflt": "pixels", + "description": "Determines whether this color bar's thickness (i.e. the measure in the constant color direction) is set in units of plot *fraction* or in *pixels*. Use `thickness` to set the value.", + "editType": "colorbars" + }, + "thickness": { + "valType": "number", + "role": "style", + "min": 0, + "dflt": 30, + "description": "Sets the thickness of the color bar This measure excludes the size of the padding, ticks and labels.", + "editType": "colorbars" + }, + "lenmode": { + "valType": "enumerated", + "values": [ + "fraction", + "pixels" + ], + "role": "info", + "dflt": "fraction", + "description": "Determines whether this color bar's length (i.e. the measure in the color variation direction) is set in units of plot *fraction* or in *pixels. Use `len` to set the value.", + "editType": "colorbars" + }, + "len": { + "valType": "number", + "min": 0, + "dflt": 1, + "role": "style", + "description": "Sets the length of the color bar This measure excludes the padding of both ends. That is, the color bar length is this length minus the padding on both ends.", + "editType": "colorbars" + }, + "x": { + "valType": "number", + "dflt": 1.02, + "min": -2, + "max": 3, + "role": "style", + "description": "Sets the x position of the color bar (in plot fraction).", + "editType": "colorbars" + }, + "xanchor": { + "valType": "enumerated", + "values": [ + "left", + "center", + "right" + ], + "dflt": "left", + "role": "style", + "description": "Sets this color bar's horizontal position anchor. This anchor binds the `x` position to the *left*, *center* or *right* of the color bar.", + "editType": "colorbars" + }, + "xpad": { + "valType": "number", + "role": "style", + "min": 0, + "dflt": 10, + "description": "Sets the amount of padding (in px) along the x direction.", + "editType": "colorbars" + }, + "y": { + "valType": "number", + "role": "style", + "dflt": 0.5, + "min": -2, + "max": 3, + "description": "Sets the y position of the color bar (in plot fraction).", + "editType": "colorbars" + }, + "yanchor": { + "valType": "enumerated", + "values": [ + "top", + "middle", + "bottom" + ], + "role": "style", + "dflt": "middle", + "description": "Sets this color bar's vertical position anchor This anchor binds the `y` position to the *top*, *middle* or *bottom* of the color bar.", + "editType": "colorbars" + }, + "ypad": { + "valType": "number", + "role": "style", + "min": 0, + "dflt": 10, + "description": "Sets the amount of padding (in px) along the y direction.", + "editType": "colorbars" + }, + "outlinecolor": { + "valType": "color", + "dflt": "#444", + "role": "style", + "editType": "colorbars", + "description": "Sets the axis line color." + }, + "outlinewidth": { + "valType": "number", + "min": 0, + "dflt": 1, + "role": "style", + "editType": "colorbars", + "description": "Sets the width (in px) of the axis line." + }, + "bordercolor": { + "valType": "color", + "dflt": "#444", + "role": "style", + "editType": "colorbars", + "description": "Sets the axis line color." + }, + "borderwidth": { + "valType": "number", + "role": "style", + "min": 0, + "dflt": 0, + "description": "Sets the width (in px) or the border enclosing this color bar.", + "editType": "colorbars" + }, + "bgcolor": { + "valType": "color", + "role": "style", + "dflt": "rgba(0,0,0,0)", + "description": "Sets the color of padded area.", + "editType": "colorbars" + }, + "tickmode": { + "valType": "enumerated", + "values": [ + "auto", + "linear", + "array" + ], + "role": "info", + "editType": "colorbars", + "impliedEdits": {}, + "description": "Sets the tick mode for this axis. If *auto*, the number of ticks is set via `nticks`. If *linear*, the placement of the ticks is determined by a starting position `tick0` and a tick step `dtick` (*linear* is the default value if `tick0` and `dtick` are provided). If *array*, the placement of the ticks is set via `tickvals` and the tick text is `ticktext`. (*array* is the default value if `tickvals` is provided)." + }, + "nticks": { + "valType": "integer", + "min": 0, + "dflt": 0, + "role": "style", + "editType": "colorbars", + "description": "Specifies the maximum number of ticks for the particular axis. The actual number of ticks will be chosen automatically to be less than or equal to `nticks`. Has an effect only if `tickmode` is set to *auto*." + }, + "tick0": { + "valType": "any", + "role": "style", + "editType": "colorbars", + "impliedEdits": { + "tickmode": "linear" + }, + "description": "Sets the placement of the first tick on this axis. Use with `dtick`. If the axis `type` is *log*, then you must take the log of your starting tick (e.g. to set the starting tick to 100, set the `tick0` to 2) except when `dtick`=*L* (see `dtick` for more info). If the axis `type` is *date*, it should be a date string, like date data. If the axis `type` is *category*, it should be a number, using the scale where each category is assigned a serial number from zero in the order it appears." + }, + "dtick": { + "valType": "any", + "role": "style", + "editType": "colorbars", + "impliedEdits": { + "tickmode": "linear" + }, + "description": "Sets the step in-between ticks on this axis. Use with `tick0`. Must be a positive number, or special strings available to *log* and *date* axes. If the axis `type` is *log*, then ticks are set every 10^(n*dtick) where n is the tick number. For example, to set a tick mark at 1, 10, 100, 1000, ... set dtick to 1. To set tick marks at 1, 100, 10000, ... set dtick to 2. To set tick marks at 1, 5, 25, 125, 625, 3125, ... set dtick to log_10(5), or 0.69897000433. *log* has several special values; *L*, where `f` is a positive number, gives ticks linearly spaced in value (but not position). For example `tick0` = 0.1, `dtick` = *L0.5* will put ticks at 0.1, 0.6, 1.1, 1.6 etc. To show powers of 10 plus small digits between, use *D1* (all digits) or *D2* (only 2 and 5). `tick0` is ignored for *D1* and *D2*. If the axis `type` is *date*, then you must convert the time to milliseconds. For example, to set the interval between ticks to one day, set `dtick` to 86400000.0. *date* also has special values *M* gives ticks spaced by a number of months. `n` must be a positive integer. To set ticks on the 15th of every third month, set `tick0` to *2000-01-15* and `dtick` to *M3*. To set ticks every 4 years, set `dtick` to *M48*" + }, + "tickvals": { + "valType": "data_array", + "editType": "colorbars", + "description": "Sets the values at which ticks on this axis appear. Only has an effect if `tickmode` is set to *array*. Used with `ticktext`.", + "role": "data" + }, + "ticktext": { + "valType": "data_array", + "editType": "colorbars", + "description": "Sets the text displayed at the ticks position via `tickvals`. Only has an effect if `tickmode` is set to *array*. Used with `tickvals`.", + "role": "data" + }, + "ticks": { + "valType": "enumerated", + "values": [ + "outside", + "inside", + "" + ], + "role": "style", + "editType": "colorbars", + "description": "Determines whether ticks are drawn or not. If **, this axis' ticks are not drawn. If *outside* (*inside*), this axis' are drawn outside (inside) the axis lines.", + "dflt": "" + }, + "ticklen": { + "valType": "number", + "min": 0, + "dflt": 5, + "role": "style", + "editType": "colorbars", + "description": "Sets the tick length (in px)." + }, + "tickwidth": { + "valType": "number", + "min": 0, + "dflt": 1, + "role": "style", + "editType": "colorbars", + "description": "Sets the tick width (in px)." + }, + "tickcolor": { + "valType": "color", + "dflt": "#444", + "role": "style", + "editType": "colorbars", + "description": "Sets the tick color." + }, + "showticklabels": { + "valType": "boolean", + "dflt": true, + "role": "style", + "editType": "colorbars", + "description": "Determines whether or not the tick labels are drawn." + }, + "tickfont": { + "family": { + "valType": "string", + "role": "style", + "noBlank": true, + "strict": true, + "description": "HTML font family - the typeface that will be applied by the web browser. The web browser will only be able to apply a font if it is available on the system which it operates. Provide multiple font families, separated by commas, to indicate the preference in which to apply fonts if they aren't available on the system. The plotly service (at https://plot.ly or on-premise) generates images on a server, where only a select number of fonts are installed and supported. These include *Arial*, *Balto*, *Courier New*, *Droid Sans*,, *Droid Serif*, *Droid Sans Mono*, *Gravitas One*, *Old Standard TT*, *Open Sans*, *Overpass*, *PT Sans Narrow*, *Raleway*, *Times New Roman*.", + "editType": "colorbars" + }, + "size": { + "valType": "number", + "role": "style", + "min": 1, + "editType": "colorbars" + }, + "color": { + "valType": "color", + "role": "style", + "editType": "colorbars" + }, + "description": "Sets the color bar's tick label font", + "editType": "colorbars", + "role": "object" + }, + "tickangle": { + "valType": "angle", + "dflt": "auto", + "role": "style", + "editType": "colorbars", + "description": "Sets the angle of the tick labels with respect to the horizontal. For example, a `tickangle` of -90 draws the tick labels vertically." + }, + "tickformat": { + "valType": "string", + "dflt": "", + "role": "style", + "editType": "colorbars", + "description": "Sets the tick label formatting rule using d3 formatting mini-languages which are very similar to those in Python. For numbers, see: https://github.com/d3/d3-format/blob/master/README.md#locale_format And for dates see: https://github.com/d3/d3-time-format/blob/master/README.md#locale_format We add one item to d3's date formatter: *%{n}f* for fractional seconds with n digits. For example, *2016-10-13 09:15:23.456* with tickformat *%H~%M~%S.%2f* would display *09~15~23.46*" + }, + "tickformatstops": { + "items": { + "tickformatstop": { + "dtickrange": { + "valType": "info_array", + "role": "info", + "items": [ + { + "valType": "any", + "editType": "colorbars" + }, + { + "valType": "any", + "editType": "colorbars" + } + ], + "editType": "colorbars", + "description": "range [*min*, *max*], where *min*, *max* - dtick values which describe some zoom level, it is possible to omit *min* or *max* value by passing *null*" + }, + "value": { + "valType": "string", + "dflt": "", + "role": "style", + "editType": "colorbars", + "description": "string - dtickformat for described zoom level, the same as *tickformat*" + }, + "editType": "colorbars", + "role": "object" + } + }, + "role": "object" + }, + "tickprefix": { + "valType": "string", + "dflt": "", + "role": "style", + "editType": "colorbars", + "description": "Sets a tick label prefix." + }, + "showtickprefix": { + "valType": "enumerated", + "values": [ + "all", + "first", + "last", + "none" + ], + "dflt": "all", + "role": "style", + "editType": "colorbars", + "description": "If *all*, all tick labels are displayed with a prefix. If *first*, only the first tick is displayed with a prefix. If *last*, only the last tick is displayed with a suffix. If *none*, tick prefixes are hidden." + }, + "ticksuffix": { + "valType": "string", + "dflt": "", + "role": "style", + "editType": "colorbars", + "description": "Sets a tick label suffix." + }, + "showticksuffix": { + "valType": "enumerated", + "values": [ + "all", + "first", + "last", + "none" + ], + "dflt": "all", + "role": "style", + "editType": "colorbars", + "description": "Same as `showtickprefix` but for tick suffixes." + }, + "separatethousands": { + "valType": "boolean", + "dflt": false, + "role": "style", + "editType": "colorbars", + "description": "If \"true\", even 4-digit integers are separated" + }, + "exponentformat": { + "valType": "enumerated", + "values": [ + "none", + "e", + "E", + "power", + "SI", + "B" + ], + "dflt": "B", + "role": "style", + "editType": "colorbars", + "description": "Determines a formatting rule for the tick exponents. For example, consider the number 1,000,000,000. If *none*, it appears as 1,000,000,000. If *e*, 1e+9. If *E*, 1E+9. If *power*, 1x10^9 (with 9 in a super script). If *SI*, 1G. If *B*, 1B." + }, + "showexponent": { + "valType": "enumerated", + "values": [ + "all", + "first", + "last", + "none" + ], + "dflt": "all", + "role": "style", + "editType": "colorbars", + "description": "If *all*, all exponents are shown besides their significands. If *first*, only the exponent of the first tick is shown. If *last*, only the exponent of the last tick is shown. If *none*, no exponents appear." + }, + "title": { + "valType": "string", + "role": "info", + "dflt": "Click to enter colorscale title", + "description": "Sets the title of the color bar.", + "editType": "colorbars" + }, + "titlefont": { + "family": { + "valType": "string", + "role": "style", + "noBlank": true, + "strict": true, + "description": "HTML font family - the typeface that will be applied by the web browser. The web browser will only be able to apply a font if it is available on the system which it operates. Provide multiple font families, separated by commas, to indicate the preference in which to apply fonts if they aren't available on the system. The plotly service (at https://plot.ly or on-premise) generates images on a server, where only a select number of fonts are installed and supported. These include *Arial*, *Balto*, *Courier New*, *Droid Sans*,, *Droid Serif*, *Droid Sans Mono*, *Gravitas One*, *Old Standard TT*, *Open Sans*, *Overpass*, *PT Sans Narrow*, *Raleway*, *Times New Roman*.", + "editType": "colorbars" + }, + "size": { + "valType": "number", + "role": "style", + "min": 1, + "editType": "colorbars" + }, + "color": { + "valType": "color", + "role": "style", + "editType": "colorbars" + }, + "description": "Sets this color bar's title font.", + "editType": "colorbars", + "role": "object" + }, + "titleside": { + "valType": "enumerated", + "values": [ + "right", + "top", + "bottom" + ], + "role": "style", + "dflt": "top", + "description": "Determines the location of the colorbar title with respect to the color bar.", + "editType": "colorbars" + }, + "editType": "colorbars", + "role": "object", + "tickvalssrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for tickvals .", + "editType": "none" + }, + "ticktextsrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for ticktext .", + "editType": "none" + } + }, + "role": "object", + "symbolsrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for symbol .", + "editType": "none" + }, + "opacitysrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for opacity .", + "editType": "none" + }, + "sizesrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for size .", + "editType": "none" + }, + "colorsrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for color .", + "editType": "none" + } + }, + "textfont": { + "family": { + "valType": "string", + "role": "style", + "noBlank": true, + "strict": true, + "editType": "calc", + "description": "HTML font family - the typeface that will be applied by the web browser. The web browser will only be able to apply a font if it is available on the system which it operates. Provide multiple font families, separated by commas, to indicate the preference in which to apply fonts if they aren't available on the system. The plotly service (at https://plot.ly or on-premise) generates images on a server, where only a select number of fonts are installed and supported. These include *Arial*, *Balto*, *Courier New*, *Droid Sans*,, *Droid Serif*, *Droid Sans Mono*, *Gravitas One*, *Old Standard TT*, *Open Sans*, *Overpass*, *PT Sans Narrow*, *Raleway*, *Times New Roman*.", + "arrayOk": true + }, + "size": { + "valType": "number", + "role": "style", + "min": 1, + "editType": "calc", + "arrayOk": true + }, + "color": { + "valType": "color", + "role": "style", + "editType": "style", + "arrayOk": true + }, + "editType": "calc", + "description": "Sets the text font.", + "role": "object", + "familysrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for family .", + "editType": "none" + }, + "sizesrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for size .", + "editType": "none" + }, + "colorsrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for color .", + "editType": "none" + } + }, + "textposition": { + "valType": "enumerated", + "values": [ + "top left", + "top center", + "top right", + "middle left", + "middle center", + "middle right", + "bottom left", + "bottom center", + "bottom right" + ], + "dflt": "middle center", + "arrayOk": true, + "role": "style", + "editType": "calc", + "description": "Sets the positions of the `text` elements with respects to the (x,y) coordinates." + }, + "selected": { + "marker": { + "opacity": { + "valType": "number", + "min": 0, + "max": 1, + "role": "style", + "editType": "style", + "description": "Sets the marker opacity of selected points." + }, + "color": { + "valType": "color", + "role": "style", + "editType": "style", + "description": "Sets the marker color of selected points." + }, + "size": { + "valType": "number", + "min": 0, + "role": "style", + "editType": "style", + "description": "Sets the marker size of selected points." + }, + "editType": "style", + "role": "object" + }, + "textfont": { + "color": { + "valType": "color", + "role": "style", + "editType": "style", + "description": "Sets the text font color of selected points." + }, + "editType": "style", + "role": "object" + }, + "editType": "style", + "role": "object" + }, + "unselected": { + "marker": { + "opacity": { + "valType": "number", + "min": 0, + "max": 1, + "role": "style", + "editType": "style", + "description": "Sets the marker opacity of unselected points, applied only when a selection exists." + }, + "color": { + "valType": "color", + "role": "style", + "editType": "style", + "description": "Sets the marker color of unselected points, applied only when a selection exists." + }, + "size": { + "valType": "number", + "min": 0, + "role": "style", + "editType": "style", + "description": "Sets the marker size of unselected points, applied only when a selection exists." + }, + "editType": "style", + "role": "object" + }, + "textfont": { + "color": { + "valType": "color", + "role": "style", + "editType": "style", + "description": "Sets the text font color of unselected points, applied only when a selection exists." + }, + "editType": "style", + "role": "object" + }, + "editType": "style", + "role": "object" + }, + "hoveron": { + "valType": "flaglist", + "flags": [ + "points", + "fills" + ], + "role": "info", + "editType": "style", + "description": "Do the hover effects highlight individual points (markers or line points) or do they highlight filled regions? If the fill is *toself* or *tonext* and there are no markers or text, then the default is *fills*, otherwise it is *points*." + }, + "subplot": { + "valType": "subplotid", + "role": "info", + "dflt": "ternary", + "editType": "calc", + "description": "Sets a reference between this trace's data coordinates and a ternary subplot. If *ternary* (the default value), the data refer to `layout.ternary`. If *ternary2*, the data refer to `layout.ternary2`, and so on." + }, + "idssrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for ids .", + "editType": "none" + }, + "customdatasrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for customdata .", + "editType": "none" + }, + "hoverinfosrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for hoverinfo .", + "editType": "none" + }, + "asrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for a .", + "editType": "none" + }, + "bsrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for b .", + "editType": "none" + }, + "csrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for c .", + "editType": "none" + }, + "textsrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for text .", + "editType": "none" + }, + "hovertextsrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for hovertext .", + "editType": "none" + }, + "textpositionsrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for textposition .", + "editType": "none" + } + } + }, + "violin": { + "meta": { + "description": "In vertical (horizontal) violin plots, statistics are computed using `y` (`x`) values. By supplying an `x` (`y`) array, one violin per distinct x (y) value is drawn If no `x` (`y`) {array} is provided, a single violin is drawn. That violin position is then positioned with with `name` or with `x0` (`y0`) if provided." + }, + "attributes": { + "type": "violin", + "visible": { + "valType": "enumerated", + "values": [ + true, + false, + "legendonly" + ], + "role": "info", + "dflt": true, + "editType": "calc", + "description": "Determines whether or not this trace is visible. If *legendonly*, the trace is not drawn, but can appear as a legend item (provided that the legend itself is visible)." + }, + "showlegend": { + "valType": "boolean", + "role": "info", + "dflt": true, + "editType": "style", + "description": "Determines whether or not an item corresponding to this trace is shown in the legend." + }, + "legendgroup": { + "valType": "string", + "role": "info", + "dflt": "", + "editType": "style", + "description": "Sets the legend group for this trace. Traces part of the same legend group hide/show at the same time when toggling legend items." + }, + "opacity": { + "valType": "number", + "role": "style", + "min": 0, + "max": 1, + "dflt": 1, + "editType": "style", + "description": "Sets the opacity of the trace." + }, + "name": { + "valType": "string", + "role": "info", + "editType": "calc+clearAxisTypes", + "description": "Sets the trace name. The trace name appear as the legend item and on hover. For box traces, the name will also be used for the position coordinate, if `x` and `x0` (`y` and `y0` if horizontal) are missing and the position axis is categorical" + }, + "uid": { + "valType": "string", + "role": "info", + "dflt": "", + "editType": "calc" + }, + "ids": { + "valType": "data_array", + "editType": "calc", + "description": "Assigns id labels to each datum. These ids for object constancy of data points during animation.", + "role": "data" + }, + "customdata": { + "valType": "data_array", + "editType": "calc", + "description": "Assigns extra data each datum. This may be useful when listening to hover, click and selection events. Note that, *scatter* traces also appends customdata items in the markers DOM elements", + "role": "data" + }, + "selectedpoints": { + "valType": "any", + "role": "info", + "editType": "calc", + "description": "Array containing integer indices of selected points. Has an effect only for traces that support selections. Note that an empty array means an empty selection where the `unselected` are turned on for all points, whereas, any other non-array values means no selection all where the `selected` and `unselected` styles have no effect." + }, + "hoverinfo": { + "valType": "flaglist", + "role": "info", + "flags": [ + "x", + "y", + "z", + "text", + "name" + ], + "extras": [ + "all", + "none", + "skip" + ], + "arrayOk": true, + "dflt": "all", + "editType": "none", + "description": "Determines which trace information appear on hover. If `none` or `skip` are set, no information is displayed upon hovering. But, if `none` is set, click and hover events are still fired." + }, + "hoverlabel": { + "bgcolor": { + "valType": "color", + "role": "style", + "arrayOk": true, + "editType": "none", + "description": "Sets the background color of the hover labels for this trace" + }, + "bordercolor": { + "valType": "color", + "role": "style", + "arrayOk": true, + "editType": "none", + "description": "Sets the border color of the hover labels for this trace." + }, + "font": { + "family": { + "valType": "string", + "role": "style", + "noBlank": true, + "strict": true, + "editType": "none", + "description": "HTML font family - the typeface that will be applied by the web browser. The web browser will only be able to apply a font if it is available on the system which it operates. Provide multiple font families, separated by commas, to indicate the preference in which to apply fonts if they aren't available on the system. The plotly service (at https://plot.ly or on-premise) generates images on a server, where only a select number of fonts are installed and supported. These include *Arial*, *Balto*, *Courier New*, *Droid Sans*,, *Droid Serif*, *Droid Sans Mono*, *Gravitas One*, *Old Standard TT*, *Open Sans*, *Overpass*, *PT Sans Narrow*, *Raleway*, *Times New Roman*.", + "arrayOk": true + }, + "size": { + "valType": "number", + "role": "style", + "min": 1, + "editType": "none", + "arrayOk": true + }, + "color": { + "valType": "color", + "role": "style", + "editType": "none", + "arrayOk": true + }, + "editType": "none", + "description": "Sets the font used in hover labels.", + "role": "object", + "familysrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for family .", + "editType": "none" + }, + "sizesrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for size .", + "editType": "none" + }, + "colorsrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for color .", + "editType": "none" + } + }, + "namelength": { + "valType": "integer", + "min": -1, + "arrayOk": true, + "role": "style", + "editType": "none", + "description": "Sets the length (in number of characters) of the trace name in the hover labels for this trace. -1 shows the whole name regardless of length. 0-3 shows the first 0-3 characters, and an integer >3 will show the whole name if it is less than that many characters, but if it is longer, will truncate to `namelength - 3` characters and add an ellipsis." + }, + "editType": "calc", + "role": "object", + "bgcolorsrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for bgcolor .", + "editType": "none" + }, + "bordercolorsrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for bordercolor .", + "editType": "none" + }, + "namelengthsrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for namelength .", + "editType": "none" + } + }, + "stream": { + "token": { + "valType": "string", + "noBlank": true, + "strict": true, + "role": "info", + "editType": "calc", + "description": "The stream id number links a data trace on a plot with a stream. See https://plot.ly/settings for more details." + }, + "maxpoints": { + "valType": "number", + "min": 0, + "max": 10000, + "dflt": 500, + "role": "info", + "editType": "calc", + "description": "Sets the maximum number of points to keep on the plots from an incoming stream. If `maxpoints` is set to *50*, only the newest 50 points will be displayed on the plot." + }, + "editType": "calc", + "role": "object" + }, + "y": { + "valType": "data_array", + "editType": "calc+clearAxisTypes", + "description": "Sets the y sample data or coordinates. See overview for more info.", + "role": "data" + }, + "x": { + "valType": "data_array", + "editType": "calc+clearAxisTypes", + "description": "Sets the x sample data or coordinates. See overview for more info.", + "role": "data" + }, + "x0": { + "valType": "any", + "role": "info", + "editType": "calc+clearAxisTypes", + "description": "Sets the x coordinate of the box. See overview for more info." + }, + "y0": { + "valType": "any", + "role": "info", + "editType": "calc+clearAxisTypes", + "description": "Sets the y coordinate of the box. See overview for more info." + }, + "orientation": { + "valType": "enumerated", + "values": [ + "v", + "h" + ], + "role": "style", + "editType": "calc+clearAxisTypes", + "description": "Sets the orientation of the violin(s). If *v* (*h*), the distribution is visualized along the vertical (horizontal)." + }, + "bandwidth": { + "valType": "number", + "min": 0, + "role": "info", + "editType": "calc", + "description": "Sets the bandwidth used to compute the kernel density estimate. By default, the bandwidth is determined by Silverman's rule of thumb." + }, + "scalegroup": { + "valType": "string", + "role": "info", + "dflt": "", + "editType": "calc", + "description": "If there are multiple violins that should be sized according to to some metric (see `scalemode`), link them by providing a non-empty group id here shared by every trace in the same group." + }, + "scalemode": { + "valType": "enumerated", + "values": [ + "width", + "count" + ], + "dflt": "width", + "role": "info", + "editType": "calc", + "description": "Sets the metric by which the width of each violin is determined.*width* means each violin has the same (max) width*count* means the violins are scaled by the number of sample points makingup each violin." + }, + "spanmode": { + "valType": "enumerated", + "values": [ + "soft", + "hard", + "manual" + ], + "dflt": "soft", + "role": "info", + "editType": "calc", + "description": "Sets the method by which the span in data space where the density function will be computed. *soft* means the span goes from the sample's minimum value minus two bandwidths to the sample's maximum value plus two bandwidths. *hard* means the span goes from the sample's minimum to its maximum value. For custom span settings, use mode *manual* and fill in the `span` attribute." + }, + "span": { + "valType": "info_array", + "items": [ + { + "valType": "any", + "editType": "calc" + }, + { + "valType": "any", + "editType": "calc" + } + ], + "role": "info", + "editType": "calc", + "description": "Sets the span in data space for which the density function will be computed. Has an effect only when `spanmode` is set to *manual*." + }, + "line": { + "color": { + "valType": "color", + "role": "style", + "editType": "style", + "description": "Sets the color of line bounding the violin(s)." + }, + "width": { + "valType": "number", + "role": "style", + "min": 0, + "dflt": 2, + "editType": "style", + "description": "Sets the width (in px) of line bounding the violin(s)." + }, + "editType": "plot", + "role": "object" + }, + "fillcolor": { + "valType": "color", + "role": "style", + "editType": "style", + "description": "Sets the fill color. Defaults to a half-transparent variant of the line color, marker color, or marker line color, whichever is available." + }, + "points": { + "valType": "enumerated", + "values": [ + "all", + "outliers", + "suspectedoutliers", + false + ], + "dflt": "outliers", + "role": "style", + "editType": "calcIfAutorange", + "description": "If *outliers*, only the sample points lying outside the whiskers are shown If *suspectedoutliers*, the outlier points are shown and points either less than 4*Q1-3*Q3 or greater than 4*Q3-3*Q1 are highlighted (see `outliercolor`) If *all*, all sample points are shown If *false*, only the violins are shown with no sample points" + }, + "jitter": { + "valType": "number", + "min": 0, + "max": 1, + "role": "style", + "editType": "calcIfAutorange", + "description": "Sets the amount of jitter in the sample points drawn. If *0*, the sample points align along the distribution axis. If *1*, the sample points are drawn in a random jitter of width equal to the width of the violins." + }, + "pointpos": { + "valType": "number", + "min": -2, + "max": 2, + "role": "style", + "editType": "calcIfAutorange", + "description": "Sets the position of the sample points in relation to the violins. If *0*, the sample points are places over the center of the violins. Positive (negative) values correspond to positions to the right (left) for vertical violins and above (below) for horizontal violins." + }, + "marker": { + "outliercolor": { + "valType": "color", + "dflt": "rgba(0, 0, 0, 0)", + "role": "style", + "editType": "style", + "description": "Sets the color of the outlier sample points." + }, + "symbol": { + "valType": "enumerated", + "values": [ + 0, + "circle", + 100, + "circle-open", + 200, + "circle-dot", + 300, + "circle-open-dot", + 1, + "square", + 101, + "square-open", + 201, + "square-dot", + 301, + "square-open-dot", + 2, + "diamond", + 102, + "diamond-open", + 202, + "diamond-dot", + 302, + "diamond-open-dot", + 3, + "cross", + 103, + "cross-open", + 203, + "cross-dot", + 303, + "cross-open-dot", + 4, + "x", + 104, + "x-open", + 204, + "x-dot", + 304, + "x-open-dot", + 5, + "triangle-up", + 105, + "triangle-up-open", + 205, + "triangle-up-dot", + 305, + "triangle-up-open-dot", + 6, + "triangle-down", + 106, + "triangle-down-open", + 206, + "triangle-down-dot", + 306, + "triangle-down-open-dot", + 7, + "triangle-left", + 107, + "triangle-left-open", + 207, + "triangle-left-dot", + 307, + "triangle-left-open-dot", + 8, + "triangle-right", + 108, + "triangle-right-open", + 208, + "triangle-right-dot", + 308, + "triangle-right-open-dot", + 9, + "triangle-ne", + 109, + "triangle-ne-open", + 209, + "triangle-ne-dot", + 309, + "triangle-ne-open-dot", + 10, + "triangle-se", + 110, + "triangle-se-open", + 210, + "triangle-se-dot", + 310, + "triangle-se-open-dot", + 11, + "triangle-sw", + 111, + "triangle-sw-open", + 211, + "triangle-sw-dot", + 311, + "triangle-sw-open-dot", + 12, + "triangle-nw", + 112, + "triangle-nw-open", + 212, + "triangle-nw-dot", + 312, + "triangle-nw-open-dot", + 13, + "pentagon", + 113, + "pentagon-open", + 213, + "pentagon-dot", + 313, + "pentagon-open-dot", + 14, + "hexagon", + 114, + "hexagon-open", + 214, + "hexagon-dot", + 314, + "hexagon-open-dot", + 15, + "hexagon2", + 115, + "hexagon2-open", + 215, + "hexagon2-dot", + 315, + "hexagon2-open-dot", + 16, + "octagon", + 116, + "octagon-open", + 216, + "octagon-dot", + 316, + "octagon-open-dot", + 17, + "star", + 117, + "star-open", + 217, + "star-dot", + 317, + "star-open-dot", + 18, + "hexagram", + 118, + "hexagram-open", + 218, + "hexagram-dot", + 318, + "hexagram-open-dot", + 19, + "star-triangle-up", + 119, + "star-triangle-up-open", + 219, + "star-triangle-up-dot", + 319, + "star-triangle-up-open-dot", + 20, + "star-triangle-down", + 120, + "star-triangle-down-open", + 220, + "star-triangle-down-dot", + 320, + "star-triangle-down-open-dot", + 21, + "star-square", + 121, + "star-square-open", + 221, + "star-square-dot", + 321, + "star-square-open-dot", + 22, + "star-diamond", + 122, + "star-diamond-open", + 222, + "star-diamond-dot", + 322, + "star-diamond-open-dot", + 23, + "diamond-tall", + 123, + "diamond-tall-open", + 223, + "diamond-tall-dot", + 323, + "diamond-tall-open-dot", + 24, + "diamond-wide", + 124, + "diamond-wide-open", + 224, + "diamond-wide-dot", + 324, + "diamond-wide-open-dot", + 25, + "hourglass", + 125, + "hourglass-open", + 26, + "bowtie", + 126, + "bowtie-open", + 27, + "circle-cross", + 127, + "circle-cross-open", + 28, + "circle-x", + 128, + "circle-x-open", + 29, + "square-cross", + 129, + "square-cross-open", + 30, + "square-x", + 130, + "square-x-open", + 31, + "diamond-cross", + 131, + "diamond-cross-open", + 32, + "diamond-x", + 132, + "diamond-x-open", + 33, + "cross-thin", + 133, + "cross-thin-open", + 34, + "x-thin", + 134, + "x-thin-open", + 35, + "asterisk", + 135, + "asterisk-open", + 36, + "hash", + 136, + "hash-open", + 236, + "hash-dot", + 336, + "hash-open-dot", + 37, + "y-up", + 137, + "y-up-open", + 38, + "y-down", + 138, + "y-down-open", + 39, + "y-left", + 139, + "y-left-open", + 40, + "y-right", + 140, + "y-right-open", + 41, + "line-ew", + 141, + "line-ew-open", + 42, + "line-ns", + 142, + "line-ns-open", + 43, + "line-ne", + 143, + "line-ne-open", + 44, + "line-nw", + 144, + "line-nw-open" + ], + "dflt": "circle", + "arrayOk": false, + "role": "style", + "editType": "plot", + "description": "Sets the marker symbol type. Adding 100 is equivalent to appending *-open* to a symbol name. Adding 200 is equivalent to appending *-dot* to a symbol name. Adding 300 is equivalent to appending *-open-dot* or *dot-open* to a symbol name." + }, + "opacity": { + "valType": "number", + "min": 0, + "max": 1, + "arrayOk": false, + "role": "style", + "editType": "style", + "description": "Sets the marker opacity.", + "dflt": 1 + }, + "size": { + "valType": "number", + "min": 0, + "dflt": 6, + "arrayOk": false, + "role": "style", + "editType": "calcIfAutorange", + "description": "Sets the marker size (in px)." + }, + "color": { + "valType": "color", + "arrayOk": false, + "role": "style", + "editType": "style", + "description": "Sets the marker color. It accepts either a specific color or an array of numbers that are mapped to the colorscale relative to the max and min values of the array or relative to `cmin` and `cmax` if set." + }, + "line": { + "color": { + "valType": "color", + "arrayOk": false, + "role": "style", + "editType": "style", + "description": "Sets the marker.line color. It accepts either a specific color or an array of numbers that are mapped to the colorscale relative to the max and min values of the array or relative to `cmin` and `cmax` if set.", + "dflt": "#444" + }, + "width": { + "valType": "number", + "min": 0, + "arrayOk": false, + "role": "style", + "editType": "style", + "description": "Sets the width (in px) of the lines bounding the marker points.", + "dflt": 0 + }, + "outliercolor": { + "valType": "color", + "role": "style", + "editType": "style", + "description": "Sets the border line color of the outlier sample points. Defaults to marker.color" + }, + "outlierwidth": { + "valType": "number", + "min": 0, + "dflt": 1, + "role": "style", + "editType": "style", + "description": "Sets the border line width (in px) of the outlier sample points." + }, + "editType": "style", + "role": "object" + }, + "editType": "plot", + "role": "object" + }, + "text": { + "valType": "string", + "role": "info", + "dflt": "", + "arrayOk": true, + "editType": "calc", + "description": "Sets the text elements associated with each sample value. If a single string, the same string appears over all the data points. If an array of string, the items are mapped in order to the this trace's (x,y) coordinates. To be seen, trace `hoverinfo` must contain a *text* flag." + }, + "box": { + "visible": { + "valType": "boolean", + "dflt": false, + "role": "info", + "editType": "plot", + "description": "Determines if an miniature box plot is drawn inside the violins. " + }, + "width": { + "valType": "number", + "min": 0, + "max": 1, + "dflt": 0.25, + "role": "info", + "editType": "plot", + "description": "Sets the width of the inner box plots relative to the violins' width. For example, with 1, the inner box plots are as wide as the violins." + }, + "fillcolor": { + "valType": "color", + "role": "style", + "editType": "style", + "description": "Sets the inner box plot fill color." + }, + "line": { + "color": { + "valType": "color", + "role": "style", + "editType": "style", + "description": "Sets the inner box plot bounding line color." + }, + "width": { + "valType": "number", + "min": 0, + "role": "style", + "editType": "style", + "description": "Sets the inner box plot bounding line width." + }, + "editType": "style", + "role": "object" + }, + "editType": "plot", + "role": "object" + }, + "meanline": { + "visible": { + "valType": "boolean", + "dflt": false, + "role": "info", + "editType": "plot", + "description": "Determines if a line corresponding to the sample's mean is shown inside the violins. If `box.visible` is turned on, the mean line is drawn inside the inner box. Otherwise, the mean line is drawn from one side of the violin to other." + }, + "color": { + "valType": "color", + "role": "style", + "editType": "style", + "description": "Sets the mean line color." + }, + "width": { + "valType": "number", + "min": 0, + "role": "style", + "editType": "style", + "description": "Sets the mean line width." + }, + "editType": "plot", + "role": "object" + }, + "side": { + "valType": "enumerated", + "values": [ + "both", + "positive", + "negative" + ], + "dflt": "both", + "role": "info", + "editType": "plot", + "description": "Determines on which side of the position value the density function making up one half of a violin is plotted. Useful when comparing two violin traces under *overlay* mode, where one trace has `side` set to *positive* and the other to *negative*." + }, + "selected": { + "marker": { + "opacity": { + "valType": "number", + "min": 0, + "max": 1, + "role": "style", + "editType": "style", + "description": "Sets the marker opacity of selected points." + }, + "color": { + "valType": "color", + "role": "style", + "editType": "style", + "description": "Sets the marker color of selected points." + }, + "size": { + "valType": "number", + "min": 0, + "role": "style", + "editType": "style", + "description": "Sets the marker size of selected points." + }, + "editType": "style", + "role": "object" + }, + "editType": "style", + "role": "object" + }, + "unselected": { + "marker": { + "opacity": { + "valType": "number", + "min": 0, + "max": 1, + "role": "style", + "editType": "style", + "description": "Sets the marker opacity of unselected points, applied only when a selection exists." + }, + "color": { + "valType": "color", + "role": "style", + "editType": "style", + "description": "Sets the marker color of unselected points, applied only when a selection exists." + }, + "size": { + "valType": "number", + "min": 0, + "role": "style", + "editType": "style", + "description": "Sets the marker size of unselected points, applied only when a selection exists." + }, + "editType": "style", + "role": "object" + }, + "editType": "style", + "role": "object" + }, + "hoveron": { + "valType": "flaglist", + "flags": [ + "violins", + "points", + "kde" + ], + "dflt": "violins+points+kde", + "extras": [ + "all" + ], + "role": "info", + "editType": "style", + "description": "Do the hover effects highlight individual violins or sample points or the kernel density estimate or any combination of them?" + }, + "xaxis": { + "valType": "subplotid", + "role": "info", + "dflt": "x", + "editType": "calc+clearAxisTypes", + "description": "Sets a reference between this trace's x coordinates and a 2D cartesian x axis. If *x* (the default value), the x coordinates refer to `layout.xaxis`. If *x2*, the x coordinates refer to `layout.xaxis2`, and so on." + }, + "yaxis": { + "valType": "subplotid", + "role": "info", + "dflt": "y", + "editType": "calc+clearAxisTypes", + "description": "Sets a reference between this trace's y coordinates and a 2D cartesian y axis. If *y* (the default value), the y coordinates refer to `layout.yaxis`. If *y2*, the y coordinates refer to `layout.xaxis2`, and so on." + }, + "idssrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for ids .", + "editType": "none" + }, + "customdatasrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for customdata .", + "editType": "none" + }, + "hoverinfosrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for hoverinfo .", + "editType": "none" + }, + "ysrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for y .", + "editType": "none" + }, + "xsrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for x .", + "editType": "none" + }, + "textsrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for text .", + "editType": "none" + } + }, + "layoutAttributes": { + "violinmode": { + "valType": "enumerated", + "values": [ + "group", + "overlay" + ], + "dflt": "overlay", + "role": "info", + "editType": "calc", + "description": "Determines how violins at the same location coordinate are displayed on the graph. If *group*, the violins are plotted next to one another centered around the shared location. If *overlay*, the violins are plotted over one another, you might need to set *opacity* to see them multiple violins." + }, + "violingap": { + "valType": "number", + "min": 0, + "max": 1, + "dflt": 0.3, + "role": "style", + "editType": "calc", + "description": "Sets the gap (in plot fraction) between violins of adjacent location coordinates." + }, + "violingroupgap": { + "valType": "number", + "min": 0, + "max": 1, + "dflt": 0.3, + "role": "style", + "editType": "calc", + "description": "Sets the gap (in plot fraction) between violins of the same location coordinate." + } + } + }, + "scatter3d": { + "meta": { + "hrName": "scatter_3d", + "description": "The data visualized as scatter point or lines in 3D dimension is set in `x`, `y`, `z`. Text (appearing either on the chart or on hover only) is via `text`. Bubble charts are achieved by setting `marker.size` and/or `marker.color` Projections are achieved via `projection`. Surface fills are achieved via `surfaceaxis`." + }, + "attributes": { + "type": "scatter3d", + "visible": { + "valType": "enumerated", + "values": [ + true, + false, + "legendonly" + ], + "role": "info", + "dflt": true, + "editType": "calc", + "description": "Determines whether or not this trace is visible. If *legendonly*, the trace is not drawn, but can appear as a legend item (provided that the legend itself is visible)." + }, + "showlegend": { + "valType": "boolean", + "role": "info", + "dflt": true, + "editType": "style", + "description": "Determines whether or not an item corresponding to this trace is shown in the legend." + }, + "legendgroup": { + "valType": "string", + "role": "info", + "dflt": "", + "editType": "style", + "description": "Sets the legend group for this trace. Traces part of the same legend group hide/show at the same time when toggling legend items." + }, + "opacity": { + "valType": "number", + "role": "style", + "min": 0, + "max": 1, + "dflt": 1, + "editType": "style", + "description": "Sets the opacity of the trace." + }, + "name": { + "valType": "string", + "role": "info", + "editType": "style", + "description": "Sets the trace name. The trace name appear as the legend item and on hover." + }, + "uid": { + "valType": "string", + "role": "info", + "dflt": "", + "editType": "calc" + }, + "ids": { + "valType": "data_array", + "editType": "calc", + "description": "Assigns id labels to each datum. These ids for object constancy of data points during animation.", + "role": "data" + }, + "customdata": { + "valType": "data_array", + "editType": "calc", + "description": "Assigns extra data each datum. This may be useful when listening to hover, click and selection events. Note that, *scatter* traces also appends customdata items in the markers DOM elements", + "role": "data" + }, + "selectedpoints": { + "valType": "any", + "role": "info", + "editType": "calc", + "description": "Array containing integer indices of selected points. Has an effect only for traces that support selections. Note that an empty array means an empty selection where the `unselected` are turned on for all points, whereas, any other non-array values means no selection all where the `selected` and `unselected` styles have no effect." + }, + "hoverinfo": { + "valType": "flaglist", + "role": "info", + "flags": [ + "x", + "y", + "z", + "text", + "name" + ], + "extras": [ + "all", + "none", + "skip" + ], + "arrayOk": true, + "dflt": "all", + "editType": "none", + "description": "Determines which trace information appear on hover. If `none` or `skip` are set, no information is displayed upon hovering. But, if `none` is set, click and hover events are still fired." + }, + "hoverlabel": { + "bgcolor": { + "valType": "color", + "role": "style", + "arrayOk": true, + "editType": "none", + "description": "Sets the background color of the hover labels for this trace" + }, + "bordercolor": { + "valType": "color", + "role": "style", + "arrayOk": true, + "editType": "none", + "description": "Sets the border color of the hover labels for this trace." + }, + "font": { + "family": { + "valType": "string", + "role": "style", + "noBlank": true, + "strict": true, + "editType": "none", + "description": "HTML font family - the typeface that will be applied by the web browser. The web browser will only be able to apply a font if it is available on the system which it operates. Provide multiple font families, separated by commas, to indicate the preference in which to apply fonts if they aren't available on the system. The plotly service (at https://plot.ly or on-premise) generates images on a server, where only a select number of fonts are installed and supported. These include *Arial*, *Balto*, *Courier New*, *Droid Sans*,, *Droid Serif*, *Droid Sans Mono*, *Gravitas One*, *Old Standard TT*, *Open Sans*, *Overpass*, *PT Sans Narrow*, *Raleway*, *Times New Roman*.", + "arrayOk": true + }, + "size": { + "valType": "number", + "role": "style", + "min": 1, + "editType": "none", + "arrayOk": true + }, + "color": { + "valType": "color", + "role": "style", + "editType": "none", + "arrayOk": true + }, + "editType": "none", + "description": "Sets the font used in hover labels.", + "role": "object", + "familysrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for family .", + "editType": "none" + }, + "sizesrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for size .", + "editType": "none" + }, + "colorsrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for color .", + "editType": "none" + } + }, + "namelength": { + "valType": "integer", + "min": -1, + "arrayOk": true, + "role": "style", + "editType": "none", + "description": "Sets the length (in number of characters) of the trace name in the hover labels for this trace. -1 shows the whole name regardless of length. 0-3 shows the first 0-3 characters, and an integer >3 will show the whole name if it is less than that many characters, but if it is longer, will truncate to `namelength - 3` characters and add an ellipsis." + }, + "editType": "calc", + "role": "object", + "bgcolorsrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for bgcolor .", + "editType": "none" + }, + "bordercolorsrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for bordercolor .", + "editType": "none" + }, + "namelengthsrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for namelength .", + "editType": "none" + } + }, + "stream": { + "token": { + "valType": "string", + "noBlank": true, + "strict": true, + "role": "info", + "editType": "calc", + "description": "The stream id number links a data trace on a plot with a stream. See https://plot.ly/settings for more details." + }, + "maxpoints": { + "valType": "number", + "min": 0, + "max": 10000, + "dflt": 500, + "role": "info", + "editType": "calc", + "description": "Sets the maximum number of points to keep on the plots from an incoming stream. If `maxpoints` is set to *50*, only the newest 50 points will be displayed on the plot." + }, + "editType": "calc", + "role": "object" + }, + "x": { + "valType": "data_array", + "editType": "calc+clearAxisTypes", + "description": "Sets the x coordinates.", + "role": "data" + }, + "y": { + "valType": "data_array", + "editType": "calc+clearAxisTypes", + "description": "Sets the y coordinates.", + "role": "data" + }, + "z": { + "valType": "data_array", + "description": "Sets the z coordinates.", + "editType": "calc+clearAxisTypes", + "role": "data" + }, + "text": { + "valType": "string", + "role": "info", + "dflt": "", + "arrayOk": true, + "editType": "calc", + "description": "Sets text elements associated with each (x,y,z) triplet. If a single string, the same string appears over all the data points. If an array of string, the items are mapped in order to the this trace's (x,y,z) coordinates. If trace `hoverinfo` contains a *text* flag and *hovertext* is not set, these elements will be seen in the hover labels." + }, + "hovertext": { + "valType": "string", + "role": "info", + "dflt": "", + "arrayOk": true, + "editType": "calc", + "description": "Sets text elements associated with each (x,y,z) triplet. If a single string, the same string appears over all the data points. If an array of string, the items are mapped in order to the this trace's (x,y,z) coordinates. To be seen, trace `hoverinfo` must contain a *text* flag." + }, + "mode": { + "valType": "flaglist", + "flags": [ + "lines", + "markers", + "text" + ], + "extras": [ + "none" + ], + "role": "info", + "editType": "calc", + "description": "Determines the drawing mode for this scatter trace. If the provided `mode` includes *text* then the `text` elements appear at the coordinates. Otherwise, the `text` elements appear on hover. If there are less than 20 points, then the default is *lines+markers*. Otherwise, *lines*.", + "dflt": "lines+markers" + }, + "surfaceaxis": { + "valType": "enumerated", + "role": "info", + "values": [ + -1, + 0, + 1, + 2 + ], + "dflt": -1, + "description": "If *-1*, the scatter points are not fill with a surface If *0*, *1*, *2*, the scatter points are filled with a Delaunay surface about the x, y, z respectively.", + "editType": "calc" + }, + "surfacecolor": { + "valType": "color", + "role": "style", + "description": "Sets the surface fill color.", + "editType": "calc" + }, + "projection": { + "x": { + "show": { + "valType": "boolean", + "role": "info", + "dflt": false, + "description": "Sets whether or not projections are shown along the x axis.", + "editType": "calc" + }, + "opacity": { + "valType": "number", + "role": "style", + "min": 0, + "max": 1, + "dflt": 1, + "description": "Sets the projection color.", + "editType": "calc" + }, + "scale": { + "valType": "number", + "role": "style", + "min": 0, + "max": 10, + "dflt": 0.6666666666666666, + "description": "Sets the scale factor determining the size of the projection marker points.", + "editType": "calc" + }, + "editType": "calc", + "role": "object" + }, + "y": { + "show": { + "valType": "boolean", + "role": "info", + "dflt": false, + "description": "Sets whether or not projections are shown along the y axis.", + "editType": "calc" + }, + "opacity": { + "valType": "number", + "role": "style", + "min": 0, + "max": 1, + "dflt": 1, + "description": "Sets the projection color.", + "editType": "calc" + }, + "scale": { + "valType": "number", + "role": "style", + "min": 0, + "max": 10, + "dflt": 0.6666666666666666, + "description": "Sets the scale factor determining the size of the projection marker points.", + "editType": "calc" + }, + "editType": "calc", + "role": "object" + }, + "z": { + "show": { + "valType": "boolean", + "role": "info", + "dflt": false, + "description": "Sets whether or not projections are shown along the z axis.", + "editType": "calc" + }, + "opacity": { + "valType": "number", + "role": "style", + "min": 0, + "max": 1, + "dflt": 1, + "description": "Sets the projection color.", + "editType": "calc" + }, + "scale": { + "valType": "number", + "role": "style", + "min": 0, + "max": 10, + "dflt": 0.6666666666666666, + "description": "Sets the scale factor determining the size of the projection marker points.", + "editType": "calc" + }, + "editType": "calc", + "role": "object" + }, + "editType": "calc", + "role": "object" + }, + "connectgaps": { + "valType": "boolean", + "dflt": false, + "role": "info", + "editType": "calc", + "description": "Determines whether or not gaps (i.e. {nan} or missing values) in the provided data arrays are connected." + }, + "line": { + "width": { + "valType": "number", + "min": 0, + "dflt": 2, + "role": "style", + "editType": "calc", + "description": "Sets the line width (in px)." + }, + "dash": { + "valType": "enumerated", + "values": [ + "solid", + "dot", + "dash", + "longdash", + "dashdot", + "longdashdot" + ], + "dflt": "solid", + "role": "style", + "description": "Sets the dash style of the lines.", + "editType": "calc" + }, + "showscale": { + "valType": "boolean", + "role": "info", + "dflt": false, + "description": "Has an effect only if `line.color` is set to a numerical array. Determines whether or not a colorbar is displayed.", + "editType": "calc" + }, + "color": { + "valType": "color", + "arrayOk": true, + "role": "style", + "editType": "calc", + "description": "Sets the line color. It accepts either a specific color or an array of numbers that are mapped to the colorscale relative to the max and min values of the array or relative to `cmin` and `cmax` if set." + }, + "colorscale": { + "valType": "colorscale", + "role": "style", + "editType": "calc", + "impliedEdits": { + "autocolorscale": false + }, + "description": "Sets the colorscale and only has an effect if `line.color` is set to a numerical array. The colorscale must be an array containing arrays mapping a normalized value to an rgb, rgba, hex, hsl, hsv, or named color string. At minimum, a mapping for the lowest (0) and highest (1) values are required. For example, `[[0, 'rgb(0,0,255)', [1, 'rgb(255,0,0)']]`. To control the bounds of the colorscale in color space, use `line.cmin` and `line.cmax`. Alternatively, `colorscale` may be a palette name string of the following list: Greys, YlGnBu, Greens, YlOrRd, Bluered, RdBu, Reds, Blues, Picnic, Rainbow, Portland, Jet, Hot, Blackbody, Earth, Electric, Viridis" + }, + "cauto": { + "valType": "boolean", + "role": "info", + "dflt": true, + "editType": "calc", + "impliedEdits": {}, + "description": "Has an effect only if `line.color` is set to a numerical array and `cmin`, `cmax` are set by the user. In this case, it controls whether the range of colors in `colorscale` is mapped to the range of values in the `color` array (`cauto: true`), or the `cmin`/`cmax` values (`cauto: false`). Defaults to `false` when `cmin`, `cmax` are set by the user." + }, + "cmax": { + "valType": "number", + "role": "info", + "dflt": null, + "editType": "calc", + "impliedEdits": { + "cauto": false + }, + "description": "Has an effect only if `line.color` is set to a numerical array. Sets the upper bound of the color domain. Value should be associated to the `line.color` array index, and if set, `line.cmin` must be set as well." + }, + "cmin": { + "valType": "number", + "role": "info", + "dflt": null, + "editType": "calc", + "impliedEdits": { + "cauto": false + }, + "description": "Has an effect only if `line.color` is set to a numerical array. Sets the lower bound of the color domain. Value should be associated to the `line.color` array index, and if set, `line.cmax` must be set as well." + }, + "autocolorscale": { + "valType": "boolean", + "role": "style", + "dflt": true, + "editType": "calc", + "impliedEdits": {}, + "description": "Has an effect only if `line.color` is set to a numerical array. Determines whether the colorscale is a default palette (`autocolorscale: true`) or the palette determined by `line.colorscale`. In case `colorscale` is unspecified or `autocolorscale` is true, the default palette will be chosen according to whether numbers in the `color` array are all positive, all negative or mixed." + }, + "reversescale": { + "valType": "boolean", + "role": "style", + "dflt": false, + "editType": "calc", + "description": "Has an effect only if `line.color` is set to a numerical array. Reverses the color mapping if true (`cmin` will correspond to the last color in the array and `cmax` will correspond to the first color)." + }, + "editType": "calc", + "role": "object", + "colorsrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for color .", + "editType": "none" + } + }, + "marker": { + "symbol": { + "valType": "enumerated", + "values": [ + "circle", + "circle-open", + "square", + "square-open", + "diamond", + "diamond-open", + "cross", + "x" + ], + "role": "style", + "dflt": "circle", + "arrayOk": true, + "description": "Sets the marker symbol type.", + "editType": "calc" + }, + "size": { + "valType": "number", + "min": 0, + "dflt": 8, + "arrayOk": true, + "role": "style", + "editType": "calc", + "description": "Sets the marker size (in px)." + }, + "sizeref": { + "valType": "number", + "dflt": 1, + "role": "style", + "editType": "calc", + "description": "Has an effect only if `marker.size` is set to a numerical array. Sets the scale factor used to determine the rendered size of marker points. Use with `sizemin` and `sizemode`." + }, + "sizemin": { + "valType": "number", + "min": 0, + "dflt": 0, + "role": "style", + "editType": "calc", + "description": "Has an effect only if `marker.size` is set to a numerical array. Sets the minimum size (in px) of the rendered marker points." + }, + "sizemode": { + "valType": "enumerated", + "values": [ + "diameter", + "area" + ], + "dflt": "diameter", + "role": "info", + "editType": "calc", + "description": "Has an effect only if `marker.size` is set to a numerical array. Sets the rule for which the data in `size` is converted to pixels." + }, + "opacity": { + "valType": "number", + "min": 0, + "max": 1, + "arrayOk": false, + "role": "style", + "editType": "calc", + "description": "Sets the marker opacity. Note that the marker opacity for scatter3d traces must be a scalar value for performance reasons. To set a blending opacity value (i.e. which is not transparent), set *marker.color* to an rgba color and use its alpha channel." + }, + "showscale": { + "valType": "boolean", + "role": "info", + "dflt": false, + "editType": "calc", + "description": "Has an effect only if `marker.color` is set to a numerical array. Determines whether or not a colorbar is displayed." + }, + "colorbar": { + "thicknessmode": { + "valType": "enumerated", + "values": [ + "fraction", + "pixels" + ], + "role": "style", + "dflt": "pixels", + "description": "Determines whether this color bar's thickness (i.e. the measure in the constant color direction) is set in units of plot *fraction* or in *pixels*. Use `thickness` to set the value.", + "editType": "calc" + }, + "thickness": { + "valType": "number", + "role": "style", + "min": 0, + "dflt": 30, + "description": "Sets the thickness of the color bar This measure excludes the size of the padding, ticks and labels.", + "editType": "calc" + }, + "lenmode": { + "valType": "enumerated", + "values": [ + "fraction", + "pixels" + ], + "role": "info", + "dflt": "fraction", + "description": "Determines whether this color bar's length (i.e. the measure in the color variation direction) is set in units of plot *fraction* or in *pixels. Use `len` to set the value.", + "editType": "calc" + }, + "len": { + "valType": "number", + "min": 0, + "dflt": 1, + "role": "style", + "description": "Sets the length of the color bar This measure excludes the padding of both ends. That is, the color bar length is this length minus the padding on both ends.", + "editType": "calc" + }, + "x": { + "valType": "number", + "dflt": 1.02, + "min": -2, + "max": 3, + "role": "style", + "description": "Sets the x position of the color bar (in plot fraction).", + "editType": "calc" + }, + "xanchor": { + "valType": "enumerated", + "values": [ + "left", + "center", + "right" + ], + "dflt": "left", + "role": "style", + "description": "Sets this color bar's horizontal position anchor. This anchor binds the `x` position to the *left*, *center* or *right* of the color bar.", + "editType": "calc" + }, + "xpad": { + "valType": "number", + "role": "style", + "min": 0, + "dflt": 10, + "description": "Sets the amount of padding (in px) along the x direction.", + "editType": "calc" + }, + "y": { + "valType": "number", + "role": "style", + "dflt": 0.5, + "min": -2, + "max": 3, + "description": "Sets the y position of the color bar (in plot fraction).", + "editType": "calc" + }, + "yanchor": { + "valType": "enumerated", + "values": [ + "top", + "middle", + "bottom" + ], + "role": "style", + "dflt": "middle", + "description": "Sets this color bar's vertical position anchor This anchor binds the `y` position to the *top*, *middle* or *bottom* of the color bar.", + "editType": "calc" + }, + "ypad": { + "valType": "number", + "role": "style", + "min": 0, + "dflt": 10, + "description": "Sets the amount of padding (in px) along the y direction.", + "editType": "calc" + }, + "outlinecolor": { + "valType": "color", + "dflt": "#444", + "role": "style", + "editType": "calc", + "description": "Sets the axis line color." + }, + "outlinewidth": { + "valType": "number", + "min": 0, + "dflt": 1, + "role": "style", + "editType": "calc", + "description": "Sets the width (in px) of the axis line." + }, + "bordercolor": { + "valType": "color", + "dflt": "#444", + "role": "style", + "editType": "calc", + "description": "Sets the axis line color." + }, + "borderwidth": { + "valType": "number", + "role": "style", + "min": 0, + "dflt": 0, + "description": "Sets the width (in px) or the border enclosing this color bar.", + "editType": "calc" + }, + "bgcolor": { + "valType": "color", + "role": "style", + "dflt": "rgba(0,0,0,0)", + "description": "Sets the color of padded area.", + "editType": "calc" + }, + "tickmode": { + "valType": "enumerated", + "values": [ + "auto", + "linear", + "array" + ], + "role": "info", + "editType": "calc", + "impliedEdits": {}, + "description": "Sets the tick mode for this axis. If *auto*, the number of ticks is set via `nticks`. If *linear*, the placement of the ticks is determined by a starting position `tick0` and a tick step `dtick` (*linear* is the default value if `tick0` and `dtick` are provided). If *array*, the placement of the ticks is set via `tickvals` and the tick text is `ticktext`. (*array* is the default value if `tickvals` is provided)." + }, + "nticks": { + "valType": "integer", + "min": 0, + "dflt": 0, + "role": "style", + "editType": "calc", + "description": "Specifies the maximum number of ticks for the particular axis. The actual number of ticks will be chosen automatically to be less than or equal to `nticks`. Has an effect only if `tickmode` is set to *auto*." + }, + "tick0": { + "valType": "any", + "role": "style", + "editType": "calc", + "impliedEdits": { + "tickmode": "linear" + }, + "description": "Sets the placement of the first tick on this axis. Use with `dtick`. If the axis `type` is *log*, then you must take the log of your starting tick (e.g. to set the starting tick to 100, set the `tick0` to 2) except when `dtick`=*L* (see `dtick` for more info). If the axis `type` is *date*, it should be a date string, like date data. If the axis `type` is *category*, it should be a number, using the scale where each category is assigned a serial number from zero in the order it appears." + }, + "dtick": { + "valType": "any", + "role": "style", + "editType": "calc", + "impliedEdits": { + "tickmode": "linear" + }, + "description": "Sets the step in-between ticks on this axis. Use with `tick0`. Must be a positive number, or special strings available to *log* and *date* axes. If the axis `type` is *log*, then ticks are set every 10^(n*dtick) where n is the tick number. For example, to set a tick mark at 1, 10, 100, 1000, ... set dtick to 1. To set tick marks at 1, 100, 10000, ... set dtick to 2. To set tick marks at 1, 5, 25, 125, 625, 3125, ... set dtick to log_10(5), or 0.69897000433. *log* has several special values; *L*, where `f` is a positive number, gives ticks linearly spaced in value (but not position). For example `tick0` = 0.1, `dtick` = *L0.5* will put ticks at 0.1, 0.6, 1.1, 1.6 etc. To show powers of 10 plus small digits between, use *D1* (all digits) or *D2* (only 2 and 5). `tick0` is ignored for *D1* and *D2*. If the axis `type` is *date*, then you must convert the time to milliseconds. For example, to set the interval between ticks to one day, set `dtick` to 86400000.0. *date* also has special values *M* gives ticks spaced by a number of months. `n` must be a positive integer. To set ticks on the 15th of every third month, set `tick0` to *2000-01-15* and `dtick` to *M3*. To set ticks every 4 years, set `dtick` to *M48*" + }, + "tickvals": { + "valType": "data_array", + "editType": "calc", + "description": "Sets the values at which ticks on this axis appear. Only has an effect if `tickmode` is set to *array*. Used with `ticktext`.", + "role": "data" + }, + "ticktext": { + "valType": "data_array", + "editType": "calc", + "description": "Sets the text displayed at the ticks position via `tickvals`. Only has an effect if `tickmode` is set to *array*. Used with `tickvals`.", + "role": "data" + }, + "ticks": { + "valType": "enumerated", + "values": [ + "outside", + "inside", + "" + ], + "role": "style", + "editType": "calc", + "description": "Determines whether ticks are drawn or not. If **, this axis' ticks are not drawn. If *outside* (*inside*), this axis' are drawn outside (inside) the axis lines.", + "dflt": "" + }, + "ticklen": { + "valType": "number", + "min": 0, + "dflt": 5, + "role": "style", + "editType": "calc", + "description": "Sets the tick length (in px)." + }, + "tickwidth": { + "valType": "number", + "min": 0, + "dflt": 1, + "role": "style", + "editType": "calc", + "description": "Sets the tick width (in px)." + }, + "tickcolor": { + "valType": "color", + "dflt": "#444", + "role": "style", + "editType": "calc", + "description": "Sets the tick color." + }, + "showticklabels": { + "valType": "boolean", + "dflt": true, + "role": "style", + "editType": "calc", + "description": "Determines whether or not the tick labels are drawn." + }, + "tickfont": { + "family": { + "valType": "string", + "role": "style", + "noBlank": true, + "strict": true, + "description": "HTML font family - the typeface that will be applied by the web browser. The web browser will only be able to apply a font if it is available on the system which it operates. Provide multiple font families, separated by commas, to indicate the preference in which to apply fonts if they aren't available on the system. The plotly service (at https://plot.ly or on-premise) generates images on a server, where only a select number of fonts are installed and supported. These include *Arial*, *Balto*, *Courier New*, *Droid Sans*,, *Droid Serif*, *Droid Sans Mono*, *Gravitas One*, *Old Standard TT*, *Open Sans*, *Overpass*, *PT Sans Narrow*, *Raleway*, *Times New Roman*.", + "editType": "calc" + }, + "size": { + "valType": "number", + "role": "style", + "min": 1, + "editType": "calc" + }, + "color": { + "valType": "color", + "role": "style", + "editType": "calc" + }, + "description": "Sets the color bar's tick label font", + "editType": "calc", + "role": "object" + }, + "tickangle": { + "valType": "angle", + "dflt": "auto", + "role": "style", + "editType": "calc", + "description": "Sets the angle of the tick labels with respect to the horizontal. For example, a `tickangle` of -90 draws the tick labels vertically." + }, + "tickformat": { + "valType": "string", + "dflt": "", + "role": "style", + "editType": "calc", + "description": "Sets the tick label formatting rule using d3 formatting mini-languages which are very similar to those in Python. For numbers, see: https://github.com/d3/d3-format/blob/master/README.md#locale_format And for dates see: https://github.com/d3/d3-time-format/blob/master/README.md#locale_format We add one item to d3's date formatter: *%{n}f* for fractional seconds with n digits. For example, *2016-10-13 09:15:23.456* with tickformat *%H~%M~%S.%2f* would display *09~15~23.46*" + }, + "tickformatstops": { + "items": { + "tickformatstop": { + "dtickrange": { + "valType": "info_array", + "role": "info", + "items": [ + { + "valType": "any", + "editType": "calc" + }, + { + "valType": "any", + "editType": "calc" + } + ], + "editType": "calc", + "description": "range [*min*, *max*], where *min*, *max* - dtick values which describe some zoom level, it is possible to omit *min* or *max* value by passing *null*" + }, + "value": { + "valType": "string", + "dflt": "", + "role": "style", + "editType": "calc", + "description": "string - dtickformat for described zoom level, the same as *tickformat*" + }, + "editType": "calc", + "role": "object" + } + }, + "role": "object" + }, + "tickprefix": { + "valType": "string", + "dflt": "", + "role": "style", + "editType": "calc", + "description": "Sets a tick label prefix." + }, + "showtickprefix": { + "valType": "enumerated", + "values": [ + "all", + "first", + "last", + "none" + ], + "dflt": "all", + "role": "style", + "editType": "calc", + "description": "If *all*, all tick labels are displayed with a prefix. If *first*, only the first tick is displayed with a prefix. If *last*, only the last tick is displayed with a suffix. If *none*, tick prefixes are hidden." + }, + "ticksuffix": { + "valType": "string", + "dflt": "", + "role": "style", + "editType": "calc", + "description": "Sets a tick label suffix." + }, + "showticksuffix": { + "valType": "enumerated", + "values": [ + "all", + "first", + "last", + "none" + ], + "dflt": "all", + "role": "style", + "editType": "calc", + "description": "Same as `showtickprefix` but for tick suffixes." + }, + "separatethousands": { + "valType": "boolean", + "dflt": false, + "role": "style", + "editType": "calc", + "description": "If \"true\", even 4-digit integers are separated" + }, + "exponentformat": { + "valType": "enumerated", + "values": [ + "none", + "e", + "E", + "power", + "SI", + "B" + ], + "dflt": "B", + "role": "style", + "editType": "calc", + "description": "Determines a formatting rule for the tick exponents. For example, consider the number 1,000,000,000. If *none*, it appears as 1,000,000,000. If *e*, 1e+9. If *E*, 1E+9. If *power*, 1x10^9 (with 9 in a super script). If *SI*, 1G. If *B*, 1B." + }, + "showexponent": { + "valType": "enumerated", + "values": [ + "all", + "first", + "last", + "none" + ], + "dflt": "all", + "role": "style", + "editType": "calc", + "description": "If *all*, all exponents are shown besides their significands. If *first*, only the exponent of the first tick is shown. If *last*, only the exponent of the last tick is shown. If *none*, no exponents appear." + }, + "title": { + "valType": "string", + "role": "info", + "dflt": "Click to enter colorscale title", + "description": "Sets the title of the color bar.", + "editType": "calc" + }, + "titlefont": { + "family": { + "valType": "string", + "role": "style", + "noBlank": true, + "strict": true, + "description": "HTML font family - the typeface that will be applied by the web browser. The web browser will only be able to apply a font if it is available on the system which it operates. Provide multiple font families, separated by commas, to indicate the preference in which to apply fonts if they aren't available on the system. The plotly service (at https://plot.ly or on-premise) generates images on a server, where only a select number of fonts are installed and supported. These include *Arial*, *Balto*, *Courier New*, *Droid Sans*,, *Droid Serif*, *Droid Sans Mono*, *Gravitas One*, *Old Standard TT*, *Open Sans*, *Overpass*, *PT Sans Narrow*, *Raleway*, *Times New Roman*.", + "editType": "calc" + }, + "size": { + "valType": "number", + "role": "style", + "min": 1, + "editType": "calc" + }, + "color": { + "valType": "color", + "role": "style", + "editType": "calc" + }, + "description": "Sets this color bar's title font.", + "editType": "calc", + "role": "object" + }, + "titleside": { + "valType": "enumerated", + "values": [ + "right", + "top", + "bottom" + ], + "role": "style", + "dflt": "top", + "description": "Determines the location of the colorbar title with respect to the color bar.", + "editType": "calc" + }, + "editType": "calc", + "role": "object", + "tickvalssrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for tickvals .", + "editType": "none" + }, + "ticktextsrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for ticktext .", + "editType": "none" + } + }, + "line": { + "width": { + "valType": "number", + "min": 0, + "arrayOk": false, + "role": "style", + "editType": "calc", + "description": "Sets the width (in px) of the lines bounding the marker points." + }, + "color": { + "valType": "color", + "arrayOk": true, + "role": "style", + "editType": "calc", + "description": "Sets the marker.line color. It accepts either a specific color or an array of numbers that are mapped to the colorscale relative to the max and min values of the array or relative to `cmin` and `cmax` if set." + }, + "colorscale": { + "valType": "colorscale", + "role": "style", + "editType": "calc", + "impliedEdits": { + "autocolorscale": false + }, + "description": "Sets the colorscale and only has an effect if `marker.line.color` is set to a numerical array. The colorscale must be an array containing arrays mapping a normalized value to an rgb, rgba, hex, hsl, hsv, or named color string. At minimum, a mapping for the lowest (0) and highest (1) values are required. For example, `[[0, 'rgb(0,0,255)', [1, 'rgb(255,0,0)']]`. To control the bounds of the colorscale in color space, use `marker.line.cmin` and `marker.line.cmax`. Alternatively, `colorscale` may be a palette name string of the following list: Greys, YlGnBu, Greens, YlOrRd, Bluered, RdBu, Reds, Blues, Picnic, Rainbow, Portland, Jet, Hot, Blackbody, Earth, Electric, Viridis" + }, + "cauto": { + "valType": "boolean", + "role": "info", + "dflt": true, + "editType": "calc", + "impliedEdits": {}, + "description": "Has an effect only if `marker.line.color` is set to a numerical array and `cmin`, `cmax` are set by the user. In this case, it controls whether the range of colors in `colorscale` is mapped to the range of values in the `color` array (`cauto: true`), or the `cmin`/`cmax` values (`cauto: false`). Defaults to `false` when `cmin`, `cmax` are set by the user." + }, + "cmax": { + "valType": "number", + "role": "info", + "dflt": null, + "editType": "calc", + "impliedEdits": { + "cauto": false + }, + "description": "Has an effect only if `marker.line.color` is set to a numerical array. Sets the upper bound of the color domain. Value should be associated to the `marker.line.color` array index, and if set, `marker.line.cmin` must be set as well." + }, + "cmin": { + "valType": "number", + "role": "info", + "dflt": null, + "editType": "calc", + "impliedEdits": { + "cauto": false + }, + "description": "Has an effect only if `marker.line.color` is set to a numerical array. Sets the lower bound of the color domain. Value should be associated to the `marker.line.color` array index, and if set, `marker.line.cmax` must be set as well." + }, + "autocolorscale": { + "valType": "boolean", + "role": "style", + "dflt": true, + "editType": "calc", + "impliedEdits": {}, + "description": "Has an effect only if `marker.line.color` is set to a numerical array. Determines whether the colorscale is a default palette (`autocolorscale: true`) or the palette determined by `marker.line.colorscale`. In case `colorscale` is unspecified or `autocolorscale` is true, the default palette will be chosen according to whether numbers in the `color` array are all positive, all negative or mixed." + }, + "reversescale": { + "valType": "boolean", + "role": "style", + "dflt": false, + "editType": "calc", + "description": "Has an effect only if `marker.line.color` is set to a numerical array. Reverses the color mapping if true (`cmin` will correspond to the last color in the array and `cmax` will correspond to the first color)." + }, + "editType": "calc", + "role": "object", + "colorsrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for color .", + "editType": "none" + } + }, + "color": { + "valType": "color", + "arrayOk": true, + "role": "style", + "editType": "calc", + "description": "Sets the marker color. It accepts either a specific color or an array of numbers that are mapped to the colorscale relative to the max and min values of the array or relative to `cmin` and `cmax` if set." + }, + "colorscale": { + "valType": "colorscale", + "role": "style", + "editType": "calc", + "impliedEdits": { + "autocolorscale": false + }, + "description": "Sets the colorscale and only has an effect if `marker.color` is set to a numerical array. The colorscale must be an array containing arrays mapping a normalized value to an rgb, rgba, hex, hsl, hsv, or named color string. At minimum, a mapping for the lowest (0) and highest (1) values are required. For example, `[[0, 'rgb(0,0,255)', [1, 'rgb(255,0,0)']]`. To control the bounds of the colorscale in color space, use `marker.cmin` and `marker.cmax`. Alternatively, `colorscale` may be a palette name string of the following list: Greys, YlGnBu, Greens, YlOrRd, Bluered, RdBu, Reds, Blues, Picnic, Rainbow, Portland, Jet, Hot, Blackbody, Earth, Electric, Viridis" + }, + "cauto": { + "valType": "boolean", + "role": "info", + "dflt": true, + "editType": "calc", + "impliedEdits": {}, + "description": "Has an effect only if `marker.color` is set to a numerical array and `cmin`, `cmax` are set by the user. In this case, it controls whether the range of colors in `colorscale` is mapped to the range of values in the `color` array (`cauto: true`), or the `cmin`/`cmax` values (`cauto: false`). Defaults to `false` when `cmin`, `cmax` are set by the user." + }, + "cmax": { + "valType": "number", + "role": "info", + "dflt": null, + "editType": "calc", + "impliedEdits": { + "cauto": false + }, + "description": "Has an effect only if `marker.color` is set to a numerical array. Sets the upper bound of the color domain. Value should be associated to the `marker.color` array index, and if set, `marker.cmin` must be set as well." + }, + "cmin": { + "valType": "number", + "role": "info", + "dflt": null, + "editType": "calc", + "impliedEdits": { + "cauto": false + }, + "description": "Has an effect only if `marker.color` is set to a numerical array. Sets the lower bound of the color domain. Value should be associated to the `marker.color` array index, and if set, `marker.cmax` must be set as well." + }, + "autocolorscale": { + "valType": "boolean", + "role": "style", + "dflt": true, + "editType": "calc", + "impliedEdits": {}, + "description": "Has an effect only if `marker.color` is set to a numerical array. Determines whether the colorscale is a default palette (`autocolorscale: true`) or the palette determined by `marker.colorscale`. In case `colorscale` is unspecified or `autocolorscale` is true, the default palette will be chosen according to whether numbers in the `color` array are all positive, all negative or mixed." + }, + "reversescale": { + "valType": "boolean", + "role": "style", + "dflt": false, + "editType": "calc", + "description": "Has an effect only if `marker.color` is set to a numerical array. Reverses the color mapping if true (`cmin` will correspond to the last color in the array and `cmax` will correspond to the first color)." + }, + "editType": "calc", + "role": "object", + "symbolsrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for symbol .", + "editType": "none" + }, + "sizesrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for size .", + "editType": "none" + }, + "colorsrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for color .", + "editType": "none" + } + }, + "textposition": { + "valType": "enumerated", + "values": [ + "top left", + "top center", + "top right", + "middle left", + "middle center", + "middle right", + "bottom left", + "bottom center", + "bottom right" + ], + "dflt": "top center", + "arrayOk": true, + "role": "style", + "editType": "calc", + "description": "Sets the positions of the `text` elements with respects to the (x,y) coordinates." + }, + "textfont": { + "family": { + "valType": "string", + "role": "style", + "noBlank": true, + "strict": true, + "editType": "calc", + "description": "HTML font family - the typeface that will be applied by the web browser. The web browser will only be able to apply a font if it is available on the system which it operates. Provide multiple font families, separated by commas, to indicate the preference in which to apply fonts if they aren't available on the system. The plotly service (at https://plot.ly or on-premise) generates images on a server, where only a select number of fonts are installed and supported. These include *Arial*, *Balto*, *Courier New*, *Droid Sans*,, *Droid Serif*, *Droid Sans Mono*, *Gravitas One*, *Old Standard TT*, *Open Sans*, *Overpass*, *PT Sans Narrow*, *Raleway*, *Times New Roman*.", + "arrayOk": true + }, + "size": { + "valType": "number", + "role": "style", + "min": 1, + "editType": "calc", + "arrayOk": true + }, + "color": { + "valType": "color", + "role": "style", + "editType": "calc", + "arrayOk": true + }, + "editType": "calc", + "description": "Sets the text font.", + "role": "object", + "familysrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for family .", + "editType": "none" + }, + "sizesrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for size .", + "editType": "none" + }, + "colorsrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for color .", + "editType": "none" + } + }, + "error_x": { + "visible": { + "valType": "boolean", + "role": "info", + "editType": "calc", + "description": "Determines whether or not this set of error bars is visible." + }, + "type": { + "valType": "enumerated", + "values": [ + "percent", + "constant", + "sqrt", + "data" + ], + "role": "info", + "editType": "calc", + "description": "Determines the rule used to generate the error bars. If *constant`, the bar lengths are of a constant value. Set this constant in `value`. If *percent*, the bar lengths correspond to a percentage of underlying data. Set this percentage in `value`. If *sqrt*, the bar lengths correspond to the sqaure of the underlying data. If *array*, the bar lengths are set with data set `array`." + }, + "symmetric": { + "valType": "boolean", + "role": "info", + "editType": "calc", + "description": "Determines whether or not the error bars have the same length in both direction (top/bottom for vertical bars, left/right for horizontal bars." + }, + "array": { + "valType": "data_array", + "editType": "calc", + "description": "Sets the data corresponding the length of each error bar. Values are plotted relative to the underlying data.", + "role": "data" + }, + "arrayminus": { + "valType": "data_array", + "editType": "calc", + "description": "Sets the data corresponding the length of each error bar in the bottom (left) direction for vertical (horizontal) bars Values are plotted relative to the underlying data.", + "role": "data" + }, + "value": { + "valType": "number", + "min": 0, + "dflt": 10, + "role": "info", + "editType": "calc", + "description": "Sets the value of either the percentage (if `type` is set to *percent*) or the constant (if `type` is set to *constant*) corresponding to the lengths of the error bars." + }, + "valueminus": { + "valType": "number", + "min": 0, + "dflt": 10, + "role": "info", + "editType": "calc", + "description": "Sets the value of either the percentage (if `type` is set to *percent*) or the constant (if `type` is set to *constant*) corresponding to the lengths of the error bars in the bottom (left) direction for vertical (horizontal) bars" + }, + "traceref": { + "valType": "integer", + "min": 0, + "dflt": 0, + "role": "info", + "editType": "calc" + }, + "tracerefminus": { + "valType": "integer", + "min": 0, + "dflt": 0, + "role": "info", + "editType": "calc" + }, + "copy_ystyle": { + "valType": "boolean", + "role": "style", + "editType": "calc" + }, + "copy_zstyle": { + "valType": "boolean", + "role": "style", + "editType": "calc" + }, + "color": { + "valType": "color", + "role": "style", + "editType": "calc", + "description": "Sets the stoke color of the error bars." + }, + "thickness": { + "valType": "number", + "min": 0, + "dflt": 2, + "role": "style", + "editType": "calc", + "description": "Sets the thickness (in px) of the error bars." + }, + "width": { + "valType": "number", + "min": 0, + "role": "style", + "editType": "calc", + "description": "Sets the width (in px) of the cross-bar at both ends of the error bars." + }, + "editType": "calc", + "_deprecated": { + "opacity": { + "valType": "number", + "role": "style", + "editType": "calc", + "description": "Obsolete. Use the alpha channel in error bar `color` to set the opacity." + } + }, + "role": "object", + "arraysrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for array .", + "editType": "none" + }, + "arrayminussrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for arrayminus .", + "editType": "none" + } + }, + "error_y": { + "visible": { + "valType": "boolean", + "role": "info", + "editType": "calc", + "description": "Determines whether or not this set of error bars is visible." + }, + "type": { + "valType": "enumerated", + "values": [ + "percent", + "constant", + "sqrt", + "data" + ], + "role": "info", + "editType": "calc", + "description": "Determines the rule used to generate the error bars. If *constant`, the bar lengths are of a constant value. Set this constant in `value`. If *percent*, the bar lengths correspond to a percentage of underlying data. Set this percentage in `value`. If *sqrt*, the bar lengths correspond to the sqaure of the underlying data. If *array*, the bar lengths are set with data set `array`." + }, + "symmetric": { + "valType": "boolean", + "role": "info", + "editType": "calc", + "description": "Determines whether or not the error bars have the same length in both direction (top/bottom for vertical bars, left/right for horizontal bars." + }, + "array": { + "valType": "data_array", + "editType": "calc", + "description": "Sets the data corresponding the length of each error bar. Values are plotted relative to the underlying data.", + "role": "data" + }, + "arrayminus": { + "valType": "data_array", + "editType": "calc", + "description": "Sets the data corresponding the length of each error bar in the bottom (left) direction for vertical (horizontal) bars Values are plotted relative to the underlying data.", + "role": "data" + }, + "value": { + "valType": "number", + "min": 0, + "dflt": 10, + "role": "info", + "editType": "calc", + "description": "Sets the value of either the percentage (if `type` is set to *percent*) or the constant (if `type` is set to *constant*) corresponding to the lengths of the error bars." + }, + "valueminus": { + "valType": "number", + "min": 0, + "dflt": 10, + "role": "info", + "editType": "calc", + "description": "Sets the value of either the percentage (if `type` is set to *percent*) or the constant (if `type` is set to *constant*) corresponding to the lengths of the error bars in the bottom (left) direction for vertical (horizontal) bars" + }, + "traceref": { + "valType": "integer", + "min": 0, + "dflt": 0, + "role": "info", + "editType": "calc" + }, + "tracerefminus": { + "valType": "integer", + "min": 0, + "dflt": 0, + "role": "info", + "editType": "calc" + }, + "copy_ystyle": { + "valType": "boolean", + "role": "style", + "editType": "calc" + }, + "copy_zstyle": { + "valType": "boolean", + "role": "style", + "editType": "calc" + }, + "color": { + "valType": "color", + "role": "style", + "editType": "calc", + "description": "Sets the stoke color of the error bars." + }, + "thickness": { + "valType": "number", + "min": 0, + "dflt": 2, + "role": "style", + "editType": "calc", + "description": "Sets the thickness (in px) of the error bars." + }, + "width": { + "valType": "number", + "min": 0, + "role": "style", + "editType": "calc", + "description": "Sets the width (in px) of the cross-bar at both ends of the error bars." + }, + "editType": "calc", + "_deprecated": { + "opacity": { + "valType": "number", + "role": "style", + "editType": "calc", + "description": "Obsolete. Use the alpha channel in error bar `color` to set the opacity." + } + }, + "role": "object", + "arraysrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for array .", + "editType": "none" + }, + "arrayminussrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for arrayminus .", + "editType": "none" + } + }, + "error_z": { + "visible": { + "valType": "boolean", + "role": "info", + "editType": "calc", + "description": "Determines whether or not this set of error bars is visible." + }, + "type": { + "valType": "enumerated", + "values": [ + "percent", + "constant", + "sqrt", + "data" + ], + "role": "info", + "editType": "calc", + "description": "Determines the rule used to generate the error bars. If *constant`, the bar lengths are of a constant value. Set this constant in `value`. If *percent*, the bar lengths correspond to a percentage of underlying data. Set this percentage in `value`. If *sqrt*, the bar lengths correspond to the sqaure of the underlying data. If *array*, the bar lengths are set with data set `array`." + }, + "symmetric": { + "valType": "boolean", + "role": "info", + "editType": "calc", + "description": "Determines whether or not the error bars have the same length in both direction (top/bottom for vertical bars, left/right for horizontal bars." + }, + "array": { + "valType": "data_array", + "editType": "calc", + "description": "Sets the data corresponding the length of each error bar. Values are plotted relative to the underlying data.", + "role": "data" + }, + "arrayminus": { + "valType": "data_array", + "editType": "calc", + "description": "Sets the data corresponding the length of each error bar in the bottom (left) direction for vertical (horizontal) bars Values are plotted relative to the underlying data.", + "role": "data" + }, + "value": { + "valType": "number", + "min": 0, + "dflt": 10, + "role": "info", + "editType": "calc", + "description": "Sets the value of either the percentage (if `type` is set to *percent*) or the constant (if `type` is set to *constant*) corresponding to the lengths of the error bars." + }, + "valueminus": { + "valType": "number", + "min": 0, + "dflt": 10, + "role": "info", + "editType": "calc", + "description": "Sets the value of either the percentage (if `type` is set to *percent*) or the constant (if `type` is set to *constant*) corresponding to the lengths of the error bars in the bottom (left) direction for vertical (horizontal) bars" + }, + "traceref": { + "valType": "integer", + "min": 0, + "dflt": 0, + "role": "info", + "editType": "calc" + }, + "tracerefminus": { + "valType": "integer", + "min": 0, + "dflt": 0, + "role": "info", + "editType": "calc" + }, + "copy_ystyle": { + "valType": "boolean", + "role": "style", + "editType": "calc" + }, + "copy_zstyle": { + "valType": "boolean", + "role": "style", + "editType": "calc" + }, + "color": { + "valType": "color", + "role": "style", + "editType": "calc", + "description": "Sets the stoke color of the error bars." + }, + "thickness": { + "valType": "number", + "min": 0, + "dflt": 2, + "role": "style", + "editType": "calc", + "description": "Sets the thickness (in px) of the error bars." + }, + "width": { + "valType": "number", + "min": 0, + "role": "style", + "editType": "calc", + "description": "Sets the width (in px) of the cross-bar at both ends of the error bars." + }, + "editType": "calc", + "_deprecated": { + "opacity": { + "valType": "number", + "role": "style", + "editType": "calc", + "description": "Obsolete. Use the alpha channel in error bar `color` to set the opacity." + } + }, + "role": "object", + "arraysrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for array .", + "editType": "none" + }, + "arrayminussrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for arrayminus .", + "editType": "none" + } + }, + "xcalendar": { + "valType": "enumerated", + "values": [ + "gregorian", + "chinese", + "coptic", + "discworld", + "ethiopian", + "hebrew", + "islamic", + "julian", + "mayan", + "nanakshahi", + "nepali", + "persian", + "jalali", + "taiwan", + "thai", + "ummalqura" + ], + "role": "info", + "editType": "calc", + "dflt": "gregorian", + "description": "Sets the calendar system to use with `x` date data." + }, + "ycalendar": { + "valType": "enumerated", + "values": [ + "gregorian", + "chinese", + "coptic", + "discworld", + "ethiopian", + "hebrew", + "islamic", + "julian", + "mayan", + "nanakshahi", + "nepali", + "persian", + "jalali", + "taiwan", + "thai", + "ummalqura" + ], + "role": "info", + "editType": "calc", + "dflt": "gregorian", + "description": "Sets the calendar system to use with `y` date data." + }, + "zcalendar": { + "valType": "enumerated", + "values": [ + "gregorian", + "chinese", + "coptic", + "discworld", + "ethiopian", + "hebrew", + "islamic", + "julian", + "mayan", + "nanakshahi", + "nepali", + "persian", + "jalali", + "taiwan", + "thai", + "ummalqura" + ], + "role": "info", + "editType": "calc", + "dflt": "gregorian", + "description": "Sets the calendar system to use with `z` date data." + }, + "scene": { + "valType": "subplotid", + "role": "info", + "dflt": "scene", + "editType": "calc+clearAxisTypes", + "description": "Sets a reference between this trace's 3D coordinate system and a 3D scene. If *scene* (the default value), the (x,y,z) coordinates refer to `layout.scene`. If *scene2*, the (x,y,z) coordinates refer to `layout.scene2`, and so on." + }, + "idssrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for ids .", + "editType": "none" + }, + "customdatasrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for customdata .", + "editType": "none" + }, + "hoverinfosrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for hoverinfo .", + "editType": "none" + }, + "xsrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for x .", + "editType": "none" + }, + "ysrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for y .", + "editType": "none" + }, + "zsrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for z .", + "editType": "none" + }, + "textsrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for text .", + "editType": "none" + }, + "hovertextsrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for hovertext .", + "editType": "none" + }, + "textpositionsrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for textposition .", + "editType": "none" + } + } + }, + "surface": { + "meta": { + "description": "The data the describes the coordinates of the surface is set in `z`. Data in `z` should be a {2D array}. Coordinates in `x` and `y` can either be 1D {arrays} or {2D arrays} (e.g. to graph parametric surfaces). If not provided in `x` and `y`, the x and y coordinates are assumed to be linear starting at 0 with a unit step. The color scale corresponds to the `z` values by default. For custom color scales, use `surfacecolor` which should be a {2D array}, where its bounds can be controlled using `cmin` and `cmax`." + }, + "attributes": { + "type": "surface", + "visible": { + "valType": "enumerated", + "values": [ + true, + false, + "legendonly" + ], + "role": "info", + "dflt": true, + "editType": "calc", + "description": "Determines whether or not this trace is visible. If *legendonly*, the trace is not drawn, but can appear as a legend item (provided that the legend itself is visible)." + }, + "showlegend": { + "valType": "boolean", + "role": "info", + "dflt": true, + "editType": "style", + "description": "Determines whether or not an item corresponding to this trace is shown in the legend." + }, + "legendgroup": { + "valType": "string", + "role": "info", + "dflt": "", + "editType": "style", + "description": "Sets the legend group for this trace. Traces part of the same legend group hide/show at the same time when toggling legend items." + }, + "opacity": { + "valType": "number", + "role": "style", + "min": 0, + "max": 1, + "dflt": 1, + "editType": "calc", + "description": "Sets the opacity of the surface." + }, + "name": { + "valType": "string", + "role": "info", + "editType": "style", + "description": "Sets the trace name. The trace name appear as the legend item and on hover." + }, + "uid": { + "valType": "string", + "role": "info", + "dflt": "", + "editType": "calc" + }, + "ids": { + "valType": "data_array", + "editType": "calc", + "description": "Assigns id labels to each datum. These ids for object constancy of data points during animation.", + "role": "data" + }, + "customdata": { + "valType": "data_array", + "editType": "calc", + "description": "Assigns extra data each datum. This may be useful when listening to hover, click and selection events. Note that, *scatter* traces also appends customdata items in the markers DOM elements", + "role": "data" + }, + "selectedpoints": { + "valType": "any", + "role": "info", + "editType": "calc", + "description": "Array containing integer indices of selected points. Has an effect only for traces that support selections. Note that an empty array means an empty selection where the `unselected` are turned on for all points, whereas, any other non-array values means no selection all where the `selected` and `unselected` styles have no effect." + }, + "hoverinfo": { + "valType": "flaglist", + "role": "info", + "flags": [ + "x", + "y", + "z", + "text", + "name" + ], + "extras": [ + "all", + "none", + "skip" + ], + "arrayOk": true, + "dflt": "all", + "editType": "none", + "description": "Determines which trace information appear on hover. If `none` or `skip` are set, no information is displayed upon hovering. But, if `none` is set, click and hover events are still fired." + }, + "hoverlabel": { + "bgcolor": { + "valType": "color", + "role": "style", + "arrayOk": true, + "editType": "none", + "description": "Sets the background color of the hover labels for this trace" + }, + "bordercolor": { + "valType": "color", + "role": "style", + "arrayOk": true, + "editType": "none", + "description": "Sets the border color of the hover labels for this trace." + }, + "font": { + "family": { + "valType": "string", + "role": "style", + "noBlank": true, + "strict": true, + "editType": "none", + "description": "HTML font family - the typeface that will be applied by the web browser. The web browser will only be able to apply a font if it is available on the system which it operates. Provide multiple font families, separated by commas, to indicate the preference in which to apply fonts if they aren't available on the system. The plotly service (at https://plot.ly or on-premise) generates images on a server, where only a select number of fonts are installed and supported. These include *Arial*, *Balto*, *Courier New*, *Droid Sans*,, *Droid Serif*, *Droid Sans Mono*, *Gravitas One*, *Old Standard TT*, *Open Sans*, *Overpass*, *PT Sans Narrow*, *Raleway*, *Times New Roman*.", + "arrayOk": true + }, + "size": { + "valType": "number", + "role": "style", + "min": 1, + "editType": "none", + "arrayOk": true + }, + "color": { + "valType": "color", + "role": "style", + "editType": "none", + "arrayOk": true + }, + "editType": "none", + "description": "Sets the font used in hover labels.", + "role": "object", + "familysrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for family .", + "editType": "none" + }, + "sizesrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for size .", + "editType": "none" + }, + "colorsrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for color .", + "editType": "none" + } + }, + "namelength": { + "valType": "integer", + "min": -1, + "arrayOk": true, + "role": "style", + "editType": "none", + "description": "Sets the length (in number of characters) of the trace name in the hover labels for this trace. -1 shows the whole name regardless of length. 0-3 shows the first 0-3 characters, and an integer >3 will show the whole name if it is less than that many characters, but if it is longer, will truncate to `namelength - 3` characters and add an ellipsis." + }, + "editType": "calc", + "role": "object", + "bgcolorsrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for bgcolor .", + "editType": "none" + }, + "bordercolorsrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for bordercolor .", + "editType": "none" + }, + "namelengthsrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for namelength .", + "editType": "none" + } + }, + "stream": { + "token": { + "valType": "string", + "noBlank": true, + "strict": true, + "role": "info", + "editType": "calc", + "description": "The stream id number links a data trace on a plot with a stream. See https://plot.ly/settings for more details." + }, + "maxpoints": { + "valType": "number", + "min": 0, + "max": 10000, + "dflt": 500, + "role": "info", + "editType": "calc", + "description": "Sets the maximum number of points to keep on the plots from an incoming stream. If `maxpoints` is set to *50*, only the newest 50 points will be displayed on the plot." + }, + "editType": "calc", + "role": "object" + }, + "z": { + "valType": "data_array", + "description": "Sets the z coordinates.", + "editType": "calc+clearAxisTypes", + "role": "data" + }, + "x": { + "valType": "data_array", + "description": "Sets the x coordinates.", + "editType": "calc+clearAxisTypes", + "role": "data" + }, + "y": { + "valType": "data_array", + "description": "Sets the y coordinates.", + "editType": "calc+clearAxisTypes", + "role": "data" + }, + "text": { + "valType": "data_array", + "description": "Sets the text elements associated with each z value.", + "editType": "calc", + "role": "data" + }, + "surfacecolor": { + "valType": "data_array", + "description": "Sets the surface color values, used for setting a color scale independent of `z`.", + "editType": "calc", + "role": "data" + }, + "cauto": { + "valType": "boolean", + "role": "info", + "dflt": true, + "editType": "calc", + "impliedEdits": {}, + "description": "Determines the whether or not the color domain is computed with respect to the input data." + }, + "cmin": { + "valType": "number", + "role": "info", + "dflt": null, + "editType": "calc", + "impliedEdits": { + "zauto": false + }, + "description": "Sets the lower bound of color domain." + }, + "cmax": { + "valType": "number", + "role": "info", + "dflt": null, + "editType": "calc", + "impliedEdits": { + "zauto": false + }, + "description": "Sets the upper bound of color domain." + }, + "colorscale": { + "valType": "colorscale", + "role": "style", + "editType": "calc", + "impliedEdits": { + "autocolorscale": false + }, + "description": "Sets the colorscale. The colorscale must be an array containing arrays mapping a normalized value to an rgb, rgba, hex, hsl, hsv, or named color string. At minimum, a mapping for the lowest (0) and highest (1) values are required. For example, `[[0, 'rgb(0,0,255)', [1, 'rgb(255,0,0)']]`. To control the bounds of the colorscale in z space, use zmin and zmax" + }, + "autocolorscale": { + "valType": "boolean", + "role": "style", + "dflt": false, + "editType": "calc", + "impliedEdits": {}, + "description": "Determines whether or not the colorscale is picked using the sign of the input z values." + }, + "reversescale": { + "valType": "boolean", + "role": "style", + "dflt": false, + "editType": "calc", + "description": "Reverses the colorscale." + }, + "showscale": { + "valType": "boolean", + "role": "info", + "dflt": true, + "editType": "calc", + "description": "Determines whether or not a colorbar is displayed for this trace." + }, + "colorbar": { + "thicknessmode": { + "valType": "enumerated", + "values": [ + "fraction", + "pixels" + ], + "role": "style", + "dflt": "pixels", + "description": "Determines whether this color bar's thickness (i.e. the measure in the constant color direction) is set in units of plot *fraction* or in *pixels*. Use `thickness` to set the value.", + "editType": "calc" + }, + "thickness": { + "valType": "number", + "role": "style", + "min": 0, + "dflt": 30, + "description": "Sets the thickness of the color bar This measure excludes the size of the padding, ticks and labels.", + "editType": "calc" + }, + "lenmode": { + "valType": "enumerated", + "values": [ + "fraction", + "pixels" + ], + "role": "info", + "dflt": "fraction", + "description": "Determines whether this color bar's length (i.e. the measure in the color variation direction) is set in units of plot *fraction* or in *pixels. Use `len` to set the value.", + "editType": "calc" + }, + "len": { + "valType": "number", + "min": 0, + "dflt": 1, + "role": "style", + "description": "Sets the length of the color bar This measure excludes the padding of both ends. That is, the color bar length is this length minus the padding on both ends.", + "editType": "calc" + }, + "x": { + "valType": "number", + "dflt": 1.02, + "min": -2, + "max": 3, + "role": "style", + "description": "Sets the x position of the color bar (in plot fraction).", + "editType": "calc" + }, + "xanchor": { + "valType": "enumerated", + "values": [ + "left", + "center", + "right" + ], + "dflt": "left", + "role": "style", + "description": "Sets this color bar's horizontal position anchor. This anchor binds the `x` position to the *left*, *center* or *right* of the color bar.", + "editType": "calc" + }, + "xpad": { + "valType": "number", + "role": "style", + "min": 0, + "dflt": 10, + "description": "Sets the amount of padding (in px) along the x direction.", + "editType": "calc" + }, + "y": { + "valType": "number", + "role": "style", + "dflt": 0.5, + "min": -2, + "max": 3, + "description": "Sets the y position of the color bar (in plot fraction).", + "editType": "calc" + }, + "yanchor": { + "valType": "enumerated", + "values": [ + "top", + "middle", + "bottom" + ], + "role": "style", + "dflt": "middle", + "description": "Sets this color bar's vertical position anchor This anchor binds the `y` position to the *top*, *middle* or *bottom* of the color bar.", + "editType": "calc" + }, + "ypad": { + "valType": "number", + "role": "style", + "min": 0, + "dflt": 10, + "description": "Sets the amount of padding (in px) along the y direction.", + "editType": "calc" + }, + "outlinecolor": { + "valType": "color", + "dflt": "#444", + "role": "style", + "editType": "calc", + "description": "Sets the axis line color." + }, + "outlinewidth": { + "valType": "number", + "min": 0, + "dflt": 1, + "role": "style", + "editType": "calc", + "description": "Sets the width (in px) of the axis line." + }, + "bordercolor": { + "valType": "color", + "dflt": "#444", + "role": "style", + "editType": "calc", + "description": "Sets the axis line color." + }, + "borderwidth": { + "valType": "number", + "role": "style", + "min": 0, + "dflt": 0, + "description": "Sets the width (in px) or the border enclosing this color bar.", + "editType": "calc" + }, + "bgcolor": { + "valType": "color", + "role": "style", + "dflt": "rgba(0,0,0,0)", + "description": "Sets the color of padded area.", + "editType": "calc" + }, + "tickmode": { + "valType": "enumerated", + "values": [ + "auto", + "linear", + "array" + ], + "role": "info", + "editType": "calc", + "impliedEdits": {}, + "description": "Sets the tick mode for this axis. If *auto*, the number of ticks is set via `nticks`. If *linear*, the placement of the ticks is determined by a starting position `tick0` and a tick step `dtick` (*linear* is the default value if `tick0` and `dtick` are provided). If *array*, the placement of the ticks is set via `tickvals` and the tick text is `ticktext`. (*array* is the default value if `tickvals` is provided)." + }, + "nticks": { + "valType": "integer", + "min": 0, + "dflt": 0, + "role": "style", + "editType": "calc", + "description": "Specifies the maximum number of ticks for the particular axis. The actual number of ticks will be chosen automatically to be less than or equal to `nticks`. Has an effect only if `tickmode` is set to *auto*." + }, + "tick0": { + "valType": "any", + "role": "style", + "editType": "calc", + "impliedEdits": { + "tickmode": "linear" + }, + "description": "Sets the placement of the first tick on this axis. Use with `dtick`. If the axis `type` is *log*, then you must take the log of your starting tick (e.g. to set the starting tick to 100, set the `tick0` to 2) except when `dtick`=*L* (see `dtick` for more info). If the axis `type` is *date*, it should be a date string, like date data. If the axis `type` is *category*, it should be a number, using the scale where each category is assigned a serial number from zero in the order it appears." + }, + "dtick": { + "valType": "any", + "role": "style", + "editType": "calc", + "impliedEdits": { + "tickmode": "linear" + }, + "description": "Sets the step in-between ticks on this axis. Use with `tick0`. Must be a positive number, or special strings available to *log* and *date* axes. If the axis `type` is *log*, then ticks are set every 10^(n*dtick) where n is the tick number. For example, to set a tick mark at 1, 10, 100, 1000, ... set dtick to 1. To set tick marks at 1, 100, 10000, ... set dtick to 2. To set tick marks at 1, 5, 25, 125, 625, 3125, ... set dtick to log_10(5), or 0.69897000433. *log* has several special values; *L*, where `f` is a positive number, gives ticks linearly spaced in value (but not position). For example `tick0` = 0.1, `dtick` = *L0.5* will put ticks at 0.1, 0.6, 1.1, 1.6 etc. To show powers of 10 plus small digits between, use *D1* (all digits) or *D2* (only 2 and 5). `tick0` is ignored for *D1* and *D2*. If the axis `type` is *date*, then you must convert the time to milliseconds. For example, to set the interval between ticks to one day, set `dtick` to 86400000.0. *date* also has special values *M* gives ticks spaced by a number of months. `n` must be a positive integer. To set ticks on the 15th of every third month, set `tick0` to *2000-01-15* and `dtick` to *M3*. To set ticks every 4 years, set `dtick` to *M48*" + }, + "tickvals": { + "valType": "data_array", + "editType": "calc", + "description": "Sets the values at which ticks on this axis appear. Only has an effect if `tickmode` is set to *array*. Used with `ticktext`.", + "role": "data" + }, + "ticktext": { + "valType": "data_array", + "editType": "calc", + "description": "Sets the text displayed at the ticks position via `tickvals`. Only has an effect if `tickmode` is set to *array*. Used with `tickvals`.", + "role": "data" + }, + "ticks": { + "valType": "enumerated", + "values": [ + "outside", + "inside", + "" + ], + "role": "style", + "editType": "calc", + "description": "Determines whether ticks are drawn or not. If **, this axis' ticks are not drawn. If *outside* (*inside*), this axis' are drawn outside (inside) the axis lines.", + "dflt": "" + }, + "ticklen": { + "valType": "number", + "min": 0, + "dflt": 5, + "role": "style", + "editType": "calc", + "description": "Sets the tick length (in px)." + }, + "tickwidth": { + "valType": "number", + "min": 0, + "dflt": 1, + "role": "style", + "editType": "calc", + "description": "Sets the tick width (in px)." + }, + "tickcolor": { + "valType": "color", + "dflt": "#444", + "role": "style", + "editType": "calc", + "description": "Sets the tick color." + }, + "showticklabels": { + "valType": "boolean", + "dflt": true, + "role": "style", + "editType": "calc", + "description": "Determines whether or not the tick labels are drawn." + }, + "tickfont": { + "family": { + "valType": "string", + "role": "style", + "noBlank": true, + "strict": true, + "description": "HTML font family - the typeface that will be applied by the web browser. The web browser will only be able to apply a font if it is available on the system which it operates. Provide multiple font families, separated by commas, to indicate the preference in which to apply fonts if they aren't available on the system. The plotly service (at https://plot.ly or on-premise) generates images on a server, where only a select number of fonts are installed and supported. These include *Arial*, *Balto*, *Courier New*, *Droid Sans*,, *Droid Serif*, *Droid Sans Mono*, *Gravitas One*, *Old Standard TT*, *Open Sans*, *Overpass*, *PT Sans Narrow*, *Raleway*, *Times New Roman*.", + "editType": "calc" + }, + "size": { + "valType": "number", + "role": "style", + "min": 1, + "editType": "calc" + }, + "color": { + "valType": "color", + "role": "style", + "editType": "calc" + }, + "description": "Sets the color bar's tick label font", + "editType": "calc", + "role": "object" + }, + "tickangle": { + "valType": "angle", + "dflt": "auto", + "role": "style", + "editType": "calc", + "description": "Sets the angle of the tick labels with respect to the horizontal. For example, a `tickangle` of -90 draws the tick labels vertically." + }, + "tickformat": { + "valType": "string", + "dflt": "", + "role": "style", + "editType": "calc", + "description": "Sets the tick label formatting rule using d3 formatting mini-languages which are very similar to those in Python. For numbers, see: https://github.com/d3/d3-format/blob/master/README.md#locale_format And for dates see: https://github.com/d3/d3-time-format/blob/master/README.md#locale_format We add one item to d3's date formatter: *%{n}f* for fractional seconds with n digits. For example, *2016-10-13 09:15:23.456* with tickformat *%H~%M~%S.%2f* would display *09~15~23.46*" + }, + "tickformatstops": { + "items": { + "tickformatstop": { + "dtickrange": { + "valType": "info_array", + "role": "info", + "items": [ + { + "valType": "any", + "editType": "calc" + }, + { + "valType": "any", + "editType": "calc" + } + ], + "editType": "calc", + "description": "range [*min*, *max*], where *min*, *max* - dtick values which describe some zoom level, it is possible to omit *min* or *max* value by passing *null*" + }, + "value": { + "valType": "string", + "dflt": "", + "role": "style", + "editType": "calc", + "description": "string - dtickformat for described zoom level, the same as *tickformat*" + }, + "editType": "calc", + "role": "object" + } + }, + "role": "object" + }, + "tickprefix": { + "valType": "string", + "dflt": "", + "role": "style", + "editType": "calc", + "description": "Sets a tick label prefix." + }, + "showtickprefix": { + "valType": "enumerated", + "values": [ + "all", + "first", + "last", + "none" + ], + "dflt": "all", + "role": "style", + "editType": "calc", + "description": "If *all*, all tick labels are displayed with a prefix. If *first*, only the first tick is displayed with a prefix. If *last*, only the last tick is displayed with a suffix. If *none*, tick prefixes are hidden." + }, + "ticksuffix": { + "valType": "string", + "dflt": "", + "role": "style", + "editType": "calc", + "description": "Sets a tick label suffix." + }, + "showticksuffix": { + "valType": "enumerated", + "values": [ + "all", + "first", + "last", + "none" + ], + "dflt": "all", + "role": "style", + "editType": "calc", + "description": "Same as `showtickprefix` but for tick suffixes." + }, + "separatethousands": { + "valType": "boolean", + "dflt": false, + "role": "style", + "editType": "calc", + "description": "If \"true\", even 4-digit integers are separated" + }, + "exponentformat": { + "valType": "enumerated", + "values": [ + "none", + "e", + "E", + "power", + "SI", + "B" + ], + "dflt": "B", + "role": "style", + "editType": "calc", + "description": "Determines a formatting rule for the tick exponents. For example, consider the number 1,000,000,000. If *none*, it appears as 1,000,000,000. If *e*, 1e+9. If *E*, 1E+9. If *power*, 1x10^9 (with 9 in a super script). If *SI*, 1G. If *B*, 1B." + }, + "showexponent": { + "valType": "enumerated", + "values": [ + "all", + "first", + "last", + "none" + ], + "dflt": "all", + "role": "style", + "editType": "calc", + "description": "If *all*, all exponents are shown besides their significands. If *first*, only the exponent of the first tick is shown. If *last*, only the exponent of the last tick is shown. If *none*, no exponents appear." + }, + "title": { + "valType": "string", + "role": "info", + "dflt": "Click to enter colorscale title", + "description": "Sets the title of the color bar.", + "editType": "calc" + }, + "titlefont": { + "family": { + "valType": "string", + "role": "style", + "noBlank": true, + "strict": true, + "description": "HTML font family - the typeface that will be applied by the web browser. The web browser will only be able to apply a font if it is available on the system which it operates. Provide multiple font families, separated by commas, to indicate the preference in which to apply fonts if they aren't available on the system. The plotly service (at https://plot.ly or on-premise) generates images on a server, where only a select number of fonts are installed and supported. These include *Arial*, *Balto*, *Courier New*, *Droid Sans*,, *Droid Serif*, *Droid Sans Mono*, *Gravitas One*, *Old Standard TT*, *Open Sans*, *Overpass*, *PT Sans Narrow*, *Raleway*, *Times New Roman*.", + "editType": "calc" + }, + "size": { + "valType": "number", + "role": "style", + "min": 1, + "editType": "calc" + }, + "color": { + "valType": "color", + "role": "style", + "editType": "calc" + }, + "description": "Sets this color bar's title font.", + "editType": "calc", + "role": "object" + }, + "titleside": { + "valType": "enumerated", + "values": [ + "right", + "top", + "bottom" + ], + "role": "style", + "dflt": "top", + "description": "Determines the location of the colorbar title with respect to the color bar.", + "editType": "calc" + }, + "editType": "calc", + "role": "object", + "tickvalssrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for tickvals .", + "editType": "none" + }, + "ticktextsrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for ticktext .", + "editType": "none" + } + }, + "contours": { + "x": { + "show": { + "valType": "boolean", + "role": "info", + "dflt": false, + "description": "Determines whether or not contour lines about the x dimension are drawn.", + "editType": "calc" + }, + "project": { + "x": { + "valType": "boolean", + "role": "info", + "dflt": false, + "description": "Determines whether or not these contour lines are projected on the x plane. If `highlight` is set to *true* (the default), the projected lines are shown on hover. If `show` is set to *true*, the projected lines are shown in permanence.", + "editType": "calc" + }, + "y": { + "valType": "boolean", + "role": "info", + "dflt": false, + "description": "Determines whether or not these contour lines are projected on the y plane. If `highlight` is set to *true* (the default), the projected lines are shown on hover. If `show` is set to *true*, the projected lines are shown in permanence.", + "editType": "calc" + }, + "z": { + "valType": "boolean", + "role": "info", + "dflt": false, + "description": "Determines whether or not these contour lines are projected on the z plane. If `highlight` is set to *true* (the default), the projected lines are shown on hover. If `show` is set to *true*, the projected lines are shown in permanence.", + "editType": "calc" + }, + "editType": "calc", + "role": "object" + }, + "color": { + "valType": "color", + "role": "style", + "dflt": "#444", + "description": "Sets the color of the contour lines.", + "editType": "calc" + }, + "usecolormap": { + "valType": "boolean", + "role": "info", + "dflt": false, + "description": "An alternate to *color*. Determines whether or not the contour lines are colored using the trace *colorscale*.", + "editType": "calc" + }, + "width": { + "valType": "number", + "role": "style", + "min": 1, + "max": 16, + "dflt": 2, + "description": "Sets the width of the contour lines.", + "editType": "calc" + }, + "highlight": { + "valType": "boolean", + "role": "info", + "dflt": true, + "description": "Determines whether or not contour lines about the x dimension are highlighted on hover.", + "editType": "calc" + }, + "highlightcolor": { + "valType": "color", + "role": "style", + "dflt": "#444", + "description": "Sets the color of the highlighted contour lines.", + "editType": "calc" + }, + "highlightwidth": { + "valType": "number", + "role": "style", + "min": 1, + "max": 16, + "dflt": 2, + "description": "Sets the width of the highlighted contour lines.", + "editType": "calc" + }, + "editType": "calc", + "role": "object" + }, + "y": { + "show": { + "valType": "boolean", + "role": "info", + "dflt": false, + "description": "Determines whether or not contour lines about the y dimension are drawn.", + "editType": "calc" + }, + "project": { + "x": { + "valType": "boolean", + "role": "info", + "dflt": false, + "description": "Determines whether or not these contour lines are projected on the x plane. If `highlight` is set to *true* (the default), the projected lines are shown on hover. If `show` is set to *true*, the projected lines are shown in permanence.", + "editType": "calc" + }, + "y": { + "valType": "boolean", + "role": "info", + "dflt": false, + "description": "Determines whether or not these contour lines are projected on the y plane. If `highlight` is set to *true* (the default), the projected lines are shown on hover. If `show` is set to *true*, the projected lines are shown in permanence.", + "editType": "calc" + }, + "z": { + "valType": "boolean", + "role": "info", + "dflt": false, + "description": "Determines whether or not these contour lines are projected on the z plane. If `highlight` is set to *true* (the default), the projected lines are shown on hover. If `show` is set to *true*, the projected lines are shown in permanence.", + "editType": "calc" + }, + "editType": "calc", + "role": "object" + }, + "color": { + "valType": "color", + "role": "style", + "dflt": "#444", + "description": "Sets the color of the contour lines.", + "editType": "calc" + }, + "usecolormap": { + "valType": "boolean", + "role": "info", + "dflt": false, + "description": "An alternate to *color*. Determines whether or not the contour lines are colored using the trace *colorscale*.", + "editType": "calc" + }, + "width": { + "valType": "number", + "role": "style", + "min": 1, + "max": 16, + "dflt": 2, + "description": "Sets the width of the contour lines.", + "editType": "calc" + }, + "highlight": { + "valType": "boolean", + "role": "info", + "dflt": true, + "description": "Determines whether or not contour lines about the y dimension are highlighted on hover.", + "editType": "calc" + }, + "highlightcolor": { + "valType": "color", + "role": "style", + "dflt": "#444", + "description": "Sets the color of the highlighted contour lines.", + "editType": "calc" + }, + "highlightwidth": { + "valType": "number", + "role": "style", + "min": 1, + "max": 16, + "dflt": 2, + "description": "Sets the width of the highlighted contour lines.", + "editType": "calc" + }, + "editType": "calc", + "role": "object" + }, + "z": { + "show": { + "valType": "boolean", + "role": "info", + "dflt": false, + "description": "Determines whether or not contour lines about the z dimension are drawn.", + "editType": "calc" + }, + "project": { + "x": { + "valType": "boolean", + "role": "info", + "dflt": false, + "description": "Determines whether or not these contour lines are projected on the x plane. If `highlight` is set to *true* (the default), the projected lines are shown on hover. If `show` is set to *true*, the projected lines are shown in permanence.", + "editType": "calc" + }, + "y": { + "valType": "boolean", + "role": "info", + "dflt": false, + "description": "Determines whether or not these contour lines are projected on the y plane. If `highlight` is set to *true* (the default), the projected lines are shown on hover. If `show` is set to *true*, the projected lines are shown in permanence.", + "editType": "calc" + }, + "z": { + "valType": "boolean", + "role": "info", + "dflt": false, + "description": "Determines whether or not these contour lines are projected on the z plane. If `highlight` is set to *true* (the default), the projected lines are shown on hover. If `show` is set to *true*, the projected lines are shown in permanence.", + "editType": "calc" + }, + "editType": "calc", + "role": "object" + }, + "color": { + "valType": "color", + "role": "style", + "dflt": "#444", + "description": "Sets the color of the contour lines.", + "editType": "calc" + }, + "usecolormap": { + "valType": "boolean", + "role": "info", + "dflt": false, + "description": "An alternate to *color*. Determines whether or not the contour lines are colored using the trace *colorscale*.", + "editType": "calc" + }, + "width": { + "valType": "number", + "role": "style", + "min": 1, + "max": 16, + "dflt": 2, + "description": "Sets the width of the contour lines.", + "editType": "calc" + }, + "highlight": { + "valType": "boolean", + "role": "info", + "dflt": true, + "description": "Determines whether or not contour lines about the z dimension are highlighted on hover.", + "editType": "calc" + }, + "highlightcolor": { + "valType": "color", + "role": "style", + "dflt": "#444", + "description": "Sets the color of the highlighted contour lines.", + "editType": "calc" + }, + "highlightwidth": { + "valType": "number", + "role": "style", + "min": 1, + "max": 16, + "dflt": 2, + "description": "Sets the width of the highlighted contour lines.", + "editType": "calc" + }, + "editType": "calc", + "role": "object" + }, + "editType": "calc", + "role": "object" + }, + "hidesurface": { + "valType": "boolean", + "role": "info", + "dflt": false, + "description": "Determines whether or not a surface is drawn. For example, set `hidesurface` to *false* `contours.x.show` to *true* and `contours.y.show` to *true* to draw a wire frame plot.", + "editType": "calc" + }, + "lightposition": { + "x": { + "valType": "number", + "role": "style", + "min": -100000, + "max": 100000, + "dflt": 10, + "description": "Numeric vector, representing the X coordinate for each vertex.", + "editType": "calc" + }, + "y": { + "valType": "number", + "role": "style", + "min": -100000, + "max": 100000, + "dflt": 10000, + "description": "Numeric vector, representing the Y coordinate for each vertex.", + "editType": "calc" + }, + "z": { + "valType": "number", + "role": "style", + "min": -100000, + "max": 100000, + "dflt": 0, + "description": "Numeric vector, representing the Z coordinate for each vertex.", + "editType": "calc" + }, + "editType": "calc", + "role": "object" + }, + "lighting": { + "ambient": { + "valType": "number", + "role": "style", + "min": 0, + "max": 1, + "dflt": 0.8, + "description": "Ambient light increases overall color visibility but can wash out the image.", + "editType": "calc" + }, + "diffuse": { + "valType": "number", + "role": "style", + "min": 0, + "max": 1, + "dflt": 0.8, + "description": "Represents the extent that incident rays are reflected in a range of angles.", + "editType": "calc" + }, + "specular": { + "valType": "number", + "role": "style", + "min": 0, + "max": 2, + "dflt": 0.05, + "description": "Represents the level that incident rays are reflected in a single direction, causing shine.", + "editType": "calc" + }, + "roughness": { + "valType": "number", + "role": "style", + "min": 0, + "max": 1, + "dflt": 0.5, + "description": "Alters specular reflection; the rougher the surface, the wider and less contrasty the shine.", + "editType": "calc" + }, + "fresnel": { + "valType": "number", + "role": "style", + "min": 0, + "max": 5, + "dflt": 0.2, + "description": "Represents the reflectance as a dependency of the viewing angle; e.g. paper is reflective when viewing it from the edge of the paper (almost 90 degrees), causing shine.", + "editType": "calc" + }, + "editType": "calc", + "role": "object" + }, + "_deprecated": { + "zauto": { + "valType": "boolean", + "role": "info", + "dflt": true, + "editType": "calc", + "impliedEdits": {}, + "description": "Obsolete. Use `cauto` instead." + }, + "zmin": { + "valType": "number", + "role": "info", + "dflt": null, + "editType": "calc", + "impliedEdits": { + "zauto": false + }, + "description": "Obsolete. Use `cmin` instead." + }, + "zmax": { + "valType": "number", + "role": "info", + "dflt": null, + "editType": "calc", + "impliedEdits": { + "zauto": false + }, + "description": "Obsolete. Use `cmax` instead." + } + }, + "xcalendar": { + "valType": "enumerated", + "values": [ + "gregorian", + "chinese", + "coptic", + "discworld", + "ethiopian", + "hebrew", + "islamic", + "julian", + "mayan", + "nanakshahi", + "nepali", + "persian", + "jalali", + "taiwan", + "thai", + "ummalqura" + ], + "role": "info", + "editType": "calc", + "dflt": "gregorian", + "description": "Sets the calendar system to use with `x` date data." + }, + "ycalendar": { + "valType": "enumerated", + "values": [ + "gregorian", + "chinese", + "coptic", + "discworld", + "ethiopian", + "hebrew", + "islamic", + "julian", + "mayan", + "nanakshahi", + "nepali", + "persian", + "jalali", + "taiwan", + "thai", + "ummalqura" + ], + "role": "info", + "editType": "calc", + "dflt": "gregorian", + "description": "Sets the calendar system to use with `y` date data." + }, + "zcalendar": { + "valType": "enumerated", + "values": [ + "gregorian", + "chinese", + "coptic", + "discworld", + "ethiopian", + "hebrew", + "islamic", + "julian", + "mayan", + "nanakshahi", + "nepali", + "persian", + "jalali", + "taiwan", + "thai", + "ummalqura" + ], + "role": "info", + "editType": "calc", + "dflt": "gregorian", + "description": "Sets the calendar system to use with `z` date data." + }, + "scene": { + "valType": "subplotid", + "role": "info", + "dflt": "scene", + "editType": "calc+clearAxisTypes", + "description": "Sets a reference between this trace's 3D coordinate system and a 3D scene. If *scene* (the default value), the (x,y,z) coordinates refer to `layout.scene`. If *scene2*, the (x,y,z) coordinates refer to `layout.scene2`, and so on." + }, + "idssrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for ids .", + "editType": "none" + }, + "customdatasrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for customdata .", + "editType": "none" + }, + "hoverinfosrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for hoverinfo .", + "editType": "none" + }, + "zsrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for z .", + "editType": "none" + }, + "xsrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for x .", + "editType": "none" + }, + "ysrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for y .", + "editType": "none" + }, + "textsrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for text .", + "editType": "none" + }, + "surfacecolorsrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for surfacecolor .", + "editType": "none" + } + } + }, + "mesh3d": { + "meta": { + "description": "Draws sets of triangles with coordinates given by three 1-dimensional arrays in `x`, `y`, `z` and (1) a sets of `i`, `j`, `k` indices (2) Delaunay triangulation or (3) the Alpha-shape algorithm or (4) the Convex-hull algorithm" + }, + "attributes": { + "type": "mesh3d", + "visible": { + "valType": "enumerated", + "values": [ + true, + false, + "legendonly" + ], + "role": "info", + "dflt": true, + "editType": "calc", + "description": "Determines whether or not this trace is visible. If *legendonly*, the trace is not drawn, but can appear as a legend item (provided that the legend itself is visible)." + }, + "showlegend": { + "valType": "boolean", + "role": "info", + "dflt": true, + "editType": "style", + "description": "Determines whether or not an item corresponding to this trace is shown in the legend." + }, + "legendgroup": { + "valType": "string", + "role": "info", + "dflt": "", + "editType": "style", + "description": "Sets the legend group for this trace. Traces part of the same legend group hide/show at the same time when toggling legend items." + }, + "opacity": { + "valType": "number", + "role": "style", + "min": 0, + "max": 1, + "dflt": 1, + "editType": "calc", + "description": "Sets the opacity of the surface." + }, + "name": { + "valType": "string", + "role": "info", + "editType": "style", + "description": "Sets the trace name. The trace name appear as the legend item and on hover." + }, + "uid": { + "valType": "string", + "role": "info", + "dflt": "", + "editType": "calc" + }, + "ids": { + "valType": "data_array", + "editType": "calc", + "description": "Assigns id labels to each datum. These ids for object constancy of data points during animation.", + "role": "data" + }, + "customdata": { + "valType": "data_array", + "editType": "calc", + "description": "Assigns extra data each datum. This may be useful when listening to hover, click and selection events. Note that, *scatter* traces also appends customdata items in the markers DOM elements", + "role": "data" + }, + "selectedpoints": { + "valType": "any", + "role": "info", + "editType": "calc", + "description": "Array containing integer indices of selected points. Has an effect only for traces that support selections. Note that an empty array means an empty selection where the `unselected` are turned on for all points, whereas, any other non-array values means no selection all where the `selected` and `unselected` styles have no effect." + }, + "hoverinfo": { + "valType": "flaglist", + "role": "info", + "flags": [ + "x", + "y", + "z", + "text", + "name" + ], + "extras": [ + "all", + "none", + "skip" + ], + "arrayOk": true, + "dflt": "all", + "editType": "none", + "description": "Determines which trace information appear on hover. If `none` or `skip` are set, no information is displayed upon hovering. But, if `none` is set, click and hover events are still fired." + }, + "hoverlabel": { + "bgcolor": { + "valType": "color", + "role": "style", + "arrayOk": true, + "editType": "none", + "description": "Sets the background color of the hover labels for this trace" + }, + "bordercolor": { + "valType": "color", + "role": "style", + "arrayOk": true, + "editType": "none", + "description": "Sets the border color of the hover labels for this trace." + }, + "font": { + "family": { + "valType": "string", + "role": "style", + "noBlank": true, + "strict": true, + "editType": "none", + "description": "HTML font family - the typeface that will be applied by the web browser. The web browser will only be able to apply a font if it is available on the system which it operates. Provide multiple font families, separated by commas, to indicate the preference in which to apply fonts if they aren't available on the system. The plotly service (at https://plot.ly or on-premise) generates images on a server, where only a select number of fonts are installed and supported. These include *Arial*, *Balto*, *Courier New*, *Droid Sans*,, *Droid Serif*, *Droid Sans Mono*, *Gravitas One*, *Old Standard TT*, *Open Sans*, *Overpass*, *PT Sans Narrow*, *Raleway*, *Times New Roman*.", + "arrayOk": true + }, + "size": { + "valType": "number", + "role": "style", + "min": 1, + "editType": "none", + "arrayOk": true + }, + "color": { + "valType": "color", + "role": "style", + "editType": "none", + "arrayOk": true + }, + "editType": "none", + "description": "Sets the font used in hover labels.", + "role": "object", + "familysrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for family .", + "editType": "none" + }, + "sizesrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for size .", + "editType": "none" + }, + "colorsrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for color .", + "editType": "none" + } + }, + "namelength": { + "valType": "integer", + "min": -1, + "arrayOk": true, + "role": "style", + "editType": "none", + "description": "Sets the length (in number of characters) of the trace name in the hover labels for this trace. -1 shows the whole name regardless of length. 0-3 shows the first 0-3 characters, and an integer >3 will show the whole name if it is less than that many characters, but if it is longer, will truncate to `namelength - 3` characters and add an ellipsis." + }, + "editType": "calc", + "role": "object", + "bgcolorsrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for bgcolor .", + "editType": "none" + }, + "bordercolorsrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for bordercolor .", + "editType": "none" + }, + "namelengthsrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for namelength .", + "editType": "none" + } + }, + "stream": { + "token": { + "valType": "string", + "noBlank": true, + "strict": true, + "role": "info", + "editType": "calc", + "description": "The stream id number links a data trace on a plot with a stream. See https://plot.ly/settings for more details." + }, + "maxpoints": { + "valType": "number", + "min": 0, + "max": 10000, + "dflt": 500, + "role": "info", + "editType": "calc", + "description": "Sets the maximum number of points to keep on the plots from an incoming stream. If `maxpoints` is set to *50*, only the newest 50 points will be displayed on the plot." + }, + "editType": "calc", + "role": "object" + }, + "color": { + "valType": "color", + "role": "style", + "editType": "calc", + "description": "Sets the color of the whole mesh" + }, + "colorscale": { + "valType": "colorscale", + "role": "style", + "editType": "calc", + "impliedEdits": { + "autocolorscale": false + }, + "description": "Sets the colorscale and only has an effect if `color` is set to a numerical array. The colorscale must be an array containing arrays mapping a normalized value to an rgb, rgba, hex, hsl, hsv, or named color string. At minimum, a mapping for the lowest (0) and highest (1) values are required. For example, `[[0, 'rgb(0,0,255)', [1, 'rgb(255,0,0)']]`. To control the bounds of the colorscale in color space, use `cmin` and `cmax`. Alternatively, `colorscale` may be a palette name string of the following list: Greys, YlGnBu, Greens, YlOrRd, Bluered, RdBu, Reds, Blues, Picnic, Rainbow, Portland, Jet, Hot, Blackbody, Earth, Electric, Viridis" + }, + "cauto": { + "valType": "boolean", + "role": "info", + "dflt": true, + "editType": "calc", + "impliedEdits": {}, + "description": "Has an effect only if `color` is set to a numerical array and `cmin`, `cmax` are set by the user. In this case, it controls whether the range of colors in `colorscale` is mapped to the range of values in the `color` array (`cauto: true`), or the `cmin`/`cmax` values (`cauto: false`). Defaults to `false` when `cmin`, `cmax` are set by the user." + }, + "cmax": { + "valType": "number", + "role": "info", + "dflt": null, + "editType": "calc", + "impliedEdits": { + "cauto": false + }, + "description": "Has an effect only if `color` is set to a numerical array. Sets the upper bound of the color domain. Value should be associated to the `color` array index, and if set, `cmin` must be set as well." + }, + "cmin": { + "valType": "number", + "role": "info", + "dflt": null, + "editType": "calc", + "impliedEdits": { + "cauto": false + }, + "description": "Has an effect only if `color` is set to a numerical array. Sets the lower bound of the color domain. Value should be associated to the `color` array index, and if set, `cmax` must be set as well." + }, + "autocolorscale": { + "valType": "boolean", + "role": "style", + "dflt": false, + "editType": "calc", + "impliedEdits": {}, + "description": "Has an effect only if `color` is set to a numerical array. Determines whether the colorscale is a default palette (`autocolorscale: true`) or the palette determined by `colorscale`. In case `colorscale` is unspecified or `autocolorscale` is true, the default palette will be chosen according to whether numbers in the `color` array are all positive, all negative or mixed." + }, + "reversescale": { + "valType": "boolean", + "role": "style", + "dflt": false, + "editType": "calc", + "description": "Has an effect only if `color` is set to a numerical array. Reverses the color mapping if true (`cmin` will correspond to the last color in the array and `cmax` will correspond to the first color)." + }, + "x": { + "valType": "data_array", + "editType": "calc+clearAxisTypes", + "description": "Sets the X coordinates of the vertices. The nth element of vectors `x`, `y` and `z` jointly represent the X, Y and Z coordinates of the nth vertex.", + "role": "data" + }, + "y": { + "valType": "data_array", + "editType": "calc+clearAxisTypes", + "description": "Sets the Y coordinates of the vertices. The nth element of vectors `x`, `y` and `z` jointly represent the X, Y and Z coordinates of the nth vertex.", + "role": "data" + }, + "z": { + "valType": "data_array", + "editType": "calc+clearAxisTypes", + "description": "Sets the Z coordinates of the vertices. The nth element of vectors `x`, `y` and `z` jointly represent the X, Y and Z coordinates of the nth vertex.", + "role": "data" + }, + "i": { + "valType": "data_array", + "editType": "calc", + "description": "A vector of vertex indices, i.e. integer values between 0 and the length of the vertex vectors, representing the *first* vertex of a triangle. For example, `{i[m], j[m], k[m]}` together represent face m (triangle m) in the mesh, where `i[m] = n` points to the triplet `{x[n], y[n], z[n]}` in the vertex arrays. Therefore, each element in `i` represents a point in space, which is the first vertex of a triangle.", + "role": "data" + }, + "j": { + "valType": "data_array", + "editType": "calc", + "description": "A vector of vertex indices, i.e. integer values between 0 and the length of the vertex vectors, representing the *second* vertex of a triangle. For example, `{i[m], j[m], k[m]}` together represent face m (triangle m) in the mesh, where `j[m] = n` points to the triplet `{x[n], y[n], z[n]}` in the vertex arrays. Therefore, each element in `j` represents a point in space, which is the second vertex of a triangle.", + "role": "data" + }, + "k": { + "valType": "data_array", + "editType": "calc", + "description": "A vector of vertex indices, i.e. integer values between 0 and the length of the vertex vectors, representing the *third* vertex of a triangle. For example, `{i[m], j[m], k[m]}` together represent face m (triangle m) in the mesh, where `k[m] = n` points to the triplet `{x[n], y[n], z[n]}` in the vertex arrays. Therefore, each element in `k` represents a point in space, which is the third vertex of a triangle.", + "role": "data" + }, + "delaunayaxis": { + "valType": "enumerated", + "role": "info", + "values": [ + "x", + "y", + "z" + ], + "dflt": "z", + "editType": "calc", + "description": "Sets the Delaunay axis, which is the axis that is perpendicular to the surface of the Delaunay triangulation. It has an effect if `i`, `j`, `k` are not provided and `alphahull` is set to indicate Delaunay triangulation." + }, + "alphahull": { + "valType": "number", + "role": "style", + "dflt": -1, + "editType": "calc", + "description": "Determines how the mesh surface triangles are derived from the set of vertices (points) represented by the `x`, `y` and `z` arrays, if the `i`, `j`, `k` arrays are not supplied. For general use of `mesh3d` it is preferred that `i`, `j`, `k` are supplied. If *-1*, Delaunay triangulation is used, which is mainly suitable if the mesh is a single, more or less layer surface that is perpendicular to `delaunayaxis`. In case the `delaunayaxis` intersects the mesh surface at more than one point it will result triangles that are very long in the dimension of `delaunayaxis`. If *>0*, the alpha-shape algorithm is used. In this case, the positive `alphahull` value signals the use of the alpha-shape algorithm, _and_ its value acts as the parameter for the mesh fitting. If *0*, the convex-hull algorithm is used. It is suitable for convex bodies or if the intention is to enclose the `x`, `y` and `z` point set into a convex hull." + }, + "intensity": { + "valType": "data_array", + "editType": "calc", + "description": "Sets the vertex intensity values, used for plotting fields on meshes", + "role": "data" + }, + "vertexcolor": { + "valType": "data_array", + "role": "data", + "editType": "calc", + "description": "Sets the color of each vertex Overrides *color*." + }, + "facecolor": { + "valType": "data_array", + "role": "data", + "editType": "calc", + "description": "Sets the color of each face Overrides *color* and *vertexcolor*." + }, + "flatshading": { + "valType": "boolean", + "role": "style", + "dflt": false, + "editType": "calc", + "description": "Determines whether or not normal smoothing is applied to the meshes, creating meshes with an angular, low-poly look via flat reflections." + }, + "contour": { + "show": { + "valType": "boolean", + "role": "info", + "dflt": false, + "description": "Sets whether or not dynamic contours are shown on hover", + "editType": "calc" + }, + "color": { + "valType": "color", + "role": "style", + "dflt": "#444", + "description": "Sets the color of the contour lines.", + "editType": "calc" + }, + "width": { + "valType": "number", + "role": "style", + "min": 1, + "max": 16, + "dflt": 2, + "description": "Sets the width of the contour lines.", + "editType": "calc" + }, + "editType": "calc", + "role": "object" + }, + "showscale": { + "valType": "boolean", + "role": "info", + "dflt": true, + "editType": "calc", + "description": "Determines whether or not a colorbar is displayed for this trace." + }, + "colorbar": { + "thicknessmode": { + "valType": "enumerated", + "values": [ + "fraction", + "pixels" + ], + "role": "style", + "dflt": "pixels", + "description": "Determines whether this color bar's thickness (i.e. the measure in the constant color direction) is set in units of plot *fraction* or in *pixels*. Use `thickness` to set the value.", + "editType": "colorbars" + }, + "thickness": { + "valType": "number", + "role": "style", + "min": 0, + "dflt": 30, + "description": "Sets the thickness of the color bar This measure excludes the size of the padding, ticks and labels.", + "editType": "colorbars" + }, + "lenmode": { + "valType": "enumerated", + "values": [ + "fraction", + "pixels" + ], + "role": "info", + "dflt": "fraction", + "description": "Determines whether this color bar's length (i.e. the measure in the color variation direction) is set in units of plot *fraction* or in *pixels. Use `len` to set the value.", + "editType": "colorbars" + }, + "len": { + "valType": "number", + "min": 0, + "dflt": 1, + "role": "style", + "description": "Sets the length of the color bar This measure excludes the padding of both ends. That is, the color bar length is this length minus the padding on both ends.", + "editType": "colorbars" + }, + "x": { + "valType": "number", + "dflt": 1.02, + "min": -2, + "max": 3, + "role": "style", + "description": "Sets the x position of the color bar (in plot fraction).", + "editType": "colorbars" + }, + "xanchor": { + "valType": "enumerated", + "values": [ + "left", + "center", + "right" + ], + "dflt": "left", + "role": "style", + "description": "Sets this color bar's horizontal position anchor. This anchor binds the `x` position to the *left*, *center* or *right* of the color bar.", + "editType": "colorbars" + }, + "xpad": { + "valType": "number", + "role": "style", + "min": 0, + "dflt": 10, + "description": "Sets the amount of padding (in px) along the x direction.", + "editType": "colorbars" + }, + "y": { + "valType": "number", + "role": "style", + "dflt": 0.5, + "min": -2, + "max": 3, + "description": "Sets the y position of the color bar (in plot fraction).", + "editType": "colorbars" + }, + "yanchor": { + "valType": "enumerated", + "values": [ + "top", + "middle", + "bottom" + ], + "role": "style", + "dflt": "middle", + "description": "Sets this color bar's vertical position anchor This anchor binds the `y` position to the *top*, *middle* or *bottom* of the color bar.", + "editType": "colorbars" + }, + "ypad": { + "valType": "number", + "role": "style", + "min": 0, + "dflt": 10, + "description": "Sets the amount of padding (in px) along the y direction.", + "editType": "colorbars" + }, + "outlinecolor": { + "valType": "color", + "dflt": "#444", + "role": "style", + "editType": "colorbars", + "description": "Sets the axis line color." + }, + "outlinewidth": { + "valType": "number", + "min": 0, + "dflt": 1, + "role": "style", + "editType": "colorbars", + "description": "Sets the width (in px) of the axis line." + }, + "bordercolor": { + "valType": "color", + "dflt": "#444", + "role": "style", + "editType": "colorbars", + "description": "Sets the axis line color." + }, + "borderwidth": { + "valType": "number", + "role": "style", + "min": 0, + "dflt": 0, + "description": "Sets the width (in px) or the border enclosing this color bar.", + "editType": "colorbars" + }, + "bgcolor": { + "valType": "color", + "role": "style", + "dflt": "rgba(0,0,0,0)", + "description": "Sets the color of padded area.", + "editType": "colorbars" + }, + "tickmode": { + "valType": "enumerated", + "values": [ + "auto", + "linear", + "array" + ], + "role": "info", + "editType": "colorbars", + "impliedEdits": {}, + "description": "Sets the tick mode for this axis. If *auto*, the number of ticks is set via `nticks`. If *linear*, the placement of the ticks is determined by a starting position `tick0` and a tick step `dtick` (*linear* is the default value if `tick0` and `dtick` are provided). If *array*, the placement of the ticks is set via `tickvals` and the tick text is `ticktext`. (*array* is the default value if `tickvals` is provided)." + }, + "nticks": { + "valType": "integer", + "min": 0, + "dflt": 0, + "role": "style", + "editType": "colorbars", + "description": "Specifies the maximum number of ticks for the particular axis. The actual number of ticks will be chosen automatically to be less than or equal to `nticks`. Has an effect only if `tickmode` is set to *auto*." + }, + "tick0": { + "valType": "any", + "role": "style", + "editType": "colorbars", + "impliedEdits": { + "tickmode": "linear" + }, + "description": "Sets the placement of the first tick on this axis. Use with `dtick`. If the axis `type` is *log*, then you must take the log of your starting tick (e.g. to set the starting tick to 100, set the `tick0` to 2) except when `dtick`=*L* (see `dtick` for more info). If the axis `type` is *date*, it should be a date string, like date data. If the axis `type` is *category*, it should be a number, using the scale where each category is assigned a serial number from zero in the order it appears." + }, + "dtick": { + "valType": "any", + "role": "style", + "editType": "colorbars", + "impliedEdits": { + "tickmode": "linear" + }, + "description": "Sets the step in-between ticks on this axis. Use with `tick0`. Must be a positive number, or special strings available to *log* and *date* axes. If the axis `type` is *log*, then ticks are set every 10^(n*dtick) where n is the tick number. For example, to set a tick mark at 1, 10, 100, 1000, ... set dtick to 1. To set tick marks at 1, 100, 10000, ... set dtick to 2. To set tick marks at 1, 5, 25, 125, 625, 3125, ... set dtick to log_10(5), or 0.69897000433. *log* has several special values; *L*, where `f` is a positive number, gives ticks linearly spaced in value (but not position). For example `tick0` = 0.1, `dtick` = *L0.5* will put ticks at 0.1, 0.6, 1.1, 1.6 etc. To show powers of 10 plus small digits between, use *D1* (all digits) or *D2* (only 2 and 5). `tick0` is ignored for *D1* and *D2*. If the axis `type` is *date*, then you must convert the time to milliseconds. For example, to set the interval between ticks to one day, set `dtick` to 86400000.0. *date* also has special values *M* gives ticks spaced by a number of months. `n` must be a positive integer. To set ticks on the 15th of every third month, set `tick0` to *2000-01-15* and `dtick` to *M3*. To set ticks every 4 years, set `dtick` to *M48*" + }, + "tickvals": { + "valType": "data_array", + "editType": "colorbars", + "description": "Sets the values at which ticks on this axis appear. Only has an effect if `tickmode` is set to *array*. Used with `ticktext`.", + "role": "data" + }, + "ticktext": { + "valType": "data_array", + "editType": "colorbars", + "description": "Sets the text displayed at the ticks position via `tickvals`. Only has an effect if `tickmode` is set to *array*. Used with `tickvals`.", + "role": "data" + }, + "ticks": { + "valType": "enumerated", + "values": [ + "outside", + "inside", + "" + ], + "role": "style", + "editType": "colorbars", + "description": "Determines whether ticks are drawn or not. If **, this axis' ticks are not drawn. If *outside* (*inside*), this axis' are drawn outside (inside) the axis lines.", + "dflt": "" + }, + "ticklen": { + "valType": "number", + "min": 0, + "dflt": 5, + "role": "style", + "editType": "colorbars", + "description": "Sets the tick length (in px)." + }, + "tickwidth": { + "valType": "number", + "min": 0, + "dflt": 1, + "role": "style", + "editType": "colorbars", + "description": "Sets the tick width (in px)." + }, + "tickcolor": { + "valType": "color", + "dflt": "#444", + "role": "style", + "editType": "colorbars", + "description": "Sets the tick color." + }, + "showticklabels": { + "valType": "boolean", + "dflt": true, + "role": "style", + "editType": "colorbars", + "description": "Determines whether or not the tick labels are drawn." + }, + "tickfont": { + "family": { + "valType": "string", + "role": "style", + "noBlank": true, + "strict": true, + "description": "HTML font family - the typeface that will be applied by the web browser. The web browser will only be able to apply a font if it is available on the system which it operates. Provide multiple font families, separated by commas, to indicate the preference in which to apply fonts if they aren't available on the system. The plotly service (at https://plot.ly or on-premise) generates images on a server, where only a select number of fonts are installed and supported. These include *Arial*, *Balto*, *Courier New*, *Droid Sans*,, *Droid Serif*, *Droid Sans Mono*, *Gravitas One*, *Old Standard TT*, *Open Sans*, *Overpass*, *PT Sans Narrow*, *Raleway*, *Times New Roman*.", + "editType": "colorbars" + }, + "size": { + "valType": "number", + "role": "style", + "min": 1, + "editType": "colorbars" + }, + "color": { + "valType": "color", + "role": "style", + "editType": "colorbars" + }, + "description": "Sets the color bar's tick label font", + "editType": "colorbars", + "role": "object" + }, + "tickangle": { + "valType": "angle", + "dflt": "auto", + "role": "style", + "editType": "colorbars", + "description": "Sets the angle of the tick labels with respect to the horizontal. For example, a `tickangle` of -90 draws the tick labels vertically." + }, + "tickformat": { + "valType": "string", + "dflt": "", + "role": "style", + "editType": "colorbars", + "description": "Sets the tick label formatting rule using d3 formatting mini-languages which are very similar to those in Python. For numbers, see: https://github.com/d3/d3-format/blob/master/README.md#locale_format And for dates see: https://github.com/d3/d3-time-format/blob/master/README.md#locale_format We add one item to d3's date formatter: *%{n}f* for fractional seconds with n digits. For example, *2016-10-13 09:15:23.456* with tickformat *%H~%M~%S.%2f* would display *09~15~23.46*" + }, + "tickformatstops": { + "items": { + "tickformatstop": { + "dtickrange": { + "valType": "info_array", + "role": "info", + "items": [ + { + "valType": "any", + "editType": "colorbars" + }, + { + "valType": "any", + "editType": "colorbars" + } + ], + "editType": "colorbars", + "description": "range [*min*, *max*], where *min*, *max* - dtick values which describe some zoom level, it is possible to omit *min* or *max* value by passing *null*" + }, + "value": { + "valType": "string", + "dflt": "", + "role": "style", + "editType": "colorbars", + "description": "string - dtickformat for described zoom level, the same as *tickformat*" + }, + "editType": "colorbars", + "role": "object" + } + }, + "role": "object" + }, + "tickprefix": { + "valType": "string", + "dflt": "", + "role": "style", + "editType": "colorbars", + "description": "Sets a tick label prefix." + }, + "showtickprefix": { + "valType": "enumerated", + "values": [ + "all", + "first", + "last", + "none" + ], + "dflt": "all", + "role": "style", + "editType": "colorbars", + "description": "If *all*, all tick labels are displayed with a prefix. If *first*, only the first tick is displayed with a prefix. If *last*, only the last tick is displayed with a suffix. If *none*, tick prefixes are hidden." + }, + "ticksuffix": { + "valType": "string", + "dflt": "", + "role": "style", + "editType": "colorbars", + "description": "Sets a tick label suffix." + }, + "showticksuffix": { + "valType": "enumerated", + "values": [ + "all", + "first", + "last", + "none" + ], + "dflt": "all", + "role": "style", + "editType": "colorbars", + "description": "Same as `showtickprefix` but for tick suffixes." + }, + "separatethousands": { + "valType": "boolean", + "dflt": false, + "role": "style", + "editType": "colorbars", + "description": "If \"true\", even 4-digit integers are separated" + }, + "exponentformat": { + "valType": "enumerated", + "values": [ + "none", + "e", + "E", + "power", + "SI", + "B" + ], + "dflt": "B", + "role": "style", + "editType": "colorbars", + "description": "Determines a formatting rule for the tick exponents. For example, consider the number 1,000,000,000. If *none*, it appears as 1,000,000,000. If *e*, 1e+9. If *E*, 1E+9. If *power*, 1x10^9 (with 9 in a super script). If *SI*, 1G. If *B*, 1B." + }, + "showexponent": { + "valType": "enumerated", + "values": [ + "all", + "first", + "last", + "none" + ], + "dflt": "all", + "role": "style", + "editType": "colorbars", + "description": "If *all*, all exponents are shown besides their significands. If *first*, only the exponent of the first tick is shown. If *last*, only the exponent of the last tick is shown. If *none*, no exponents appear." + }, + "title": { + "valType": "string", + "role": "info", + "dflt": "Click to enter colorscale title", + "description": "Sets the title of the color bar.", + "editType": "colorbars" + }, + "titlefont": { + "family": { + "valType": "string", + "role": "style", + "noBlank": true, + "strict": true, + "description": "HTML font family - the typeface that will be applied by the web browser. The web browser will only be able to apply a font if it is available on the system which it operates. Provide multiple font families, separated by commas, to indicate the preference in which to apply fonts if they aren't available on the system. The plotly service (at https://plot.ly or on-premise) generates images on a server, where only a select number of fonts are installed and supported. These include *Arial*, *Balto*, *Courier New*, *Droid Sans*,, *Droid Serif*, *Droid Sans Mono*, *Gravitas One*, *Old Standard TT*, *Open Sans*, *Overpass*, *PT Sans Narrow*, *Raleway*, *Times New Roman*.", + "editType": "colorbars" + }, + "size": { + "valType": "number", + "role": "style", + "min": 1, + "editType": "colorbars" + }, + "color": { + "valType": "color", + "role": "style", + "editType": "colorbars" + }, + "description": "Sets this color bar's title font.", + "editType": "colorbars", + "role": "object" + }, + "titleside": { + "valType": "enumerated", + "values": [ + "right", + "top", + "bottom" + ], + "role": "style", + "dflt": "top", + "description": "Determines the location of the colorbar title with respect to the color bar.", + "editType": "colorbars" + }, + "editType": "colorbars", + "role": "object", + "tickvalssrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for tickvals .", + "editType": "none" + }, + "ticktextsrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for ticktext .", + "editType": "none" + } + }, + "lightposition": { + "x": { + "valType": "number", + "role": "style", + "min": -100000, + "max": 100000, + "dflt": 100000, + "description": "Numeric vector, representing the X coordinate for each vertex.", + "editType": "calc" + }, + "y": { + "valType": "number", + "role": "style", + "min": -100000, + "max": 100000, + "dflt": 100000, + "description": "Numeric vector, representing the Y coordinate for each vertex.", + "editType": "calc" + }, + "z": { + "valType": "number", + "role": "style", + "min": -100000, + "max": 100000, + "dflt": 0, + "description": "Numeric vector, representing the Z coordinate for each vertex.", + "editType": "calc" + }, + "editType": "calc", + "role": "object" + }, + "lighting": { + "vertexnormalsepsilon": { + "valType": "number", + "role": "style", + "min": 0, + "max": 1, + "dflt": 1e-12, + "editType": "calc", + "description": "Epsilon for vertex normals calculation avoids math issues arising from degenerate geometry." + }, + "facenormalsepsilon": { + "valType": "number", + "role": "style", + "min": 0, + "max": 1, + "dflt": 0.000001, + "editType": "calc", + "description": "Epsilon for face normals calculation avoids math issues arising from degenerate geometry." + }, + "editType": "calc", + "ambient": { + "valType": "number", + "role": "style", + "min": 0, + "max": 1, + "dflt": 0.8, + "description": "Ambient light increases overall color visibility but can wash out the image.", + "editType": "calc" + }, + "diffuse": { + "valType": "number", + "role": "style", + "min": 0, + "max": 1, + "dflt": 0.8, + "description": "Represents the extent that incident rays are reflected in a range of angles.", + "editType": "calc" + }, + "specular": { + "valType": "number", + "role": "style", + "min": 0, + "max": 2, + "dflt": 0.05, + "description": "Represents the level that incident rays are reflected in a single direction, causing shine.", + "editType": "calc" + }, + "roughness": { + "valType": "number", + "role": "style", + "min": 0, + "max": 1, + "dflt": 0.5, + "description": "Alters specular reflection; the rougher the surface, the wider and less contrasty the shine.", + "editType": "calc" + }, + "fresnel": { + "valType": "number", + "role": "style", + "min": 0, + "max": 5, + "dflt": 0.2, + "description": "Represents the reflectance as a dependency of the viewing angle; e.g. paper is reflective when viewing it from the edge of the paper (almost 90 degrees), causing shine.", + "editType": "calc" + }, + "role": "object" + }, + "xcalendar": { + "valType": "enumerated", + "values": [ + "gregorian", + "chinese", + "coptic", + "discworld", + "ethiopian", + "hebrew", + "islamic", + "julian", + "mayan", + "nanakshahi", + "nepali", + "persian", + "jalali", + "taiwan", + "thai", + "ummalqura" + ], + "role": "info", + "editType": "calc", + "dflt": "gregorian", + "description": "Sets the calendar system to use with `x` date data." + }, + "ycalendar": { + "valType": "enumerated", + "values": [ + "gregorian", + "chinese", + "coptic", + "discworld", + "ethiopian", + "hebrew", + "islamic", + "julian", + "mayan", + "nanakshahi", + "nepali", + "persian", + "jalali", + "taiwan", + "thai", + "ummalqura" + ], + "role": "info", + "editType": "calc", + "dflt": "gregorian", + "description": "Sets the calendar system to use with `y` date data." + }, + "zcalendar": { + "valType": "enumerated", + "values": [ + "gregorian", + "chinese", + "coptic", + "discworld", + "ethiopian", + "hebrew", + "islamic", + "julian", + "mayan", + "nanakshahi", + "nepali", + "persian", + "jalali", + "taiwan", + "thai", + "ummalqura" + ], + "role": "info", + "editType": "calc", + "dflt": "gregorian", + "description": "Sets the calendar system to use with `z` date data." + }, + "scene": { + "valType": "subplotid", + "role": "info", + "dflt": "scene", + "editType": "calc+clearAxisTypes", + "description": "Sets a reference between this trace's 3D coordinate system and a 3D scene. If *scene* (the default value), the (x,y,z) coordinates refer to `layout.scene`. If *scene2*, the (x,y,z) coordinates refer to `layout.scene2`, and so on." + }, + "idssrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for ids .", + "editType": "none" + }, + "customdatasrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for customdata .", + "editType": "none" + }, + "hoverinfosrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for hoverinfo .", + "editType": "none" + }, + "xsrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for x .", + "editType": "none" + }, + "ysrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for y .", + "editType": "none" + }, + "zsrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for z .", + "editType": "none" + }, + "isrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for i .", + "editType": "none" + }, + "jsrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for j .", + "editType": "none" + }, + "ksrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for k .", + "editType": "none" + }, + "intensitysrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for intensity .", + "editType": "none" + }, + "vertexcolorsrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for vertexcolor .", + "editType": "none" + }, + "facecolorsrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for facecolor .", + "editType": "none" + } + } + }, + "scattergeo": { + "meta": { + "hrName": "scatter_geo", + "description": "The data visualized as scatter point or lines on a geographic map is provided either by longitude/latitude pairs in `lon` and `lat` respectively or by geographic location IDs or names in `locations`." + }, + "attributes": { + "type": "scattergeo", + "visible": { + "valType": "enumerated", + "values": [ + true, + false, + "legendonly" + ], + "role": "info", + "dflt": true, + "editType": "calc", + "description": "Determines whether or not this trace is visible. If *legendonly*, the trace is not drawn, but can appear as a legend item (provided that the legend itself is visible)." + }, + "showlegend": { + "valType": "boolean", + "role": "info", + "dflt": true, + "editType": "style", + "description": "Determines whether or not an item corresponding to this trace is shown in the legend." + }, + "legendgroup": { + "valType": "string", + "role": "info", + "dflt": "", + "editType": "style", + "description": "Sets the legend group for this trace. Traces part of the same legend group hide/show at the same time when toggling legend items." + }, + "opacity": { + "valType": "number", + "role": "style", + "min": 0, + "max": 1, + "dflt": 1, + "editType": "style", + "description": "Sets the opacity of the trace." + }, + "name": { + "valType": "string", + "role": "info", + "editType": "style", + "description": "Sets the trace name. The trace name appear as the legend item and on hover." + }, + "uid": { + "valType": "string", + "role": "info", + "dflt": "", + "editType": "calc" + }, + "ids": { + "valType": "data_array", + "editType": "calc", + "description": "Assigns id labels to each datum. These ids for object constancy of data points during animation.", + "role": "data" + }, + "customdata": { + "valType": "data_array", + "editType": "calc", + "description": "Assigns extra data each datum. This may be useful when listening to hover, click and selection events. Note that, *scatter* traces also appends customdata items in the markers DOM elements", + "role": "data" + }, + "selectedpoints": { + "valType": "any", + "role": "info", + "editType": "calc", + "description": "Array containing integer indices of selected points. Has an effect only for traces that support selections. Note that an empty array means an empty selection where the `unselected` are turned on for all points, whereas, any other non-array values means no selection all where the `selected` and `unselected` styles have no effect." + }, + "hoverinfo": { + "valType": "flaglist", + "role": "info", + "flags": [ + "lon", + "lat", + "location", + "text", + "name" + ], + "extras": [ + "all", + "none", + "skip" + ], + "arrayOk": true, + "dflt": "all", + "editType": "calc", + "description": "Determines which trace information appear on hover. If `none` or `skip` are set, no information is displayed upon hovering. But, if `none` is set, click and hover events are still fired." + }, + "hoverlabel": { + "bgcolor": { + "valType": "color", + "role": "style", + "arrayOk": true, + "editType": "none", + "description": "Sets the background color of the hover labels for this trace" + }, + "bordercolor": { + "valType": "color", + "role": "style", + "arrayOk": true, + "editType": "none", + "description": "Sets the border color of the hover labels for this trace." + }, + "font": { + "family": { + "valType": "string", + "role": "style", + "noBlank": true, + "strict": true, + "editType": "none", + "description": "HTML font family - the typeface that will be applied by the web browser. The web browser will only be able to apply a font if it is available on the system which it operates. Provide multiple font families, separated by commas, to indicate the preference in which to apply fonts if they aren't available on the system. The plotly service (at https://plot.ly or on-premise) generates images on a server, where only a select number of fonts are installed and supported. These include *Arial*, *Balto*, *Courier New*, *Droid Sans*,, *Droid Serif*, *Droid Sans Mono*, *Gravitas One*, *Old Standard TT*, *Open Sans*, *Overpass*, *PT Sans Narrow*, *Raleway*, *Times New Roman*.", + "arrayOk": true + }, + "size": { + "valType": "number", + "role": "style", + "min": 1, + "editType": "none", + "arrayOk": true + }, + "color": { + "valType": "color", + "role": "style", + "editType": "none", + "arrayOk": true + }, + "editType": "none", + "description": "Sets the font used in hover labels.", + "role": "object", + "familysrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for family .", + "editType": "none" + }, + "sizesrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for size .", + "editType": "none" + }, + "colorsrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for color .", + "editType": "none" + } + }, + "namelength": { + "valType": "integer", + "min": -1, + "arrayOk": true, + "role": "style", + "editType": "none", + "description": "Sets the length (in number of characters) of the trace name in the hover labels for this trace. -1 shows the whole name regardless of length. 0-3 shows the first 0-3 characters, and an integer >3 will show the whole name if it is less than that many characters, but if it is longer, will truncate to `namelength - 3` characters and add an ellipsis." + }, + "editType": "calc", + "role": "object", + "bgcolorsrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for bgcolor .", + "editType": "none" + }, + "bordercolorsrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for bordercolor .", + "editType": "none" + }, + "namelengthsrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for namelength .", + "editType": "none" + } + }, + "stream": { + "token": { + "valType": "string", + "noBlank": true, + "strict": true, + "role": "info", + "editType": "calc", + "description": "The stream id number links a data trace on a plot with a stream. See https://plot.ly/settings for more details." + }, + "maxpoints": { + "valType": "number", + "min": 0, + "max": 10000, + "dflt": 500, + "role": "info", + "editType": "calc", + "description": "Sets the maximum number of points to keep on the plots from an incoming stream. If `maxpoints` is set to *50*, only the newest 50 points will be displayed on the plot." + }, + "editType": "calc", + "role": "object" + }, + "lon": { + "valType": "data_array", + "description": "Sets the longitude coordinates (in degrees East).", + "editType": "calc", + "role": "data" + }, + "lat": { + "valType": "data_array", + "description": "Sets the latitude coordinates (in degrees North).", + "editType": "calc", + "role": "data" + }, + "locations": { + "valType": "data_array", + "description": "Sets the coordinates via location IDs or names. Coordinates correspond to the centroid of each location given. See `locationmode` for more info.", + "editType": "calc", + "role": "data" + }, + "locationmode": { + "valType": "enumerated", + "values": [ + "ISO-3", + "USA-states", + "country names" + ], + "role": "info", + "dflt": "ISO-3", + "description": "Determines the set of locations used to match entries in `locations` to regions on the map.", + "editType": "calc" + }, + "mode": { + "valType": "flaglist", + "flags": [ + "lines", + "markers", + "text" + ], + "extras": [ + "none" + ], + "role": "info", + "editType": "calc", + "description": "Determines the drawing mode for this scatter trace. If the provided `mode` includes *text* then the `text` elements appear at the coordinates. Otherwise, the `text` elements appear on hover. If there are less than 20 points, then the default is *lines+markers*. Otherwise, *lines*.", + "dflt": "markers" + }, + "text": { + "valType": "string", + "role": "info", + "dflt": "", + "arrayOk": true, + "editType": "calc", + "description": "Sets text elements associated with each (lon,lat) pair or item in `locations`. If a single string, the same string appears over all the data points. If an array of string, the items are mapped in order to the this trace's (lon,lat) or `locations` coordinates. If trace `hoverinfo` contains a *text* flag and *hovertext* is not set, these elements will be seen in the hover labels." + }, + "hovertext": { + "valType": "string", + "role": "info", + "dflt": "", + "arrayOk": true, + "editType": "calc", + "description": "Sets hover text elements associated with each (lon,lat) pair or item in `locations`. If a single string, the same string appears over all the data points. If an array of string, the items are mapped in order to the this trace's (lon,lat) or `locations` coordinates. To be seen, trace `hoverinfo` must contain a *text* flag." + }, + "textfont": { + "family": { + "valType": "string", + "role": "style", + "noBlank": true, + "strict": true, + "editType": "calc", + "description": "HTML font family - the typeface that will be applied by the web browser. The web browser will only be able to apply a font if it is available on the system which it operates. Provide multiple font families, separated by commas, to indicate the preference in which to apply fonts if they aren't available on the system. The plotly service (at https://plot.ly or on-premise) generates images on a server, where only a select number of fonts are installed and supported. These include *Arial*, *Balto*, *Courier New*, *Droid Sans*,, *Droid Serif*, *Droid Sans Mono*, *Gravitas One*, *Old Standard TT*, *Open Sans*, *Overpass*, *PT Sans Narrow*, *Raleway*, *Times New Roman*.", + "arrayOk": true + }, + "size": { + "valType": "number", + "role": "style", + "min": 1, + "editType": "calc", + "arrayOk": true + }, + "color": { + "valType": "color", + "role": "style", + "editType": "calc", + "arrayOk": true + }, + "editType": "calc", + "description": "Sets the text font.", + "role": "object", + "familysrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for family .", + "editType": "none" + }, + "sizesrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for size .", + "editType": "none" + }, + "colorsrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for color .", + "editType": "none" + } + }, + "textposition": { + "valType": "enumerated", + "values": [ + "top left", + "top center", + "top right", + "middle left", + "middle center", + "middle right", + "bottom left", + "bottom center", + "bottom right" + ], + "dflt": "middle center", + "arrayOk": true, + "role": "style", + "editType": "calc", + "description": "Sets the positions of the `text` elements with respects to the (x,y) coordinates." + }, + "line": { + "color": { + "valType": "color", + "role": "style", + "editType": "calc", + "description": "Sets the line color." + }, + "width": { + "valType": "number", + "min": 0, + "dflt": 2, + "role": "style", + "editType": "calc", + "description": "Sets the line width (in px)." + }, + "dash": { + "valType": "string", + "values": [ + "solid", + "dot", + "dash", + "longdash", + "dashdot", + "longdashdot" + ], + "dflt": "solid", + "role": "style", + "editType": "calc", + "description": "Sets the dash style of lines. Set to a dash type string (*solid*, *dot*, *dash*, *longdash*, *dashdot*, or *longdashdot*) or a dash length list in px (eg *5px,10px,2px,2px*)." + }, + "editType": "calc", + "role": "object" + }, + "connectgaps": { + "valType": "boolean", + "dflt": false, + "role": "info", + "editType": "calc", + "description": "Determines whether or not gaps (i.e. {nan} or missing values) in the provided data arrays are connected." + }, + "marker": { + "symbol": { + "valType": "enumerated", + "values": [ + 0, + "circle", + 100, + "circle-open", + 200, + "circle-dot", + 300, + "circle-open-dot", + 1, + "square", + 101, + "square-open", + 201, + "square-dot", + 301, + "square-open-dot", + 2, + "diamond", + 102, + "diamond-open", + 202, + "diamond-dot", + 302, + "diamond-open-dot", + 3, + "cross", + 103, + "cross-open", + 203, + "cross-dot", + 303, + "cross-open-dot", + 4, + "x", + 104, + "x-open", + 204, + "x-dot", + 304, + "x-open-dot", + 5, + "triangle-up", + 105, + "triangle-up-open", + 205, + "triangle-up-dot", + 305, + "triangle-up-open-dot", + 6, + "triangle-down", + 106, + "triangle-down-open", + 206, + "triangle-down-dot", + 306, + "triangle-down-open-dot", + 7, + "triangle-left", + 107, + "triangle-left-open", + 207, + "triangle-left-dot", + 307, + "triangle-left-open-dot", + 8, + "triangle-right", + 108, + "triangle-right-open", + 208, + "triangle-right-dot", + 308, + "triangle-right-open-dot", + 9, + "triangle-ne", + 109, + "triangle-ne-open", + 209, + "triangle-ne-dot", + 309, + "triangle-ne-open-dot", + 10, + "triangle-se", + 110, + "triangle-se-open", + 210, + "triangle-se-dot", + 310, + "triangle-se-open-dot", + 11, + "triangle-sw", + 111, + "triangle-sw-open", + 211, + "triangle-sw-dot", + 311, + "triangle-sw-open-dot", + 12, + "triangle-nw", + 112, + "triangle-nw-open", + 212, + "triangle-nw-dot", + 312, + "triangle-nw-open-dot", + 13, + "pentagon", + 113, + "pentagon-open", + 213, + "pentagon-dot", + 313, + "pentagon-open-dot", + 14, + "hexagon", + 114, + "hexagon-open", + 214, + "hexagon-dot", + 314, + "hexagon-open-dot", + 15, + "hexagon2", + 115, + "hexagon2-open", + 215, + "hexagon2-dot", + 315, + "hexagon2-open-dot", + 16, + "octagon", + 116, + "octagon-open", + 216, + "octagon-dot", + 316, + "octagon-open-dot", + 17, + "star", + 117, + "star-open", + 217, + "star-dot", + 317, + "star-open-dot", + 18, + "hexagram", + 118, + "hexagram-open", + 218, + "hexagram-dot", + 318, + "hexagram-open-dot", + 19, + "star-triangle-up", + 119, + "star-triangle-up-open", + 219, + "star-triangle-up-dot", + 319, + "star-triangle-up-open-dot", + 20, + "star-triangle-down", + 120, + "star-triangle-down-open", + 220, + "star-triangle-down-dot", + 320, + "star-triangle-down-open-dot", + 21, + "star-square", + 121, + "star-square-open", + 221, + "star-square-dot", + 321, + "star-square-open-dot", + 22, + "star-diamond", + 122, + "star-diamond-open", + 222, + "star-diamond-dot", + 322, + "star-diamond-open-dot", + 23, + "diamond-tall", + 123, + "diamond-tall-open", + 223, + "diamond-tall-dot", + 323, + "diamond-tall-open-dot", + 24, + "diamond-wide", + 124, + "diamond-wide-open", + 224, + "diamond-wide-dot", + 324, + "diamond-wide-open-dot", + 25, + "hourglass", + 125, + "hourglass-open", + 26, + "bowtie", + 126, + "bowtie-open", + 27, + "circle-cross", + 127, + "circle-cross-open", + 28, + "circle-x", + 128, + "circle-x-open", + 29, + "square-cross", + 129, + "square-cross-open", + 30, + "square-x", + 130, + "square-x-open", + 31, + "diamond-cross", + 131, + "diamond-cross-open", + 32, + "diamond-x", + 132, + "diamond-x-open", + 33, + "cross-thin", + 133, + "cross-thin-open", + 34, + "x-thin", + 134, + "x-thin-open", + 35, + "asterisk", + 135, + "asterisk-open", + 36, + "hash", + 136, + "hash-open", + 236, + "hash-dot", + 336, + "hash-open-dot", + 37, + "y-up", + 137, + "y-up-open", + 38, + "y-down", + 138, + "y-down-open", + 39, + "y-left", + 139, + "y-left-open", + 40, + "y-right", + 140, + "y-right-open", + 41, + "line-ew", + 141, + "line-ew-open", + 42, + "line-ns", + 142, + "line-ns-open", + 43, + "line-ne", + 143, + "line-ne-open", + 44, + "line-nw", + 144, + "line-nw-open" + ], + "dflt": "circle", + "arrayOk": true, + "role": "style", + "editType": "calc", + "description": "Sets the marker symbol type. Adding 100 is equivalent to appending *-open* to a symbol name. Adding 200 is equivalent to appending *-dot* to a symbol name. Adding 300 is equivalent to appending *-open-dot* or *dot-open* to a symbol name." + }, + "opacity": { + "valType": "number", + "min": 0, + "max": 1, + "arrayOk": true, + "role": "style", + "editType": "calc", + "description": "Sets the marker opacity." + }, + "size": { + "valType": "number", + "min": 0, + "dflt": 6, + "arrayOk": true, + "role": "style", + "editType": "calc", + "description": "Sets the marker size (in px)." + }, + "sizeref": { + "valType": "number", + "dflt": 1, + "role": "style", + "editType": "calc", + "description": "Has an effect only if `marker.size` is set to a numerical array. Sets the scale factor used to determine the rendered size of marker points. Use with `sizemin` and `sizemode`." + }, + "sizemin": { + "valType": "number", + "min": 0, + "dflt": 0, + "role": "style", + "editType": "calc", + "description": "Has an effect only if `marker.size` is set to a numerical array. Sets the minimum size (in px) of the rendered marker points." + }, + "sizemode": { + "valType": "enumerated", + "values": [ + "diameter", + "area" + ], + "dflt": "diameter", + "role": "info", + "editType": "calc", + "description": "Has an effect only if `marker.size` is set to a numerical array. Sets the rule for which the data in `size` is converted to pixels." + }, + "showscale": { + "valType": "boolean", + "role": "info", + "dflt": false, + "editType": "calc", + "description": "Has an effect only if `marker.color` is set to a numerical array. Determines whether or not a colorbar is displayed." + }, + "colorbar": { + "thicknessmode": { + "valType": "enumerated", + "values": [ + "fraction", + "pixels" + ], + "role": "style", + "dflt": "pixels", + "description": "Determines whether this color bar's thickness (i.e. the measure in the constant color direction) is set in units of plot *fraction* or in *pixels*. Use `thickness` to set the value.", + "editType": "calc" + }, + "thickness": { + "valType": "number", + "role": "style", + "min": 0, + "dflt": 30, + "description": "Sets the thickness of the color bar This measure excludes the size of the padding, ticks and labels.", + "editType": "calc" + }, + "lenmode": { + "valType": "enumerated", + "values": [ + "fraction", + "pixels" + ], + "role": "info", + "dflt": "fraction", + "description": "Determines whether this color bar's length (i.e. the measure in the color variation direction) is set in units of plot *fraction* or in *pixels. Use `len` to set the value.", + "editType": "calc" + }, + "len": { + "valType": "number", + "min": 0, + "dflt": 1, + "role": "style", + "description": "Sets the length of the color bar This measure excludes the padding of both ends. That is, the color bar length is this length minus the padding on both ends.", + "editType": "calc" + }, + "x": { + "valType": "number", + "dflt": 1.02, + "min": -2, + "max": 3, + "role": "style", + "description": "Sets the x position of the color bar (in plot fraction).", + "editType": "calc" + }, + "xanchor": { + "valType": "enumerated", + "values": [ + "left", + "center", + "right" + ], + "dflt": "left", + "role": "style", + "description": "Sets this color bar's horizontal position anchor. This anchor binds the `x` position to the *left*, *center* or *right* of the color bar.", + "editType": "calc" + }, + "xpad": { + "valType": "number", + "role": "style", + "min": 0, + "dflt": 10, + "description": "Sets the amount of padding (in px) along the x direction.", + "editType": "calc" + }, + "y": { + "valType": "number", + "role": "style", + "dflt": 0.5, + "min": -2, + "max": 3, + "description": "Sets the y position of the color bar (in plot fraction).", + "editType": "calc" + }, + "yanchor": { + "valType": "enumerated", + "values": [ + "top", + "middle", + "bottom" + ], + "role": "style", + "dflt": "middle", + "description": "Sets this color bar's vertical position anchor This anchor binds the `y` position to the *top*, *middle* or *bottom* of the color bar.", + "editType": "calc" + }, + "ypad": { + "valType": "number", + "role": "style", + "min": 0, + "dflt": 10, + "description": "Sets the amount of padding (in px) along the y direction.", + "editType": "calc" + }, + "outlinecolor": { + "valType": "color", + "dflt": "#444", + "role": "style", + "editType": "calc", + "description": "Sets the axis line color." + }, + "outlinewidth": { + "valType": "number", + "min": 0, + "dflt": 1, + "role": "style", + "editType": "calc", + "description": "Sets the width (in px) of the axis line." + }, + "bordercolor": { + "valType": "color", + "dflt": "#444", + "role": "style", + "editType": "calc", + "description": "Sets the axis line color." + }, + "borderwidth": { + "valType": "number", + "role": "style", + "min": 0, + "dflt": 0, + "description": "Sets the width (in px) or the border enclosing this color bar.", + "editType": "calc" + }, + "bgcolor": { + "valType": "color", + "role": "style", + "dflt": "rgba(0,0,0,0)", + "description": "Sets the color of padded area.", + "editType": "calc" + }, + "tickmode": { + "valType": "enumerated", + "values": [ + "auto", + "linear", + "array" + ], + "role": "info", + "editType": "calc", + "impliedEdits": {}, + "description": "Sets the tick mode for this axis. If *auto*, the number of ticks is set via `nticks`. If *linear*, the placement of the ticks is determined by a starting position `tick0` and a tick step `dtick` (*linear* is the default value if `tick0` and `dtick` are provided). If *array*, the placement of the ticks is set via `tickvals` and the tick text is `ticktext`. (*array* is the default value if `tickvals` is provided)." + }, + "nticks": { + "valType": "integer", + "min": 0, + "dflt": 0, + "role": "style", + "editType": "calc", + "description": "Specifies the maximum number of ticks for the particular axis. The actual number of ticks will be chosen automatically to be less than or equal to `nticks`. Has an effect only if `tickmode` is set to *auto*." + }, + "tick0": { + "valType": "any", + "role": "style", + "editType": "calc", + "impliedEdits": { + "tickmode": "linear" + }, + "description": "Sets the placement of the first tick on this axis. Use with `dtick`. If the axis `type` is *log*, then you must take the log of your starting tick (e.g. to set the starting tick to 100, set the `tick0` to 2) except when `dtick`=*L* (see `dtick` for more info). If the axis `type` is *date*, it should be a date string, like date data. If the axis `type` is *category*, it should be a number, using the scale where each category is assigned a serial number from zero in the order it appears." + }, + "dtick": { + "valType": "any", + "role": "style", + "editType": "calc", + "impliedEdits": { + "tickmode": "linear" + }, + "description": "Sets the step in-between ticks on this axis. Use with `tick0`. Must be a positive number, or special strings available to *log* and *date* axes. If the axis `type` is *log*, then ticks are set every 10^(n*dtick) where n is the tick number. For example, to set a tick mark at 1, 10, 100, 1000, ... set dtick to 1. To set tick marks at 1, 100, 10000, ... set dtick to 2. To set tick marks at 1, 5, 25, 125, 625, 3125, ... set dtick to log_10(5), or 0.69897000433. *log* has several special values; *L*, where `f` is a positive number, gives ticks linearly spaced in value (but not position). For example `tick0` = 0.1, `dtick` = *L0.5* will put ticks at 0.1, 0.6, 1.1, 1.6 etc. To show powers of 10 plus small digits between, use *D1* (all digits) or *D2* (only 2 and 5). `tick0` is ignored for *D1* and *D2*. If the axis `type` is *date*, then you must convert the time to milliseconds. For example, to set the interval between ticks to one day, set `dtick` to 86400000.0. *date* also has special values *M* gives ticks spaced by a number of months. `n` must be a positive integer. To set ticks on the 15th of every third month, set `tick0` to *2000-01-15* and `dtick` to *M3*. To set ticks every 4 years, set `dtick` to *M48*" + }, + "tickvals": { + "valType": "data_array", + "editType": "calc", + "description": "Sets the values at which ticks on this axis appear. Only has an effect if `tickmode` is set to *array*. Used with `ticktext`.", + "role": "data" + }, + "ticktext": { + "valType": "data_array", + "editType": "calc", + "description": "Sets the text displayed at the ticks position via `tickvals`. Only has an effect if `tickmode` is set to *array*. Used with `tickvals`.", + "role": "data" + }, + "ticks": { + "valType": "enumerated", + "values": [ + "outside", + "inside", + "" + ], + "role": "style", + "editType": "calc", + "description": "Determines whether ticks are drawn or not. If **, this axis' ticks are not drawn. If *outside* (*inside*), this axis' are drawn outside (inside) the axis lines.", + "dflt": "" + }, + "ticklen": { + "valType": "number", + "min": 0, + "dflt": 5, + "role": "style", + "editType": "calc", + "description": "Sets the tick length (in px)." + }, + "tickwidth": { + "valType": "number", + "min": 0, + "dflt": 1, + "role": "style", + "editType": "calc", + "description": "Sets the tick width (in px)." + }, + "tickcolor": { + "valType": "color", + "dflt": "#444", + "role": "style", + "editType": "calc", + "description": "Sets the tick color." + }, + "showticklabels": { + "valType": "boolean", + "dflt": true, + "role": "style", + "editType": "calc", + "description": "Determines whether or not the tick labels are drawn." + }, + "tickfont": { + "family": { + "valType": "string", + "role": "style", + "noBlank": true, + "strict": true, + "description": "HTML font family - the typeface that will be applied by the web browser. The web browser will only be able to apply a font if it is available on the system which it operates. Provide multiple font families, separated by commas, to indicate the preference in which to apply fonts if they aren't available on the system. The plotly service (at https://plot.ly or on-premise) generates images on a server, where only a select number of fonts are installed and supported. These include *Arial*, *Balto*, *Courier New*, *Droid Sans*,, *Droid Serif*, *Droid Sans Mono*, *Gravitas One*, *Old Standard TT*, *Open Sans*, *Overpass*, *PT Sans Narrow*, *Raleway*, *Times New Roman*.", + "editType": "calc" + }, + "size": { + "valType": "number", + "role": "style", + "min": 1, + "editType": "calc" + }, + "color": { + "valType": "color", + "role": "style", + "editType": "calc" + }, + "description": "Sets the color bar's tick label font", + "editType": "calc", + "role": "object" + }, + "tickangle": { + "valType": "angle", + "dflt": "auto", + "role": "style", + "editType": "calc", + "description": "Sets the angle of the tick labels with respect to the horizontal. For example, a `tickangle` of -90 draws the tick labels vertically." + }, + "tickformat": { + "valType": "string", + "dflt": "", + "role": "style", + "editType": "calc", + "description": "Sets the tick label formatting rule using d3 formatting mini-languages which are very similar to those in Python. For numbers, see: https://github.com/d3/d3-format/blob/master/README.md#locale_format And for dates see: https://github.com/d3/d3-time-format/blob/master/README.md#locale_format We add one item to d3's date formatter: *%{n}f* for fractional seconds with n digits. For example, *2016-10-13 09:15:23.456* with tickformat *%H~%M~%S.%2f* would display *09~15~23.46*" + }, + "tickformatstops": { + "items": { + "tickformatstop": { + "dtickrange": { + "valType": "info_array", + "role": "info", + "items": [ + { + "valType": "any", + "editType": "calc" + }, + { + "valType": "any", + "editType": "calc" + } + ], + "editType": "calc", + "description": "range [*min*, *max*], where *min*, *max* - dtick values which describe some zoom level, it is possible to omit *min* or *max* value by passing *null*" + }, + "value": { + "valType": "string", + "dflt": "", + "role": "style", + "editType": "calc", + "description": "string - dtickformat for described zoom level, the same as *tickformat*" + }, + "editType": "calc", + "role": "object" + } + }, + "role": "object" + }, + "tickprefix": { + "valType": "string", + "dflt": "", + "role": "style", + "editType": "calc", + "description": "Sets a tick label prefix." + }, + "showtickprefix": { + "valType": "enumerated", + "values": [ + "all", + "first", + "last", + "none" + ], + "dflt": "all", + "role": "style", + "editType": "calc", + "description": "If *all*, all tick labels are displayed with a prefix. If *first*, only the first tick is displayed with a prefix. If *last*, only the last tick is displayed with a suffix. If *none*, tick prefixes are hidden." + }, + "ticksuffix": { + "valType": "string", + "dflt": "", + "role": "style", + "editType": "calc", + "description": "Sets a tick label suffix." + }, + "showticksuffix": { + "valType": "enumerated", + "values": [ + "all", + "first", + "last", + "none" + ], + "dflt": "all", + "role": "style", + "editType": "calc", + "description": "Same as `showtickprefix` but for tick suffixes." + }, + "separatethousands": { + "valType": "boolean", + "dflt": false, + "role": "style", + "editType": "calc", + "description": "If \"true\", even 4-digit integers are separated" + }, + "exponentformat": { + "valType": "enumerated", + "values": [ + "none", + "e", + "E", + "power", + "SI", + "B" + ], + "dflt": "B", + "role": "style", + "editType": "calc", + "description": "Determines a formatting rule for the tick exponents. For example, consider the number 1,000,000,000. If *none*, it appears as 1,000,000,000. If *e*, 1e+9. If *E*, 1E+9. If *power*, 1x10^9 (with 9 in a super script). If *SI*, 1G. If *B*, 1B." + }, + "showexponent": { + "valType": "enumerated", + "values": [ + "all", + "first", + "last", + "none" + ], + "dflt": "all", + "role": "style", + "editType": "calc", + "description": "If *all*, all exponents are shown besides their significands. If *first*, only the exponent of the first tick is shown. If *last*, only the exponent of the last tick is shown. If *none*, no exponents appear." + }, + "title": { + "valType": "string", + "role": "info", + "dflt": "Click to enter colorscale title", + "description": "Sets the title of the color bar.", + "editType": "calc" + }, + "titlefont": { + "family": { + "valType": "string", + "role": "style", + "noBlank": true, + "strict": true, + "description": "HTML font family - the typeface that will be applied by the web browser. The web browser will only be able to apply a font if it is available on the system which it operates. Provide multiple font families, separated by commas, to indicate the preference in which to apply fonts if they aren't available on the system. The plotly service (at https://plot.ly or on-premise) generates images on a server, where only a select number of fonts are installed and supported. These include *Arial*, *Balto*, *Courier New*, *Droid Sans*,, *Droid Serif*, *Droid Sans Mono*, *Gravitas One*, *Old Standard TT*, *Open Sans*, *Overpass*, *PT Sans Narrow*, *Raleway*, *Times New Roman*.", + "editType": "calc" + }, + "size": { + "valType": "number", + "role": "style", + "min": 1, + "editType": "calc" + }, + "color": { + "valType": "color", + "role": "style", + "editType": "calc" + }, + "description": "Sets this color bar's title font.", + "editType": "calc", + "role": "object" + }, + "titleside": { + "valType": "enumerated", + "values": [ + "right", + "top", + "bottom" + ], + "role": "style", + "dflt": "top", + "description": "Determines the location of the colorbar title with respect to the color bar.", + "editType": "calc" + }, + "editType": "calc", + "role": "object", + "tickvalssrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for tickvals .", + "editType": "none" + }, + "ticktextsrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for ticktext .", + "editType": "none" + } + }, + "line": { + "width": { + "valType": "number", + "min": 0, + "arrayOk": true, + "role": "style", + "editType": "calc", + "description": "Sets the width (in px) of the lines bounding the marker points." + }, + "color": { + "valType": "color", + "arrayOk": true, + "role": "style", + "editType": "calc", + "description": "Sets the marker.line color. It accepts either a specific color or an array of numbers that are mapped to the colorscale relative to the max and min values of the array or relative to `cmin` and `cmax` if set." + }, + "colorscale": { + "valType": "colorscale", + "role": "style", + "editType": "calc", + "impliedEdits": { + "autocolorscale": false + }, + "description": "Sets the colorscale and only has an effect if `marker.line.color` is set to a numerical array. The colorscale must be an array containing arrays mapping a normalized value to an rgb, rgba, hex, hsl, hsv, or named color string. At minimum, a mapping for the lowest (0) and highest (1) values are required. For example, `[[0, 'rgb(0,0,255)', [1, 'rgb(255,0,0)']]`. To control the bounds of the colorscale in color space, use `marker.line.cmin` and `marker.line.cmax`. Alternatively, `colorscale` may be a palette name string of the following list: Greys, YlGnBu, Greens, YlOrRd, Bluered, RdBu, Reds, Blues, Picnic, Rainbow, Portland, Jet, Hot, Blackbody, Earth, Electric, Viridis" + }, + "cauto": { + "valType": "boolean", + "role": "info", + "dflt": true, + "editType": "calc", + "impliedEdits": {}, + "description": "Has an effect only if `marker.line.color` is set to a numerical array and `cmin`, `cmax` are set by the user. In this case, it controls whether the range of colors in `colorscale` is mapped to the range of values in the `color` array (`cauto: true`), or the `cmin`/`cmax` values (`cauto: false`). Defaults to `false` when `cmin`, `cmax` are set by the user." + }, + "cmax": { + "valType": "number", + "role": "info", + "dflt": null, + "editType": "calc", + "impliedEdits": { + "cauto": false + }, + "description": "Has an effect only if `marker.line.color` is set to a numerical array. Sets the upper bound of the color domain. Value should be associated to the `marker.line.color` array index, and if set, `marker.line.cmin` must be set as well." + }, + "cmin": { + "valType": "number", + "role": "info", + "dflt": null, + "editType": "calc", + "impliedEdits": { + "cauto": false + }, + "description": "Has an effect only if `marker.line.color` is set to a numerical array. Sets the lower bound of the color domain. Value should be associated to the `marker.line.color` array index, and if set, `marker.line.cmax` must be set as well." + }, + "autocolorscale": { + "valType": "boolean", + "role": "style", + "dflt": true, + "editType": "calc", + "impliedEdits": {}, + "description": "Has an effect only if `marker.line.color` is set to a numerical array. Determines whether the colorscale is a default palette (`autocolorscale: true`) or the palette determined by `marker.line.colorscale`. In case `colorscale` is unspecified or `autocolorscale` is true, the default palette will be chosen according to whether numbers in the `color` array are all positive, all negative or mixed." + }, + "reversescale": { + "valType": "boolean", + "role": "style", + "dflt": false, + "editType": "calc", + "description": "Has an effect only if `marker.line.color` is set to a numerical array. Reverses the color mapping if true (`cmin` will correspond to the last color in the array and `cmax` will correspond to the first color)." + }, + "editType": "calc", + "role": "object", + "widthsrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for width .", + "editType": "none" + }, + "colorsrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for color .", + "editType": "none" + } + }, + "gradient": { + "type": { + "valType": "enumerated", + "values": [ + "radial", + "horizontal", + "vertical", + "none" + ], + "arrayOk": true, + "dflt": "none", + "role": "style", + "editType": "calc", + "description": "Sets the type of gradient used to fill the markers" + }, + "color": { + "valType": "color", + "arrayOk": true, + "role": "style", + "editType": "calc", + "description": "Sets the final color of the gradient fill: the center color for radial, the right for horizontal, or the bottom for vertical." + }, + "editType": "calc", + "role": "object", + "typesrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for type .", + "editType": "none" + }, + "colorsrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for color .", + "editType": "none" + } + }, + "color": { + "valType": "color", + "arrayOk": true, + "role": "style", + "editType": "calc", + "description": "Sets the marker color. It accepts either a specific color or an array of numbers that are mapped to the colorscale relative to the max and min values of the array or relative to `cmin` and `cmax` if set." + }, + "colorscale": { + "valType": "colorscale", + "role": "style", + "editType": "calc", + "impliedEdits": { + "autocolorscale": false + }, + "description": "Sets the colorscale and only has an effect if `marker.color` is set to a numerical array. The colorscale must be an array containing arrays mapping a normalized value to an rgb, rgba, hex, hsl, hsv, or named color string. At minimum, a mapping for the lowest (0) and highest (1) values are required. For example, `[[0, 'rgb(0,0,255)', [1, 'rgb(255,0,0)']]`. To control the bounds of the colorscale in color space, use `marker.cmin` and `marker.cmax`. Alternatively, `colorscale` may be a palette name string of the following list: Greys, YlGnBu, Greens, YlOrRd, Bluered, RdBu, Reds, Blues, Picnic, Rainbow, Portland, Jet, Hot, Blackbody, Earth, Electric, Viridis" + }, + "cauto": { + "valType": "boolean", + "role": "info", + "dflt": true, + "editType": "calc", + "impliedEdits": {}, + "description": "Has an effect only if `marker.color` is set to a numerical array and `cmin`, `cmax` are set by the user. In this case, it controls whether the range of colors in `colorscale` is mapped to the range of values in the `color` array (`cauto: true`), or the `cmin`/`cmax` values (`cauto: false`). Defaults to `false` when `cmin`, `cmax` are set by the user." + }, + "cmax": { + "valType": "number", + "role": "info", + "dflt": null, + "editType": "calc", + "impliedEdits": { + "cauto": false + }, + "description": "Has an effect only if `marker.color` is set to a numerical array. Sets the upper bound of the color domain. Value should be associated to the `marker.color` array index, and if set, `marker.cmin` must be set as well." + }, + "cmin": { + "valType": "number", + "role": "info", + "dflt": null, + "editType": "calc", + "impliedEdits": { + "cauto": false + }, + "description": "Has an effect only if `marker.color` is set to a numerical array. Sets the lower bound of the color domain. Value should be associated to the `marker.color` array index, and if set, `marker.cmax` must be set as well." + }, + "autocolorscale": { + "valType": "boolean", + "role": "style", + "dflt": true, + "editType": "calc", + "impliedEdits": {}, + "description": "Has an effect only if `marker.color` is set to a numerical array. Determines whether the colorscale is a default palette (`autocolorscale: true`) or the palette determined by `marker.colorscale`. In case `colorscale` is unspecified or `autocolorscale` is true, the default palette will be chosen according to whether numbers in the `color` array are all positive, all negative or mixed." + }, + "reversescale": { + "valType": "boolean", + "role": "style", + "dflt": false, + "editType": "calc", + "description": "Has an effect only if `marker.color` is set to a numerical array. Reverses the color mapping if true (`cmin` will correspond to the last color in the array and `cmax` will correspond to the first color)." + }, + "editType": "calc", + "role": "object", + "symbolsrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for symbol .", + "editType": "none" + }, + "opacitysrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for opacity .", + "editType": "none" + }, + "sizesrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for size .", + "editType": "none" + }, + "colorsrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for color .", + "editType": "none" + } + }, + "fill": { + "valType": "enumerated", + "values": [ + "none", + "toself" + ], + "dflt": "none", + "role": "style", + "description": "Sets the area to fill with a solid color. Use with `fillcolor` if not *none*. *toself* connects the endpoints of the trace (or each segment of the trace if it has gaps) into a closed shape.", + "editType": "calc" + }, + "fillcolor": { + "valType": "color", + "role": "style", + "editType": "calc", + "description": "Sets the fill color. Defaults to a half-transparent variant of the line color, marker color, or marker line color, whichever is available." + }, + "selected": { + "marker": { + "opacity": { + "valType": "number", + "min": 0, + "max": 1, + "role": "style", + "editType": "calc", + "description": "Sets the marker opacity of selected points." + }, + "color": { + "valType": "color", + "role": "style", + "editType": "calc", + "description": "Sets the marker color of selected points." + }, + "size": { + "valType": "number", + "min": 0, + "role": "style", + "editType": "calc", + "description": "Sets the marker size of selected points." + }, + "editType": "calc", + "role": "object" + }, + "textfont": { + "color": { + "valType": "color", + "role": "style", + "editType": "calc", + "description": "Sets the text font color of selected points." + }, + "editType": "calc", + "role": "object" + }, + "editType": "calc", + "role": "object" + }, + "unselected": { + "marker": { + "opacity": { + "valType": "number", + "min": 0, + "max": 1, + "role": "style", + "editType": "calc", + "description": "Sets the marker opacity of unselected points, applied only when a selection exists." + }, + "color": { + "valType": "color", + "role": "style", + "editType": "calc", + "description": "Sets the marker color of unselected points, applied only when a selection exists." + }, + "size": { + "valType": "number", + "min": 0, + "role": "style", + "editType": "calc", + "description": "Sets the marker size of unselected points, applied only when a selection exists." + }, + "editType": "calc", + "role": "object" + }, + "textfont": { + "color": { + "valType": "color", + "role": "style", + "editType": "calc", + "description": "Sets the text font color of unselected points, applied only when a selection exists." + }, + "editType": "calc", + "role": "object" + }, + "editType": "calc", + "role": "object" + }, + "geo": { + "valType": "subplotid", + "role": "info", + "dflt": "geo", + "editType": "calc", + "description": "Sets a reference between this trace's geospatial coordinates and a geographic map. If *geo* (the default value), the geospatial coordinates refer to `layout.geo`. If *geo2*, the geospatial coordinates refer to `layout.geo2`, and so on." + }, + "idssrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for ids .", + "editType": "none" + }, + "customdatasrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for customdata .", + "editType": "none" + }, + "hoverinfosrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for hoverinfo .", + "editType": "none" + }, + "lonsrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for lon .", + "editType": "none" + }, + "latsrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for lat .", + "editType": "none" + }, + "locationssrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for locations .", + "editType": "none" + }, + "textsrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for text .", + "editType": "none" + }, + "hovertextsrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for hovertext .", + "editType": "none" + }, + "textpositionsrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for textposition .", + "editType": "none" + } + } + }, + "choropleth": { + "meta": { + "description": "The data that describes the choropleth value-to-color mapping is set in `z`. The geographic locations corresponding to each value in `z` are set in `locations`." + }, + "attributes": { + "type": "choropleth", + "visible": { + "valType": "enumerated", + "values": [ + true, + false, + "legendonly" + ], + "role": "info", + "dflt": true, + "editType": "calc", + "description": "Determines whether or not this trace is visible. If *legendonly*, the trace is not drawn, but can appear as a legend item (provided that the legend itself is visible)." + }, + "showlegend": { + "valType": "boolean", + "role": "info", + "dflt": true, + "editType": "style", + "description": "Determines whether or not an item corresponding to this trace is shown in the legend." + }, + "legendgroup": { + "valType": "string", + "role": "info", + "dflt": "", + "editType": "style", + "description": "Sets the legend group for this trace. Traces part of the same legend group hide/show at the same time when toggling legend items." + }, + "opacity": { + "valType": "number", + "role": "style", + "min": 0, + "max": 1, + "dflt": 1, + "editType": "style", + "description": "Sets the opacity of the trace." + }, + "name": { + "valType": "string", + "role": "info", + "editType": "style", + "description": "Sets the trace name. The trace name appear as the legend item and on hover." + }, + "uid": { + "valType": "string", + "role": "info", + "dflt": "", + "editType": "calc" + }, + "ids": { + "valType": "data_array", + "editType": "calc", + "description": "Assigns id labels to each datum. These ids for object constancy of data points during animation.", + "role": "data" + }, + "customdata": { + "valType": "data_array", + "editType": "calc", + "description": "Assigns extra data each datum. This may be useful when listening to hover, click and selection events. Note that, *scatter* traces also appends customdata items in the markers DOM elements", + "role": "data" + }, + "selectedpoints": { + "valType": "any", + "role": "info", + "editType": "calc", + "description": "Array containing integer indices of selected points. Has an effect only for traces that support selections. Note that an empty array means an empty selection where the `unselected` are turned on for all points, whereas, any other non-array values means no selection all where the `selected` and `unselected` styles have no effect." + }, + "hoverinfo": { + "valType": "flaglist", + "role": "info", + "flags": [ + "location", + "z", + "text", + "name", + "name" + ], + "extras": [ + "all", + "none", + "skip" + ], + "arrayOk": true, + "dflt": "all", + "editType": "calc", + "description": "Determines which trace information appear on hover. If `none` or `skip` are set, no information is displayed upon hovering. But, if `none` is set, click and hover events are still fired." + }, + "hoverlabel": { + "bgcolor": { + "valType": "color", + "role": "style", + "arrayOk": true, + "editType": "none", + "description": "Sets the background color of the hover labels for this trace" + }, + "bordercolor": { + "valType": "color", + "role": "style", + "arrayOk": true, + "editType": "none", + "description": "Sets the border color of the hover labels for this trace." + }, + "font": { + "family": { + "valType": "string", + "role": "style", + "noBlank": true, + "strict": true, + "editType": "none", + "description": "HTML font family - the typeface that will be applied by the web browser. The web browser will only be able to apply a font if it is available on the system which it operates. Provide multiple font families, separated by commas, to indicate the preference in which to apply fonts if they aren't available on the system. The plotly service (at https://plot.ly or on-premise) generates images on a server, where only a select number of fonts are installed and supported. These include *Arial*, *Balto*, *Courier New*, *Droid Sans*,, *Droid Serif*, *Droid Sans Mono*, *Gravitas One*, *Old Standard TT*, *Open Sans*, *Overpass*, *PT Sans Narrow*, *Raleway*, *Times New Roman*.", + "arrayOk": true + }, + "size": { + "valType": "number", + "role": "style", + "min": 1, + "editType": "none", + "arrayOk": true + }, + "color": { + "valType": "color", + "role": "style", + "editType": "none", + "arrayOk": true + }, + "editType": "none", + "description": "Sets the font used in hover labels.", + "role": "object", + "familysrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for family .", + "editType": "none" + }, + "sizesrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for size .", + "editType": "none" + }, + "colorsrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for color .", + "editType": "none" + } + }, + "namelength": { + "valType": "integer", + "min": -1, + "arrayOk": true, + "role": "style", + "editType": "none", + "description": "Sets the length (in number of characters) of the trace name in the hover labels for this trace. -1 shows the whole name regardless of length. 0-3 shows the first 0-3 characters, and an integer >3 will show the whole name if it is less than that many characters, but if it is longer, will truncate to `namelength - 3` characters and add an ellipsis." + }, + "editType": "calc", + "role": "object", + "bgcolorsrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for bgcolor .", + "editType": "none" + }, + "bordercolorsrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for bordercolor .", + "editType": "none" + }, + "namelengthsrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for namelength .", + "editType": "none" + } + }, + "stream": { + "token": { + "valType": "string", + "noBlank": true, + "strict": true, + "role": "info", + "editType": "calc", + "description": "The stream id number links a data trace on a plot with a stream. See https://plot.ly/settings for more details." + }, + "maxpoints": { + "valType": "number", + "min": 0, + "max": 10000, + "dflt": 500, + "role": "info", + "editType": "calc", + "description": "Sets the maximum number of points to keep on the plots from an incoming stream. If `maxpoints` is set to *50*, only the newest 50 points will be displayed on the plot." + }, + "editType": "calc", + "role": "object" + }, + "locations": { + "valType": "data_array", + "editType": "calc", + "description": "Sets the coordinates via location IDs or names. See `locationmode` for more info.", + "role": "data" + }, + "locationmode": { + "valType": "enumerated", + "values": [ + "ISO-3", + "USA-states", + "country names" + ], + "role": "info", + "dflt": "ISO-3", + "description": "Determines the set of locations used to match entries in `locations` to regions on the map.", + "editType": "calc" + }, + "z": { + "valType": "data_array", + "editType": "calc", + "description": "Sets the color values.", + "role": "data" + }, + "text": { + "valType": "string", + "role": "info", + "dflt": "", + "arrayOk": true, + "editType": "calc", + "description": "Sets the text elements associated with each location." + }, + "marker": { + "line": { + "color": { + "valType": "color", + "arrayOk": true, + "role": "style", + "editType": "calc", + "description": "Sets the marker.line color. It accepts either a specific color or an array of numbers that are mapped to the colorscale relative to the max and min values of the array or relative to `cmin` and `cmax` if set." + }, + "width": { + "valType": "number", + "min": 0, + "arrayOk": true, + "role": "style", + "editType": "calc", + "description": "Sets the width (in px) of the lines bounding the marker points.", + "dflt": 1 + }, + "editType": "calc", + "role": "object", + "colorsrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for color .", + "editType": "none" + }, + "widthsrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for width .", + "editType": "none" + } + }, + "opacity": { + "valType": "number", + "arrayOk": true, + "min": 0, + "max": 1, + "dflt": 1, + "role": "style", + "editType": "style", + "description": "Sets the opacity of the locations." + }, + "editType": "calc", + "role": "object", + "opacitysrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for opacity .", + "editType": "none" + } + }, + "selected": { + "marker": { + "opacity": { + "valType": "number", + "min": 0, + "max": 1, + "role": "style", + "editType": "calc", + "description": "Sets the marker opacity of selected points." + }, + "editType": "plot", + "role": "object" + }, + "editType": "plot", + "role": "object" + }, + "unselected": { + "marker": { + "opacity": { + "valType": "number", + "min": 0, + "max": 1, + "role": "style", + "editType": "calc", + "description": "Sets the marker opacity of unselected points, applied only when a selection exists." + }, + "editType": "plot", + "role": "object" + }, + "editType": "plot", + "role": "object" + }, + "zauto": { + "valType": "boolean", + "role": "info", + "dflt": true, + "editType": "calc", + "impliedEdits": {}, + "description": "Determines the whether or not the color domain is computed with respect to the input data." + }, + "zmin": { + "valType": "number", + "role": "info", + "dflt": null, + "editType": "calc", + "impliedEdits": { + "zauto": false + }, + "description": "Sets the lower bound of color domain." + }, + "zmax": { + "valType": "number", + "role": "info", + "dflt": null, + "editType": "calc", + "impliedEdits": { + "zauto": false + }, + "description": "Sets the upper bound of color domain." + }, + "colorscale": { + "valType": "colorscale", + "role": "style", + "editType": "calc", + "impliedEdits": { + "autocolorscale": false + }, + "description": "Sets the colorscale. The colorscale must be an array containing arrays mapping a normalized value to an rgb, rgba, hex, hsl, hsv, or named color string. At minimum, a mapping for the lowest (0) and highest (1) values are required. For example, `[[0, 'rgb(0,0,255)', [1, 'rgb(255,0,0)']]`. To control the bounds of the colorscale in z space, use zmin and zmax" + }, + "autocolorscale": { + "valType": "boolean", + "role": "style", + "dflt": true, + "editType": "calc", + "impliedEdits": {}, + "description": "Determines whether or not the colorscale is picked using the sign of the input z values." + }, + "reversescale": { + "valType": "boolean", + "role": "style", + "dflt": false, + "editType": "calc", + "description": "Reverses the colorscale." + }, + "showscale": { + "valType": "boolean", + "role": "info", + "dflt": true, + "editType": "calc", + "description": "Determines whether or not a colorbar is displayed for this trace." + }, + "colorbar": { + "thicknessmode": { + "valType": "enumerated", + "values": [ + "fraction", + "pixels" + ], + "role": "style", + "dflt": "pixels", + "description": "Determines whether this color bar's thickness (i.e. the measure in the constant color direction) is set in units of plot *fraction* or in *pixels*. Use `thickness` to set the value.", + "editType": "colorbars" + }, + "thickness": { + "valType": "number", + "role": "style", + "min": 0, + "dflt": 30, + "description": "Sets the thickness of the color bar This measure excludes the size of the padding, ticks and labels.", + "editType": "colorbars" + }, + "lenmode": { + "valType": "enumerated", + "values": [ + "fraction", + "pixels" + ], + "role": "info", + "dflt": "fraction", + "description": "Determines whether this color bar's length (i.e. the measure in the color variation direction) is set in units of plot *fraction* or in *pixels. Use `len` to set the value.", + "editType": "colorbars" + }, + "len": { + "valType": "number", + "min": 0, + "dflt": 1, + "role": "style", + "description": "Sets the length of the color bar This measure excludes the padding of both ends. That is, the color bar length is this length minus the padding on both ends.", + "editType": "colorbars" + }, + "x": { + "valType": "number", + "dflt": 1.02, + "min": -2, + "max": 3, + "role": "style", + "description": "Sets the x position of the color bar (in plot fraction).", + "editType": "colorbars" + }, + "xanchor": { + "valType": "enumerated", + "values": [ + "left", + "center", + "right" + ], + "dflt": "left", + "role": "style", + "description": "Sets this color bar's horizontal position anchor. This anchor binds the `x` position to the *left*, *center* or *right* of the color bar.", + "editType": "colorbars" + }, + "xpad": { + "valType": "number", + "role": "style", + "min": 0, + "dflt": 10, + "description": "Sets the amount of padding (in px) along the x direction.", + "editType": "colorbars" + }, + "y": { + "valType": "number", + "role": "style", + "dflt": 0.5, + "min": -2, + "max": 3, + "description": "Sets the y position of the color bar (in plot fraction).", + "editType": "colorbars" + }, + "yanchor": { + "valType": "enumerated", + "values": [ + "top", + "middle", + "bottom" + ], + "role": "style", + "dflt": "middle", + "description": "Sets this color bar's vertical position anchor This anchor binds the `y` position to the *top*, *middle* or *bottom* of the color bar.", + "editType": "colorbars" + }, + "ypad": { + "valType": "number", + "role": "style", + "min": 0, + "dflt": 10, + "description": "Sets the amount of padding (in px) along the y direction.", + "editType": "colorbars" + }, + "outlinecolor": { + "valType": "color", + "dflt": "#444", + "role": "style", + "editType": "colorbars", + "description": "Sets the axis line color." + }, + "outlinewidth": { + "valType": "number", + "min": 0, + "dflt": 1, + "role": "style", + "editType": "colorbars", + "description": "Sets the width (in px) of the axis line." + }, + "bordercolor": { + "valType": "color", + "dflt": "#444", + "role": "style", + "editType": "colorbars", + "description": "Sets the axis line color." + }, + "borderwidth": { + "valType": "number", + "role": "style", + "min": 0, + "dflt": 0, + "description": "Sets the width (in px) or the border enclosing this color bar.", + "editType": "colorbars" + }, + "bgcolor": { + "valType": "color", + "role": "style", + "dflt": "rgba(0,0,0,0)", + "description": "Sets the color of padded area.", + "editType": "colorbars" + }, + "tickmode": { + "valType": "enumerated", + "values": [ + "auto", + "linear", + "array" + ], + "role": "info", + "editType": "colorbars", + "impliedEdits": {}, + "description": "Sets the tick mode for this axis. If *auto*, the number of ticks is set via `nticks`. If *linear*, the placement of the ticks is determined by a starting position `tick0` and a tick step `dtick` (*linear* is the default value if `tick0` and `dtick` are provided). If *array*, the placement of the ticks is set via `tickvals` and the tick text is `ticktext`. (*array* is the default value if `tickvals` is provided)." + }, + "nticks": { + "valType": "integer", + "min": 0, + "dflt": 0, + "role": "style", + "editType": "colorbars", + "description": "Specifies the maximum number of ticks for the particular axis. The actual number of ticks will be chosen automatically to be less than or equal to `nticks`. Has an effect only if `tickmode` is set to *auto*." + }, + "tick0": { + "valType": "any", + "role": "style", + "editType": "colorbars", + "impliedEdits": { + "tickmode": "linear" + }, + "description": "Sets the placement of the first tick on this axis. Use with `dtick`. If the axis `type` is *log*, then you must take the log of your starting tick (e.g. to set the starting tick to 100, set the `tick0` to 2) except when `dtick`=*L* (see `dtick` for more info). If the axis `type` is *date*, it should be a date string, like date data. If the axis `type` is *category*, it should be a number, using the scale where each category is assigned a serial number from zero in the order it appears." + }, + "dtick": { + "valType": "any", + "role": "style", + "editType": "colorbars", + "impliedEdits": { + "tickmode": "linear" + }, + "description": "Sets the step in-between ticks on this axis. Use with `tick0`. Must be a positive number, or special strings available to *log* and *date* axes. If the axis `type` is *log*, then ticks are set every 10^(n*dtick) where n is the tick number. For example, to set a tick mark at 1, 10, 100, 1000, ... set dtick to 1. To set tick marks at 1, 100, 10000, ... set dtick to 2. To set tick marks at 1, 5, 25, 125, 625, 3125, ... set dtick to log_10(5), or 0.69897000433. *log* has several special values; *L*, where `f` is a positive number, gives ticks linearly spaced in value (but not position). For example `tick0` = 0.1, `dtick` = *L0.5* will put ticks at 0.1, 0.6, 1.1, 1.6 etc. To show powers of 10 plus small digits between, use *D1* (all digits) or *D2* (only 2 and 5). `tick0` is ignored for *D1* and *D2*. If the axis `type` is *date*, then you must convert the time to milliseconds. For example, to set the interval between ticks to one day, set `dtick` to 86400000.0. *date* also has special values *M* gives ticks spaced by a number of months. `n` must be a positive integer. To set ticks on the 15th of every third month, set `tick0` to *2000-01-15* and `dtick` to *M3*. To set ticks every 4 years, set `dtick` to *M48*" + }, + "tickvals": { + "valType": "data_array", + "editType": "colorbars", + "description": "Sets the values at which ticks on this axis appear. Only has an effect if `tickmode` is set to *array*. Used with `ticktext`.", + "role": "data" + }, + "ticktext": { + "valType": "data_array", + "editType": "colorbars", + "description": "Sets the text displayed at the ticks position via `tickvals`. Only has an effect if `tickmode` is set to *array*. Used with `tickvals`.", + "role": "data" + }, + "ticks": { + "valType": "enumerated", + "values": [ + "outside", + "inside", + "" + ], + "role": "style", + "editType": "colorbars", + "description": "Determines whether ticks are drawn or not. If **, this axis' ticks are not drawn. If *outside* (*inside*), this axis' are drawn outside (inside) the axis lines.", + "dflt": "" + }, + "ticklen": { + "valType": "number", + "min": 0, + "dflt": 5, + "role": "style", + "editType": "colorbars", + "description": "Sets the tick length (in px)." + }, + "tickwidth": { + "valType": "number", + "min": 0, + "dflt": 1, + "role": "style", + "editType": "colorbars", + "description": "Sets the tick width (in px)." + }, + "tickcolor": { + "valType": "color", + "dflt": "#444", + "role": "style", + "editType": "colorbars", + "description": "Sets the tick color." + }, + "showticklabels": { + "valType": "boolean", + "dflt": true, + "role": "style", + "editType": "colorbars", + "description": "Determines whether or not the tick labels are drawn." + }, + "tickfont": { + "family": { + "valType": "string", + "role": "style", + "noBlank": true, + "strict": true, + "description": "HTML font family - the typeface that will be applied by the web browser. The web browser will only be able to apply a font if it is available on the system which it operates. Provide multiple font families, separated by commas, to indicate the preference in which to apply fonts if they aren't available on the system. The plotly service (at https://plot.ly or on-premise) generates images on a server, where only a select number of fonts are installed and supported. These include *Arial*, *Balto*, *Courier New*, *Droid Sans*,, *Droid Serif*, *Droid Sans Mono*, *Gravitas One*, *Old Standard TT*, *Open Sans*, *Overpass*, *PT Sans Narrow*, *Raleway*, *Times New Roman*.", + "editType": "colorbars" + }, + "size": { + "valType": "number", + "role": "style", + "min": 1, + "editType": "colorbars" + }, + "color": { + "valType": "color", + "role": "style", + "editType": "colorbars" + }, + "description": "Sets the color bar's tick label font", + "editType": "colorbars", + "role": "object" + }, + "tickangle": { + "valType": "angle", + "dflt": "auto", + "role": "style", + "editType": "colorbars", + "description": "Sets the angle of the tick labels with respect to the horizontal. For example, a `tickangle` of -90 draws the tick labels vertically." + }, + "tickformat": { + "valType": "string", + "dflt": "", + "role": "style", + "editType": "colorbars", + "description": "Sets the tick label formatting rule using d3 formatting mini-languages which are very similar to those in Python. For numbers, see: https://github.com/d3/d3-format/blob/master/README.md#locale_format And for dates see: https://github.com/d3/d3-time-format/blob/master/README.md#locale_format We add one item to d3's date formatter: *%{n}f* for fractional seconds with n digits. For example, *2016-10-13 09:15:23.456* with tickformat *%H~%M~%S.%2f* would display *09~15~23.46*" + }, + "tickformatstops": { + "items": { + "tickformatstop": { + "dtickrange": { + "valType": "info_array", + "role": "info", + "items": [ + { + "valType": "any", + "editType": "colorbars" + }, + { + "valType": "any", + "editType": "colorbars" + } + ], + "editType": "colorbars", + "description": "range [*min*, *max*], where *min*, *max* - dtick values which describe some zoom level, it is possible to omit *min* or *max* value by passing *null*" + }, + "value": { + "valType": "string", + "dflt": "", + "role": "style", + "editType": "colorbars", + "description": "string - dtickformat for described zoom level, the same as *tickformat*" + }, + "editType": "colorbars", + "role": "object" + } + }, + "role": "object" + }, + "tickprefix": { + "valType": "string", + "dflt": "", + "role": "style", + "editType": "colorbars", + "description": "Sets a tick label prefix." + }, + "showtickprefix": { + "valType": "enumerated", + "values": [ + "all", + "first", + "last", + "none" + ], + "dflt": "all", + "role": "style", + "editType": "colorbars", + "description": "If *all*, all tick labels are displayed with a prefix. If *first*, only the first tick is displayed with a prefix. If *last*, only the last tick is displayed with a suffix. If *none*, tick prefixes are hidden." + }, + "ticksuffix": { + "valType": "string", + "dflt": "", + "role": "style", + "editType": "colorbars", + "description": "Sets a tick label suffix." + }, + "showticksuffix": { + "valType": "enumerated", + "values": [ + "all", + "first", + "last", + "none" + ], + "dflt": "all", + "role": "style", + "editType": "colorbars", + "description": "Same as `showtickprefix` but for tick suffixes." + }, + "separatethousands": { + "valType": "boolean", + "dflt": false, + "role": "style", + "editType": "colorbars", + "description": "If \"true\", even 4-digit integers are separated" + }, + "exponentformat": { + "valType": "enumerated", + "values": [ + "none", + "e", + "E", + "power", + "SI", + "B" + ], + "dflt": "B", + "role": "style", + "editType": "colorbars", + "description": "Determines a formatting rule for the tick exponents. For example, consider the number 1,000,000,000. If *none*, it appears as 1,000,000,000. If *e*, 1e+9. If *E*, 1E+9. If *power*, 1x10^9 (with 9 in a super script). If *SI*, 1G. If *B*, 1B." + }, + "showexponent": { + "valType": "enumerated", + "values": [ + "all", + "first", + "last", + "none" + ], + "dflt": "all", + "role": "style", + "editType": "colorbars", + "description": "If *all*, all exponents are shown besides their significands. If *first*, only the exponent of the first tick is shown. If *last*, only the exponent of the last tick is shown. If *none*, no exponents appear." + }, + "title": { + "valType": "string", + "role": "info", + "dflt": "Click to enter colorscale title", + "description": "Sets the title of the color bar.", + "editType": "colorbars" + }, + "titlefont": { + "family": { + "valType": "string", + "role": "style", + "noBlank": true, + "strict": true, + "description": "HTML font family - the typeface that will be applied by the web browser. The web browser will only be able to apply a font if it is available on the system which it operates. Provide multiple font families, separated by commas, to indicate the preference in which to apply fonts if they aren't available on the system. The plotly service (at https://plot.ly or on-premise) generates images on a server, where only a select number of fonts are installed and supported. These include *Arial*, *Balto*, *Courier New*, *Droid Sans*,, *Droid Serif*, *Droid Sans Mono*, *Gravitas One*, *Old Standard TT*, *Open Sans*, *Overpass*, *PT Sans Narrow*, *Raleway*, *Times New Roman*.", + "editType": "colorbars" + }, + "size": { + "valType": "number", + "role": "style", + "min": 1, + "editType": "colorbars" + }, + "color": { + "valType": "color", + "role": "style", + "editType": "colorbars" + }, + "description": "Sets this color bar's title font.", + "editType": "colorbars", + "role": "object" + }, + "titleside": { + "valType": "enumerated", + "values": [ + "right", + "top", + "bottom" + ], + "role": "style", + "dflt": "top", + "description": "Determines the location of the colorbar title with respect to the color bar.", + "editType": "colorbars" + }, + "editType": "colorbars", + "role": "object", + "tickvalssrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for tickvals .", + "editType": "none" + }, + "ticktextsrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for ticktext .", + "editType": "none" + } + }, + "geo": { + "valType": "subplotid", + "role": "info", + "dflt": "geo", + "editType": "calc", + "description": "Sets a reference between this trace's geospatial coordinates and a geographic map. If *geo* (the default value), the geospatial coordinates refer to `layout.geo`. If *geo2*, the geospatial coordinates refer to `layout.geo2`, and so on." + }, + "idssrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for ids .", + "editType": "none" + }, + "customdatasrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for customdata .", + "editType": "none" + }, + "hoverinfosrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for hoverinfo .", + "editType": "none" + }, + "locationssrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for locations .", + "editType": "none" + }, + "zsrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for z .", + "editType": "none" + }, + "textsrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for text .", + "editType": "none" + } + } + }, + "scattergl": { + "meta": { + "description": "The data visualized as scatter point or lines is set in `x` and `y` using the WebGl plotting engine. Bubble charts are achieved by setting `marker.size` and/or `marker.color` to a numerical arrays." + }, + "attributes": { + "type": "scattergl", + "visible": { + "valType": "enumerated", + "values": [ + true, + false, + "legendonly" + ], + "role": "info", + "dflt": true, + "editType": "calc", + "description": "Determines whether or not this trace is visible. If *legendonly*, the trace is not drawn, but can appear as a legend item (provided that the legend itself is visible)." + }, + "showlegend": { + "valType": "boolean", + "role": "info", + "dflt": true, + "editType": "style", + "description": "Determines whether or not an item corresponding to this trace is shown in the legend." + }, + "legendgroup": { + "valType": "string", + "role": "info", + "dflt": "", + "editType": "style", + "description": "Sets the legend group for this trace. Traces part of the same legend group hide/show at the same time when toggling legend items." + }, + "opacity": { + "valType": "number", + "role": "style", + "min": 0, + "max": 1, + "dflt": 1, + "editType": "style", + "description": "Sets the opacity of the trace." + }, + "name": { + "valType": "string", + "role": "info", + "editType": "style", + "description": "Sets the trace name. The trace name appear as the legend item and on hover." + }, + "uid": { + "valType": "string", + "role": "info", + "dflt": "", + "editType": "calc" + }, + "ids": { + "valType": "data_array", + "editType": "calc", + "description": "Assigns id labels to each datum. These ids for object constancy of data points during animation.", + "role": "data" + }, + "customdata": { + "valType": "data_array", + "editType": "calc", + "description": "Assigns extra data each datum. This may be useful when listening to hover, click and selection events. Note that, *scatter* traces also appends customdata items in the markers DOM elements", + "role": "data" + }, + "selectedpoints": { + "valType": "any", + "role": "info", + "editType": "calc", + "description": "Array containing integer indices of selected points. Has an effect only for traces that support selections. Note that an empty array means an empty selection where the `unselected` are turned on for all points, whereas, any other non-array values means no selection all where the `selected` and `unselected` styles have no effect." + }, + "hoverinfo": { + "valType": "flaglist", + "role": "info", + "flags": [ + "x", + "y", + "z", + "text", + "name" + ], + "extras": [ + "all", + "none", + "skip" + ], + "arrayOk": true, + "dflt": "all", + "editType": "none", + "description": "Determines which trace information appear on hover. If `none` or `skip` are set, no information is displayed upon hovering. But, if `none` is set, click and hover events are still fired." + }, + "hoverlabel": { + "bgcolor": { + "valType": "color", + "role": "style", + "arrayOk": true, + "editType": "none", + "description": "Sets the background color of the hover labels for this trace" + }, + "bordercolor": { + "valType": "color", + "role": "style", + "arrayOk": true, + "editType": "none", + "description": "Sets the border color of the hover labels for this trace." + }, + "font": { + "family": { + "valType": "string", + "role": "style", + "noBlank": true, + "strict": true, + "editType": "none", + "description": "HTML font family - the typeface that will be applied by the web browser. The web browser will only be able to apply a font if it is available on the system which it operates. Provide multiple font families, separated by commas, to indicate the preference in which to apply fonts if they aren't available on the system. The plotly service (at https://plot.ly or on-premise) generates images on a server, where only a select number of fonts are installed and supported. These include *Arial*, *Balto*, *Courier New*, *Droid Sans*,, *Droid Serif*, *Droid Sans Mono*, *Gravitas One*, *Old Standard TT*, *Open Sans*, *Overpass*, *PT Sans Narrow*, *Raleway*, *Times New Roman*.", + "arrayOk": true + }, + "size": { + "valType": "number", + "role": "style", + "min": 1, + "editType": "none", + "arrayOk": true + }, + "color": { + "valType": "color", + "role": "style", + "editType": "none", + "arrayOk": true + }, + "editType": "none", + "description": "Sets the font used in hover labels.", + "role": "object", + "familysrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for family .", + "editType": "none" + }, + "sizesrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for size .", + "editType": "none" + }, + "colorsrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for color .", + "editType": "none" + } + }, + "namelength": { + "valType": "integer", + "min": -1, + "arrayOk": true, + "role": "style", + "editType": "none", + "description": "Sets the length (in number of characters) of the trace name in the hover labels for this trace. -1 shows the whole name regardless of length. 0-3 shows the first 0-3 characters, and an integer >3 will show the whole name if it is less than that many characters, but if it is longer, will truncate to `namelength - 3` characters and add an ellipsis." + }, + "editType": "calc", + "role": "object", + "bgcolorsrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for bgcolor .", + "editType": "none" + }, + "bordercolorsrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for bordercolor .", + "editType": "none" + }, + "namelengthsrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for namelength .", + "editType": "none" + } + }, + "stream": { + "token": { + "valType": "string", + "noBlank": true, + "strict": true, + "role": "info", + "editType": "calc", + "description": "The stream id number links a data trace on a plot with a stream. See https://plot.ly/settings for more details." + }, + "maxpoints": { + "valType": "number", + "min": 0, + "max": 10000, + "dflt": 500, + "role": "info", + "editType": "calc", + "description": "Sets the maximum number of points to keep on the plots from an incoming stream. If `maxpoints` is set to *50*, only the newest 50 points will be displayed on the plot." + }, + "editType": "calc", + "role": "object" + }, + "x": { + "valType": "data_array", + "editType": "calc+clearAxisTypes", + "description": "Sets the x coordinates.", + "role": "data" + }, + "x0": { + "valType": "any", + "dflt": 0, + "role": "info", + "editType": "calc+clearAxisTypes", + "description": "Alternate to `x`. Builds a linear space of x coordinates. Use with `dx` where `x0` is the starting coordinate and `dx` the step." + }, + "dx": { + "valType": "number", + "dflt": 1, + "role": "info", + "editType": "calc", + "description": "Sets the x coordinate step. See `x0` for more info." + }, + "y": { + "valType": "data_array", + "editType": "calc+clearAxisTypes", + "description": "Sets the y coordinates.", + "role": "data" + }, + "y0": { + "valType": "any", + "dflt": 0, + "role": "info", + "editType": "calc+clearAxisTypes", + "description": "Alternate to `y`. Builds a linear space of y coordinates. Use with `dy` where `y0` is the starting coordinate and `dy` the step." + }, + "dy": { + "valType": "number", + "dflt": 1, + "role": "info", + "editType": "calc", + "description": "Sets the y coordinate step. See `y0` for more info." + }, + "text": { + "valType": "string", + "role": "info", + "dflt": "", + "arrayOk": true, + "editType": "calc", + "description": "Sets text elements associated with each (x,y) pair to appear on hover. If a single string, the same string appears over all the data points. If an array of string, the items are mapped in order to the this trace's (x,y) coordinates." + }, + "mode": { + "valType": "flaglist", + "flags": [ + "lines", + "markers" + ], + "extras": [ + "none" + ], + "role": "info", + "description": "Determines the drawing mode for this scatter trace.", + "editType": "calc" + }, + "line": { + "color": { + "valType": "color", + "role": "style", + "editType": "calc", + "description": "Sets the line color." + }, + "width": { + "valType": "number", + "min": 0, + "dflt": 2, + "role": "style", + "editType": "calc", + "description": "Sets the line width (in px)." + }, + "dash": { + "valType": "enumerated", + "values": [ + "solid", + "dot", + "dash", + "longdash", + "dashdot", + "longdashdot" + ], + "dflt": "solid", + "role": "style", + "description": "Sets the style of the lines.", + "editType": "calc" + }, + "editType": "calc", + "role": "object" + }, + "marker": { + "color": { + "valType": "color", + "arrayOk": true, + "role": "style", + "editType": "calc", + "description": "Sets the marker color. It accepts either a specific color or an array of numbers that are mapped to the colorscale relative to the max and min values of the array or relative to `cmin` and `cmax` if set." + }, + "colorscale": { + "valType": "colorscale", + "role": "style", + "editType": "calc", + "impliedEdits": { + "autocolorscale": false + }, + "description": "Sets the colorscale and only has an effect if `marker.color` is set to a numerical array. The colorscale must be an array containing arrays mapping a normalized value to an rgb, rgba, hex, hsl, hsv, or named color string. At minimum, a mapping for the lowest (0) and highest (1) values are required. For example, `[[0, 'rgb(0,0,255)', [1, 'rgb(255,0,0)']]`. To control the bounds of the colorscale in color space, use `marker.cmin` and `marker.cmax`. Alternatively, `colorscale` may be a palette name string of the following list: Greys, YlGnBu, Greens, YlOrRd, Bluered, RdBu, Reds, Blues, Picnic, Rainbow, Portland, Jet, Hot, Blackbody, Earth, Electric, Viridis" + }, + "cauto": { + "valType": "boolean", + "role": "info", + "dflt": true, + "editType": "calc", + "impliedEdits": {}, + "description": "Has an effect only if `marker.color` is set to a numerical array and `cmin`, `cmax` are set by the user. In this case, it controls whether the range of colors in `colorscale` is mapped to the range of values in the `color` array (`cauto: true`), or the `cmin`/`cmax` values (`cauto: false`). Defaults to `false` when `cmin`, `cmax` are set by the user." + }, + "cmax": { + "valType": "number", + "role": "info", + "dflt": null, + "editType": "calc", + "impliedEdits": { + "cauto": false + }, + "description": "Has an effect only if `marker.color` is set to a numerical array. Sets the upper bound of the color domain. Value should be associated to the `marker.color` array index, and if set, `marker.cmin` must be set as well." + }, + "cmin": { + "valType": "number", + "role": "info", + "dflt": null, + "editType": "calc", + "impliedEdits": { + "cauto": false + }, + "description": "Has an effect only if `marker.color` is set to a numerical array. Sets the lower bound of the color domain. Value should be associated to the `marker.color` array index, and if set, `marker.cmax` must be set as well." + }, + "autocolorscale": { + "valType": "boolean", + "role": "style", + "dflt": true, + "editType": "calc", + "impliedEdits": {}, + "description": "Has an effect only if `marker.color` is set to a numerical array. Determines whether the colorscale is a default palette (`autocolorscale: true`) or the palette determined by `marker.colorscale`. In case `colorscale` is unspecified or `autocolorscale` is true, the default palette will be chosen according to whether numbers in the `color` array are all positive, all negative or mixed." + }, + "reversescale": { + "valType": "boolean", + "role": "style", + "dflt": false, + "editType": "calc", + "description": "Has an effect only if `marker.color` is set to a numerical array. Reverses the color mapping if true (`cmin` will correspond to the last color in the array and `cmax` will correspond to the first color)." + }, + "symbol": { + "valType": "enumerated", + "values": [ + "circle", + "square", + "diamond", + "cross", + "x", + "triangle-up", + "triangle-down", + "triangle-left", + "triangle-right", + "triangle-ne", + "triangle-nw", + "triangle-se", + "triangle-sw", + "pentagon", + "hexagon", + "hexagon2", + "star", + "diamond-tall", + "bowtie", + "diamond-x", + "cross-thin", + "asterisk", + "y-up", + "y-down", + "line-ew", + "line-ns", + "circle-open", + "square-open", + "diamond-open", + "cross-open", + "x-open", + "triangle-up-open", + "triangle-down-open", + "triangle-left-open", + "triangle-right-open", + "triangle-ne-open", + "triangle-nw-open", + "triangle-se-open", + "triangle-sw-open", + "pentagon-open", + "hexagon-open", + "hexagon2-open", + "star-open", + "diamond-tall-open", + "bowtie-open", + "diamond-x-open", + "cross-thin-open", + "asterisk-open", + "y-up-open", + "y-down-open", + "line-ew-open", + "line-ns-open", + "circle-cross-open", + "circle-x-open", + "square-cross-open", + "square-x-open" + ], + "dflt": "circle", + "arrayOk": true, + "role": "style", + "description": "Sets the marker symbol type.", + "editType": "calc" + }, + "size": { + "valType": "number", + "min": 0, + "dflt": 6, + "arrayOk": true, + "role": "style", + "editType": "calc", + "description": "Sets the marker size (in px)." + }, + "sizeref": { + "valType": "number", + "dflt": 1, + "role": "style", + "editType": "calc", + "description": "Has an effect only if `marker.size` is set to a numerical array. Sets the scale factor used to determine the rendered size of marker points. Use with `sizemin` and `sizemode`." + }, + "sizemin": { + "valType": "number", + "min": 0, + "dflt": 0, + "role": "style", + "editType": "calc", + "description": "Has an effect only if `marker.size` is set to a numerical array. Sets the minimum size (in px) of the rendered marker points." + }, + "sizemode": { + "valType": "enumerated", + "values": [ + "diameter", + "area" + ], + "dflt": "diameter", + "role": "info", + "editType": "calc", + "description": "Has an effect only if `marker.size` is set to a numerical array. Sets the rule for which the data in `size` is converted to pixels." + }, + "opacity": { + "valType": "number", + "min": 0, + "max": 1, + "arrayOk": true, + "role": "style", + "editType": "calc", + "description": "Sets the marker opacity." + }, + "showscale": { + "valType": "boolean", + "role": "info", + "dflt": false, + "editType": "calc", + "description": "Has an effect only if `marker.color` is set to a numerical array. Determines whether or not a colorbar is displayed." + }, + "colorbar": { + "thicknessmode": { + "valType": "enumerated", + "values": [ + "fraction", + "pixels" + ], + "role": "style", + "dflt": "pixels", + "description": "Determines whether this color bar's thickness (i.e. the measure in the constant color direction) is set in units of plot *fraction* or in *pixels*. Use `thickness` to set the value.", + "editType": "calc" + }, + "thickness": { + "valType": "number", + "role": "style", + "min": 0, + "dflt": 30, + "description": "Sets the thickness of the color bar This measure excludes the size of the padding, ticks and labels.", + "editType": "calc" + }, + "lenmode": { + "valType": "enumerated", + "values": [ + "fraction", + "pixels" + ], + "role": "info", + "dflt": "fraction", + "description": "Determines whether this color bar's length (i.e. the measure in the color variation direction) is set in units of plot *fraction* or in *pixels. Use `len` to set the value.", + "editType": "calc" + }, + "len": { + "valType": "number", + "min": 0, + "dflt": 1, + "role": "style", + "description": "Sets the length of the color bar This measure excludes the padding of both ends. That is, the color bar length is this length minus the padding on both ends.", + "editType": "calc" + }, + "x": { + "valType": "number", + "dflt": 1.02, + "min": -2, + "max": 3, + "role": "style", + "description": "Sets the x position of the color bar (in plot fraction).", + "editType": "calc" + }, + "xanchor": { + "valType": "enumerated", + "values": [ + "left", + "center", + "right" + ], + "dflt": "left", + "role": "style", + "description": "Sets this color bar's horizontal position anchor. This anchor binds the `x` position to the *left*, *center* or *right* of the color bar.", + "editType": "calc" + }, + "xpad": { + "valType": "number", + "role": "style", + "min": 0, + "dflt": 10, + "description": "Sets the amount of padding (in px) along the x direction.", + "editType": "calc" + }, + "y": { + "valType": "number", + "role": "style", + "dflt": 0.5, + "min": -2, + "max": 3, + "description": "Sets the y position of the color bar (in plot fraction).", + "editType": "calc" + }, + "yanchor": { + "valType": "enumerated", + "values": [ + "top", + "middle", + "bottom" + ], + "role": "style", + "dflt": "middle", + "description": "Sets this color bar's vertical position anchor This anchor binds the `y` position to the *top*, *middle* or *bottom* of the color bar.", + "editType": "calc" + }, + "ypad": { + "valType": "number", + "role": "style", + "min": 0, + "dflt": 10, + "description": "Sets the amount of padding (in px) along the y direction.", + "editType": "calc" + }, + "outlinecolor": { + "valType": "color", + "dflt": "#444", + "role": "style", + "editType": "calc", + "description": "Sets the axis line color." + }, + "outlinewidth": { + "valType": "number", + "min": 0, + "dflt": 1, + "role": "style", + "editType": "calc", + "description": "Sets the width (in px) of the axis line." + }, + "bordercolor": { + "valType": "color", + "dflt": "#444", + "role": "style", + "editType": "calc", + "description": "Sets the axis line color." + }, + "borderwidth": { + "valType": "number", + "role": "style", + "min": 0, + "dflt": 0, + "description": "Sets the width (in px) or the border enclosing this color bar.", + "editType": "calc" + }, + "bgcolor": { + "valType": "color", + "role": "style", + "dflt": "rgba(0,0,0,0)", + "description": "Sets the color of padded area.", + "editType": "calc" + }, + "tickmode": { + "valType": "enumerated", + "values": [ + "auto", + "linear", + "array" + ], + "role": "info", + "editType": "calc", + "impliedEdits": {}, + "description": "Sets the tick mode for this axis. If *auto*, the number of ticks is set via `nticks`. If *linear*, the placement of the ticks is determined by a starting position `tick0` and a tick step `dtick` (*linear* is the default value if `tick0` and `dtick` are provided). If *array*, the placement of the ticks is set via `tickvals` and the tick text is `ticktext`. (*array* is the default value if `tickvals` is provided)." + }, + "nticks": { + "valType": "integer", + "min": 0, + "dflt": 0, + "role": "style", + "editType": "calc", + "description": "Specifies the maximum number of ticks for the particular axis. The actual number of ticks will be chosen automatically to be less than or equal to `nticks`. Has an effect only if `tickmode` is set to *auto*." + }, + "tick0": { + "valType": "any", + "role": "style", + "editType": "calc", + "impliedEdits": { + "tickmode": "linear" + }, + "description": "Sets the placement of the first tick on this axis. Use with `dtick`. If the axis `type` is *log*, then you must take the log of your starting tick (e.g. to set the starting tick to 100, set the `tick0` to 2) except when `dtick`=*L* (see `dtick` for more info). If the axis `type` is *date*, it should be a date string, like date data. If the axis `type` is *category*, it should be a number, using the scale where each category is assigned a serial number from zero in the order it appears." + }, + "dtick": { + "valType": "any", + "role": "style", + "editType": "calc", + "impliedEdits": { + "tickmode": "linear" + }, + "description": "Sets the step in-between ticks on this axis. Use with `tick0`. Must be a positive number, or special strings available to *log* and *date* axes. If the axis `type` is *log*, then ticks are set every 10^(n*dtick) where n is the tick number. For example, to set a tick mark at 1, 10, 100, 1000, ... set dtick to 1. To set tick marks at 1, 100, 10000, ... set dtick to 2. To set tick marks at 1, 5, 25, 125, 625, 3125, ... set dtick to log_10(5), or 0.69897000433. *log* has several special values; *L*, where `f` is a positive number, gives ticks linearly spaced in value (but not position). For example `tick0` = 0.1, `dtick` = *L0.5* will put ticks at 0.1, 0.6, 1.1, 1.6 etc. To show powers of 10 plus small digits between, use *D1* (all digits) or *D2* (only 2 and 5). `tick0` is ignored for *D1* and *D2*. If the axis `type` is *date*, then you must convert the time to milliseconds. For example, to set the interval between ticks to one day, set `dtick` to 86400000.0. *date* also has special values *M* gives ticks spaced by a number of months. `n` must be a positive integer. To set ticks on the 15th of every third month, set `tick0` to *2000-01-15* and `dtick` to *M3*. To set ticks every 4 years, set `dtick` to *M48*" + }, + "tickvals": { + "valType": "data_array", + "editType": "calc", + "description": "Sets the values at which ticks on this axis appear. Only has an effect if `tickmode` is set to *array*. Used with `ticktext`.", + "role": "data" + }, + "ticktext": { + "valType": "data_array", + "editType": "calc", + "description": "Sets the text displayed at the ticks position via `tickvals`. Only has an effect if `tickmode` is set to *array*. Used with `tickvals`.", + "role": "data" + }, + "ticks": { + "valType": "enumerated", + "values": [ + "outside", + "inside", + "" + ], + "role": "style", + "editType": "calc", + "description": "Determines whether ticks are drawn or not. If **, this axis' ticks are not drawn. If *outside* (*inside*), this axis' are drawn outside (inside) the axis lines.", + "dflt": "" + }, + "ticklen": { + "valType": "number", + "min": 0, + "dflt": 5, + "role": "style", + "editType": "calc", + "description": "Sets the tick length (in px)." + }, + "tickwidth": { + "valType": "number", + "min": 0, + "dflt": 1, + "role": "style", + "editType": "calc", + "description": "Sets the tick width (in px)." + }, + "tickcolor": { + "valType": "color", + "dflt": "#444", + "role": "style", + "editType": "calc", + "description": "Sets the tick color." + }, + "showticklabels": { + "valType": "boolean", + "dflt": true, + "role": "style", + "editType": "calc", + "description": "Determines whether or not the tick labels are drawn." + }, + "tickfont": { + "family": { + "valType": "string", + "role": "style", + "noBlank": true, + "strict": true, + "description": "HTML font family - the typeface that will be applied by the web browser. The web browser will only be able to apply a font if it is available on the system which it operates. Provide multiple font families, separated by commas, to indicate the preference in which to apply fonts if they aren't available on the system. The plotly service (at https://plot.ly or on-premise) generates images on a server, where only a select number of fonts are installed and supported. These include *Arial*, *Balto*, *Courier New*, *Droid Sans*,, *Droid Serif*, *Droid Sans Mono*, *Gravitas One*, *Old Standard TT*, *Open Sans*, *Overpass*, *PT Sans Narrow*, *Raleway*, *Times New Roman*.", + "editType": "calc" + }, + "size": { + "valType": "number", + "role": "style", + "min": 1, + "editType": "calc" + }, + "color": { + "valType": "color", + "role": "style", + "editType": "calc" + }, + "description": "Sets the color bar's tick label font", + "editType": "calc", + "role": "object" + }, + "tickangle": { + "valType": "angle", + "dflt": "auto", + "role": "style", + "editType": "calc", + "description": "Sets the angle of the tick labels with respect to the horizontal. For example, a `tickangle` of -90 draws the tick labels vertically." + }, + "tickformat": { + "valType": "string", + "dflt": "", + "role": "style", + "editType": "calc", + "description": "Sets the tick label formatting rule using d3 formatting mini-languages which are very similar to those in Python. For numbers, see: https://github.com/d3/d3-format/blob/master/README.md#locale_format And for dates see: https://github.com/d3/d3-time-format/blob/master/README.md#locale_format We add one item to d3's date formatter: *%{n}f* for fractional seconds with n digits. For example, *2016-10-13 09:15:23.456* with tickformat *%H~%M~%S.%2f* would display *09~15~23.46*" + }, + "tickformatstops": { + "items": { + "tickformatstop": { + "dtickrange": { + "valType": "info_array", + "role": "info", + "items": [ + { + "valType": "any", + "editType": "calc" + }, + { + "valType": "any", + "editType": "calc" + } + ], + "editType": "calc", + "description": "range [*min*, *max*], where *min*, *max* - dtick values which describe some zoom level, it is possible to omit *min* or *max* value by passing *null*" + }, + "value": { + "valType": "string", + "dflt": "", + "role": "style", + "editType": "calc", + "description": "string - dtickformat for described zoom level, the same as *tickformat*" + }, + "editType": "calc", + "role": "object" + } + }, + "role": "object" + }, + "tickprefix": { + "valType": "string", + "dflt": "", + "role": "style", + "editType": "calc", + "description": "Sets a tick label prefix." + }, + "showtickprefix": { + "valType": "enumerated", + "values": [ + "all", + "first", + "last", + "none" + ], + "dflt": "all", + "role": "style", + "editType": "calc", + "description": "If *all*, all tick labels are displayed with a prefix. If *first*, only the first tick is displayed with a prefix. If *last*, only the last tick is displayed with a suffix. If *none*, tick prefixes are hidden." + }, + "ticksuffix": { + "valType": "string", + "dflt": "", + "role": "style", + "editType": "calc", + "description": "Sets a tick label suffix." + }, + "showticksuffix": { + "valType": "enumerated", + "values": [ + "all", + "first", + "last", + "none" + ], + "dflt": "all", + "role": "style", + "editType": "calc", + "description": "Same as `showtickprefix` but for tick suffixes." + }, + "separatethousands": { + "valType": "boolean", + "dflt": false, + "role": "style", + "editType": "calc", + "description": "If \"true\", even 4-digit integers are separated" + }, + "exponentformat": { + "valType": "enumerated", + "values": [ + "none", + "e", + "E", + "power", + "SI", + "B" + ], + "dflt": "B", + "role": "style", + "editType": "calc", + "description": "Determines a formatting rule for the tick exponents. For example, consider the number 1,000,000,000. If *none*, it appears as 1,000,000,000. If *e*, 1e+9. If *E*, 1E+9. If *power*, 1x10^9 (with 9 in a super script). If *SI*, 1G. If *B*, 1B." + }, + "showexponent": { + "valType": "enumerated", + "values": [ + "all", + "first", + "last", + "none" + ], + "dflt": "all", + "role": "style", + "editType": "calc", + "description": "If *all*, all exponents are shown besides their significands. If *first*, only the exponent of the first tick is shown. If *last*, only the exponent of the last tick is shown. If *none*, no exponents appear." + }, + "title": { + "valType": "string", + "role": "info", + "dflt": "Click to enter colorscale title", + "description": "Sets the title of the color bar.", + "editType": "calc" + }, + "titlefont": { + "family": { + "valType": "string", + "role": "style", + "noBlank": true, + "strict": true, + "description": "HTML font family - the typeface that will be applied by the web browser. The web browser will only be able to apply a font if it is available on the system which it operates. Provide multiple font families, separated by commas, to indicate the preference in which to apply fonts if they aren't available on the system. The plotly service (at https://plot.ly or on-premise) generates images on a server, where only a select number of fonts are installed and supported. These include *Arial*, *Balto*, *Courier New*, *Droid Sans*,, *Droid Serif*, *Droid Sans Mono*, *Gravitas One*, *Old Standard TT*, *Open Sans*, *Overpass*, *PT Sans Narrow*, *Raleway*, *Times New Roman*.", + "editType": "calc" + }, + "size": { + "valType": "number", + "role": "style", + "min": 1, + "editType": "calc" + }, + "color": { + "valType": "color", + "role": "style", + "editType": "calc" + }, + "description": "Sets this color bar's title font.", + "editType": "calc", + "role": "object" + }, + "titleside": { + "valType": "enumerated", + "values": [ + "right", + "top", + "bottom" + ], + "role": "style", + "dflt": "top", + "description": "Determines the location of the colorbar title with respect to the color bar.", + "editType": "calc" + }, + "editType": "calc", + "role": "object", + "tickvalssrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for tickvals .", + "editType": "none" + }, + "ticktextsrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for ticktext .", + "editType": "none" + } + }, + "line": { + "color": { + "valType": "color", + "arrayOk": true, + "role": "style", + "editType": "calc", + "description": "Sets the marker.line color. It accepts either a specific color or an array of numbers that are mapped to the colorscale relative to the max and min values of the array or relative to `cmin` and `cmax` if set." + }, + "colorscale": { + "valType": "colorscale", + "role": "style", + "editType": "calc", + "impliedEdits": { + "autocolorscale": false + }, + "description": "Sets the colorscale and only has an effect if `marker.line.color` is set to a numerical array. The colorscale must be an array containing arrays mapping a normalized value to an rgb, rgba, hex, hsl, hsv, or named color string. At minimum, a mapping for the lowest (0) and highest (1) values are required. For example, `[[0, 'rgb(0,0,255)', [1, 'rgb(255,0,0)']]`. To control the bounds of the colorscale in color space, use `marker.line.cmin` and `marker.line.cmax`. Alternatively, `colorscale` may be a palette name string of the following list: Greys, YlGnBu, Greens, YlOrRd, Bluered, RdBu, Reds, Blues, Picnic, Rainbow, Portland, Jet, Hot, Blackbody, Earth, Electric, Viridis" + }, + "cauto": { + "valType": "boolean", + "role": "info", + "dflt": true, + "editType": "calc", + "impliedEdits": {}, + "description": "Has an effect only if `marker.line.color` is set to a numerical array and `cmin`, `cmax` are set by the user. In this case, it controls whether the range of colors in `colorscale` is mapped to the range of values in the `color` array (`cauto: true`), or the `cmin`/`cmax` values (`cauto: false`). Defaults to `false` when `cmin`, `cmax` are set by the user." + }, + "cmax": { + "valType": "number", + "role": "info", + "dflt": null, + "editType": "calc", + "impliedEdits": { + "cauto": false + }, + "description": "Has an effect only if `marker.line.color` is set to a numerical array. Sets the upper bound of the color domain. Value should be associated to the `marker.line.color` array index, and if set, `marker.line.cmin` must be set as well." + }, + "cmin": { + "valType": "number", + "role": "info", + "dflt": null, + "editType": "calc", + "impliedEdits": { + "cauto": false + }, + "description": "Has an effect only if `marker.line.color` is set to a numerical array. Sets the lower bound of the color domain. Value should be associated to the `marker.line.color` array index, and if set, `marker.line.cmax` must be set as well." + }, + "autocolorscale": { + "valType": "boolean", + "role": "style", + "dflt": true, + "editType": "calc", + "impliedEdits": {}, + "description": "Has an effect only if `marker.line.color` is set to a numerical array. Determines whether the colorscale is a default palette (`autocolorscale: true`) or the palette determined by `marker.line.colorscale`. In case `colorscale` is unspecified or `autocolorscale` is true, the default palette will be chosen according to whether numbers in the `color` array are all positive, all negative or mixed." + }, + "reversescale": { + "valType": "boolean", + "role": "style", + "dflt": false, + "editType": "calc", + "description": "Has an effect only if `marker.line.color` is set to a numerical array. Reverses the color mapping if true (`cmin` will correspond to the last color in the array and `cmax` will correspond to the first color)." + }, + "width": { + "valType": "number", + "min": 0, + "arrayOk": true, + "role": "style", + "editType": "calc", + "description": "Sets the width (in px) of the lines bounding the marker points." + }, + "editType": "calc", + "role": "object", + "colorsrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for color .", + "editType": "none" + }, + "widthsrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for width .", + "editType": "none" + } + }, + "editType": "calc", + "role": "object", + "colorsrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for color .", + "editType": "none" + }, + "symbolsrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for symbol .", + "editType": "none" + }, + "sizesrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for size .", + "editType": "none" + }, + "opacitysrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for opacity .", + "editType": "none" + } + }, + "connectgaps": { + "valType": "boolean", + "dflt": false, + "role": "info", + "editType": "calc", + "description": "Determines whether or not gaps (i.e. {nan} or missing values) in the provided data arrays are connected." + }, + "fill": { + "valType": "enumerated", + "values": [ + "none", + "tozeroy", + "tozerox" + ], + "dflt": "none", + "role": "style", + "editType": "calc", + "description": "Sets the area to fill with a solid color. Use with `fillcolor` if not *none*. *tozerox* and *tozeroy* fill to x=0 and y=0 respectively. *tonextx* and *tonexty* fill between the endpoints of this trace and the endpoints of the trace before it, connecting those endpoints with straight lines (to make a stacked area graph); if there is no trace before it, they behave like *tozerox* and *tozeroy*. *toself* connects the endpoints of the trace (or each segment of the trace if it has gaps) into a closed shape. *tonext* fills the space between two traces if one completely encloses the other (eg consecutive contour lines), and behaves like *toself* if there is no trace before it. *tonext* should not be used if one trace does not enclose the other." + }, + "fillcolor": { + "valType": "color", + "role": "style", + "editType": "calc", + "description": "Sets the fill color. Defaults to a half-transparent variant of the line color, marker color, or marker line color, whichever is available." + }, + "error_y": { + "visible": { + "valType": "boolean", + "role": "info", + "editType": "calc", + "description": "Determines whether or not this set of error bars is visible." + }, + "type": { + "valType": "enumerated", + "values": [ + "percent", + "constant", + "sqrt", + "data" + ], + "role": "info", + "editType": "calc", + "description": "Determines the rule used to generate the error bars. If *constant`, the bar lengths are of a constant value. Set this constant in `value`. If *percent*, the bar lengths correspond to a percentage of underlying data. Set this percentage in `value`. If *sqrt*, the bar lengths correspond to the sqaure of the underlying data. If *array*, the bar lengths are set with data set `array`." + }, + "symmetric": { + "valType": "boolean", + "role": "info", + "editType": "calc", + "description": "Determines whether or not the error bars have the same length in both direction (top/bottom for vertical bars, left/right for horizontal bars." + }, + "array": { + "valType": "data_array", + "editType": "calc", + "description": "Sets the data corresponding the length of each error bar. Values are plotted relative to the underlying data.", + "role": "data" + }, + "arrayminus": { + "valType": "data_array", + "editType": "calc", + "description": "Sets the data corresponding the length of each error bar in the bottom (left) direction for vertical (horizontal) bars Values are plotted relative to the underlying data.", + "role": "data" + }, + "value": { + "valType": "number", + "min": 0, + "dflt": 10, + "role": "info", + "editType": "calc", + "description": "Sets the value of either the percentage (if `type` is set to *percent*) or the constant (if `type` is set to *constant*) corresponding to the lengths of the error bars." + }, + "valueminus": { + "valType": "number", + "min": 0, + "dflt": 10, + "role": "info", + "editType": "calc", + "description": "Sets the value of either the percentage (if `type` is set to *percent*) or the constant (if `type` is set to *constant*) corresponding to the lengths of the error bars in the bottom (left) direction for vertical (horizontal) bars" + }, + "traceref": { + "valType": "integer", + "min": 0, + "dflt": 0, + "role": "info", + "editType": "calc" + }, + "tracerefminus": { + "valType": "integer", + "min": 0, + "dflt": 0, + "role": "info", + "editType": "calc" + }, + "copy_ystyle": { + "valType": "boolean", + "role": "style", + "editType": "calc" + }, + "copy_zstyle": { + "valType": "boolean", + "role": "style", + "editType": "calc" + }, + "color": { + "valType": "color", + "role": "style", + "editType": "calc", + "description": "Sets the stoke color of the error bars." + }, + "thickness": { + "valType": "number", + "min": 0, + "dflt": 2, + "role": "style", + "editType": "calc", + "description": "Sets the thickness (in px) of the error bars." + }, + "width": { + "valType": "number", + "min": 0, + "role": "style", + "editType": "calc", + "description": "Sets the width (in px) of the cross-bar at both ends of the error bars." + }, + "editType": "calc", + "_deprecated": { + "opacity": { + "valType": "number", + "role": "style", + "editType": "calc", + "description": "Obsolete. Use the alpha channel in error bar `color` to set the opacity." + } + }, + "role": "object", + "arraysrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for array .", + "editType": "none" + }, + "arrayminussrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for arrayminus .", + "editType": "none" + } + }, + "error_x": { + "visible": { + "valType": "boolean", + "role": "info", + "editType": "calc", + "description": "Determines whether or not this set of error bars is visible." + }, + "type": { + "valType": "enumerated", + "values": [ + "percent", + "constant", + "sqrt", + "data" + ], + "role": "info", + "editType": "calc", + "description": "Determines the rule used to generate the error bars. If *constant`, the bar lengths are of a constant value. Set this constant in `value`. If *percent*, the bar lengths correspond to a percentage of underlying data. Set this percentage in `value`. If *sqrt*, the bar lengths correspond to the sqaure of the underlying data. If *array*, the bar lengths are set with data set `array`." + }, + "symmetric": { + "valType": "boolean", + "role": "info", + "editType": "calc", + "description": "Determines whether or not the error bars have the same length in both direction (top/bottom for vertical bars, left/right for horizontal bars." + }, + "array": { + "valType": "data_array", + "editType": "calc", + "description": "Sets the data corresponding the length of each error bar. Values are plotted relative to the underlying data.", + "role": "data" + }, + "arrayminus": { + "valType": "data_array", + "editType": "calc", + "description": "Sets the data corresponding the length of each error bar in the bottom (left) direction for vertical (horizontal) bars Values are plotted relative to the underlying data.", + "role": "data" + }, + "value": { + "valType": "number", + "min": 0, + "dflt": 10, + "role": "info", + "editType": "calc", + "description": "Sets the value of either the percentage (if `type` is set to *percent*) or the constant (if `type` is set to *constant*) corresponding to the lengths of the error bars." + }, + "valueminus": { + "valType": "number", + "min": 0, + "dflt": 10, + "role": "info", + "editType": "calc", + "description": "Sets the value of either the percentage (if `type` is set to *percent*) or the constant (if `type` is set to *constant*) corresponding to the lengths of the error bars in the bottom (left) direction for vertical (horizontal) bars" + }, + "traceref": { + "valType": "integer", + "min": 0, + "dflt": 0, + "role": "info", + "editType": "calc" + }, + "tracerefminus": { + "valType": "integer", + "min": 0, + "dflt": 0, + "role": "info", + "editType": "calc" + }, + "copy_ystyle": { + "valType": "boolean", + "role": "style", + "editType": "calc" + }, + "copy_zstyle": { + "valType": "boolean", + "role": "style", + "editType": "calc" + }, + "color": { + "valType": "color", + "role": "style", + "editType": "calc", + "description": "Sets the stoke color of the error bars." + }, + "thickness": { + "valType": "number", + "min": 0, + "dflt": 2, + "role": "style", + "editType": "calc", + "description": "Sets the thickness (in px) of the error bars." + }, + "width": { + "valType": "number", + "min": 0, + "role": "style", + "editType": "calc", + "description": "Sets the width (in px) of the cross-bar at both ends of the error bars." + }, + "editType": "calc", + "_deprecated": { + "opacity": { + "valType": "number", + "role": "style", + "editType": "calc", + "description": "Obsolete. Use the alpha channel in error bar `color` to set the opacity." + } + }, + "role": "object", + "arraysrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for array .", + "editType": "none" + }, + "arrayminussrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for arrayminus .", + "editType": "none" + } + }, + "xcalendar": { + "valType": "enumerated", + "values": [ + "gregorian", + "chinese", + "coptic", + "discworld", + "ethiopian", + "hebrew", + "islamic", + "julian", + "mayan", + "nanakshahi", + "nepali", + "persian", + "jalali", + "taiwan", + "thai", + "ummalqura" + ], + "role": "info", + "editType": "calc", + "dflt": "gregorian", + "description": "Sets the calendar system to use with `x` date data." + }, + "ycalendar": { + "valType": "enumerated", + "values": [ + "gregorian", + "chinese", + "coptic", + "discworld", + "ethiopian", + "hebrew", + "islamic", + "julian", + "mayan", + "nanakshahi", + "nepali", + "persian", + "jalali", + "taiwan", + "thai", + "ummalqura" + ], + "role": "info", + "editType": "calc", + "dflt": "gregorian", + "description": "Sets the calendar system to use with `y` date data." + }, + "xaxis": { + "valType": "subplotid", + "role": "info", + "dflt": "x", + "editType": "calc+clearAxisTypes", + "description": "Sets a reference between this trace's x coordinates and a 2D cartesian x axis. If *x* (the default value), the x coordinates refer to `layout.xaxis`. If *x2*, the x coordinates refer to `layout.xaxis2`, and so on." + }, + "yaxis": { + "valType": "subplotid", + "role": "info", + "dflt": "y", + "editType": "calc+clearAxisTypes", + "description": "Sets a reference between this trace's y coordinates and a 2D cartesian y axis. If *y* (the default value), the y coordinates refer to `layout.yaxis`. If *y2*, the y coordinates refer to `layout.xaxis2`, and so on." + }, + "idssrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for ids .", + "editType": "none" + }, + "customdatasrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for customdata .", + "editType": "none" + }, + "hoverinfosrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for hoverinfo .", + "editType": "none" + }, + "xsrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for x .", + "editType": "none" + }, + "ysrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for y .", + "editType": "none" + }, + "textsrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for text .", + "editType": "none" + } + } + }, + "pointcloud": { + "meta": { + "description": "The data visualized as a point cloud set in `x` and `y` using the WebGl plotting engine." + }, + "attributes": { + "type": "pointcloud", + "visible": { + "valType": "enumerated", + "values": [ + true, + false, + "legendonly" + ], + "role": "info", + "dflt": true, + "editType": "calc", + "description": "Determines whether or not this trace is visible. If *legendonly*, the trace is not drawn, but can appear as a legend item (provided that the legend itself is visible)." + }, + "showlegend": { + "valType": "boolean", + "role": "info", + "dflt": true, + "editType": "style", + "description": "Determines whether or not an item corresponding to this trace is shown in the legend." + }, + "legendgroup": { + "valType": "string", + "role": "info", + "dflt": "", + "editType": "style", + "description": "Sets the legend group for this trace. Traces part of the same legend group hide/show at the same time when toggling legend items." + }, + "opacity": { + "valType": "number", + "role": "style", + "min": 0, + "max": 1, + "dflt": 1, + "editType": "style", + "description": "Sets the opacity of the trace." + }, + "name": { + "valType": "string", + "role": "info", + "editType": "style", + "description": "Sets the trace name. The trace name appear as the legend item and on hover." + }, + "uid": { + "valType": "string", + "role": "info", + "dflt": "", + "editType": "calc" + }, + "ids": { + "valType": "data_array", + "editType": "calc", + "description": "Assigns id labels to each datum. These ids for object constancy of data points during animation.", + "role": "data" + }, + "customdata": { + "valType": "data_array", + "editType": "calc", + "description": "Assigns extra data each datum. This may be useful when listening to hover, click and selection events. Note that, *scatter* traces also appends customdata items in the markers DOM elements", + "role": "data" + }, + "selectedpoints": { + "valType": "any", + "role": "info", + "editType": "calc", + "description": "Array containing integer indices of selected points. Has an effect only for traces that support selections. Note that an empty array means an empty selection where the `unselected` are turned on for all points, whereas, any other non-array values means no selection all where the `selected` and `unselected` styles have no effect." + }, + "hoverinfo": { + "valType": "flaglist", + "role": "info", + "flags": [ + "x", + "y", + "z", + "text", + "name" + ], + "extras": [ + "all", + "none", + "skip" + ], + "arrayOk": true, + "dflt": "all", + "editType": "none", + "description": "Determines which trace information appear on hover. If `none` or `skip` are set, no information is displayed upon hovering. But, if `none` is set, click and hover events are still fired." + }, + "hoverlabel": { + "bgcolor": { + "valType": "color", + "role": "style", + "arrayOk": true, + "editType": "none", + "description": "Sets the background color of the hover labels for this trace" + }, + "bordercolor": { + "valType": "color", + "role": "style", + "arrayOk": true, + "editType": "none", + "description": "Sets the border color of the hover labels for this trace." + }, + "font": { + "family": { + "valType": "string", + "role": "style", + "noBlank": true, + "strict": true, + "editType": "none", + "description": "HTML font family - the typeface that will be applied by the web browser. The web browser will only be able to apply a font if it is available on the system which it operates. Provide multiple font families, separated by commas, to indicate the preference in which to apply fonts if they aren't available on the system. The plotly service (at https://plot.ly or on-premise) generates images on a server, where only a select number of fonts are installed and supported. These include *Arial*, *Balto*, *Courier New*, *Droid Sans*,, *Droid Serif*, *Droid Sans Mono*, *Gravitas One*, *Old Standard TT*, *Open Sans*, *Overpass*, *PT Sans Narrow*, *Raleway*, *Times New Roman*.", + "arrayOk": true + }, + "size": { + "valType": "number", + "role": "style", + "min": 1, + "editType": "none", + "arrayOk": true + }, + "color": { + "valType": "color", + "role": "style", + "editType": "none", + "arrayOk": true + }, + "editType": "none", + "description": "Sets the font used in hover labels.", + "role": "object", + "familysrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for family .", + "editType": "none" + }, + "sizesrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for size .", + "editType": "none" + }, + "colorsrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for color .", + "editType": "none" + } + }, + "namelength": { + "valType": "integer", + "min": -1, + "arrayOk": true, + "role": "style", + "editType": "none", + "description": "Sets the length (in number of characters) of the trace name in the hover labels for this trace. -1 shows the whole name regardless of length. 0-3 shows the first 0-3 characters, and an integer >3 will show the whole name if it is less than that many characters, but if it is longer, will truncate to `namelength - 3` characters and add an ellipsis." + }, + "editType": "calc", + "role": "object", + "bgcolorsrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for bgcolor .", + "editType": "none" + }, + "bordercolorsrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for bordercolor .", + "editType": "none" + }, + "namelengthsrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for namelength .", + "editType": "none" + } + }, + "stream": { + "token": { + "valType": "string", + "noBlank": true, + "strict": true, + "role": "info", + "editType": "calc", + "description": "The stream id number links a data trace on a plot with a stream. See https://plot.ly/settings for more details." + }, + "maxpoints": { + "valType": "number", + "min": 0, + "max": 10000, + "dflt": 500, + "role": "info", + "editType": "calc", + "description": "Sets the maximum number of points to keep on the plots from an incoming stream. If `maxpoints` is set to *50*, only the newest 50 points will be displayed on the plot." + }, + "editType": "calc", + "role": "object" + }, + "x": { + "valType": "data_array", + "editType": "calc+clearAxisTypes", + "description": "Sets the x coordinates.", + "role": "data" + }, + "y": { + "valType": "data_array", + "editType": "calc+clearAxisTypes", + "description": "Sets the y coordinates.", + "role": "data" + }, + "xy": { + "valType": "data_array", + "editType": "calc", + "description": "Faster alternative to specifying `x` and `y` separately. If supplied, it must be a typed `Float32Array` array that represents points such that `xy[i * 2] = x[i]` and `xy[i * 2 + 1] = y[i]`", + "role": "data" + }, + "indices": { + "valType": "data_array", + "editType": "calc", + "description": "A sequential value, 0..n, supply it to avoid creating this array inside plotting. If specified, it must be a typed `Int32Array` array. Its length must be equal to or greater than the number of points. For the best performance and memory use, create one large `indices` typed array that is guaranteed to be at least as long as the largest number of points during use, and reuse it on each `Plotly.restyle()` call.", + "role": "data" + }, + "xbounds": { + "valType": "data_array", + "editType": "calc", + "description": "Specify `xbounds` in the shape of `[xMin, xMax] to avoid looping through the `xy` typed array. Use it in conjunction with `xy` and `ybounds` for the performance benefits.", + "role": "data" + }, + "ybounds": { + "valType": "data_array", + "editType": "calc", + "description": "Specify `ybounds` in the shape of `[yMin, yMax] to avoid looping through the `xy` typed array. Use it in conjunction with `xy` and `xbounds` for the performance benefits.", + "role": "data" + }, + "text": { + "valType": "string", + "role": "info", + "dflt": "", + "arrayOk": true, + "editType": "calc", + "description": "Sets text elements associated with each (x,y) pair to appear on hover. If a single string, the same string appears over all the data points. If an array of string, the items are mapped in order to the this trace's (x,y) coordinates." + }, + "marker": { + "color": { + "valType": "color", + "arrayOk": false, + "role": "style", + "editType": "calc", + "description": "Sets the marker fill color. It accepts a specific color.If the color is not fully opaque and there are hundreds of thousandsof points, it may cause slower zooming and panning." + }, + "opacity": { + "valType": "number", + "min": 0, + "max": 1, + "dflt": 1, + "arrayOk": false, + "role": "style", + "editType": "calc", + "description": "Sets the marker opacity. The default value is `1` (fully opaque). If the markers are not fully opaque and there are hundreds of thousands of points, it may cause slower zooming and panning. Opacity fades the color even if `blend` is left on `false` even if there is no translucency effect in that case." + }, + "blend": { + "valType": "boolean", + "dflt": null, + "role": "style", + "editType": "calc", + "description": "Determines if colors are blended together for a translucency effect in case `opacity` is specified as a value less then `1`. Setting `blend` to `true` reduces zoom/pan speed if used with large numbers of points." + }, + "sizemin": { + "valType": "number", + "min": 0.1, + "max": 2, + "dflt": 0.5, + "role": "style", + "editType": "calc", + "description": "Sets the minimum size (in px) of the rendered marker points, effective when the `pointcloud` shows a million or more points." + }, + "sizemax": { + "valType": "number", + "min": 0.1, + "dflt": 20, + "role": "style", + "editType": "calc", + "description": "Sets the maximum size (in px) of the rendered marker points. Effective when the `pointcloud` shows only few points." + }, + "border": { + "color": { + "valType": "color", + "arrayOk": false, + "role": "style", + "editType": "calc", + "description": "Sets the stroke color. It accepts a specific color. If the color is not fully opaque and there are hundreds of thousands of points, it may cause slower zooming and panning." + }, + "arearatio": { + "valType": "number", + "min": 0, + "max": 1, + "dflt": 0, + "role": "style", + "editType": "calc", + "description": "Specifies what fraction of the marker area is covered with the border." + }, + "editType": "calc", + "role": "object" + }, + "editType": "calc", + "role": "object" + }, + "xaxis": { + "valType": "subplotid", + "role": "info", + "dflt": "x", + "editType": "calc+clearAxisTypes", + "description": "Sets a reference between this trace's x coordinates and a 2D cartesian x axis. If *x* (the default value), the x coordinates refer to `layout.xaxis`. If *x2*, the x coordinates refer to `layout.xaxis2`, and so on." + }, + "yaxis": { + "valType": "subplotid", + "role": "info", + "dflt": "y", + "editType": "calc+clearAxisTypes", + "description": "Sets a reference between this trace's y coordinates and a 2D cartesian y axis. If *y* (the default value), the y coordinates refer to `layout.yaxis`. If *y2*, the y coordinates refer to `layout.xaxis2`, and so on." + }, + "idssrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for ids .", + "editType": "none" + }, + "customdatasrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for customdata .", + "editType": "none" + }, + "hoverinfosrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for hoverinfo .", + "editType": "none" + }, + "xsrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for x .", + "editType": "none" + }, + "ysrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for y .", + "editType": "none" + }, + "xysrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for xy .", + "editType": "none" + }, + "indicessrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for indices .", + "editType": "none" + }, + "xboundssrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for xbounds .", + "editType": "none" + }, + "yboundssrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for ybounds .", + "editType": "none" + }, + "textsrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for text .", + "editType": "none" + } + } + }, + "heatmapgl": { + "meta": { + "description": "WebGL version of the heatmap trace type." + }, + "attributes": { + "type": "heatmapgl", + "visible": { + "valType": "enumerated", + "values": [ + true, + false, + "legendonly" + ], + "role": "info", + "dflt": true, + "editType": "calc", + "description": "Determines whether or not this trace is visible. If *legendonly*, the trace is not drawn, but can appear as a legend item (provided that the legend itself is visible)." + }, + "showlegend": { + "valType": "boolean", + "role": "info", + "dflt": true, + "editType": "style", + "description": "Determines whether or not an item corresponding to this trace is shown in the legend." + }, + "legendgroup": { + "valType": "string", + "role": "info", + "dflt": "", + "editType": "style", + "description": "Sets the legend group for this trace. Traces part of the same legend group hide/show at the same time when toggling legend items." + }, + "opacity": { + "valType": "number", + "role": "style", + "min": 0, + "max": 1, + "dflt": 1, + "editType": "style", + "description": "Sets the opacity of the trace." + }, + "name": { + "valType": "string", + "role": "info", + "editType": "style", + "description": "Sets the trace name. The trace name appear as the legend item and on hover." + }, + "uid": { + "valType": "string", + "role": "info", + "dflt": "", + "editType": "calc" + }, + "ids": { + "valType": "data_array", + "editType": "calc", + "description": "Assigns id labels to each datum. These ids for object constancy of data points during animation.", + "role": "data" + }, + "customdata": { + "valType": "data_array", + "editType": "calc", + "description": "Assigns extra data each datum. This may be useful when listening to hover, click and selection events. Note that, *scatter* traces also appends customdata items in the markers DOM elements", + "role": "data" + }, + "selectedpoints": { + "valType": "any", + "role": "info", + "editType": "calc", + "description": "Array containing integer indices of selected points. Has an effect only for traces that support selections. Note that an empty array means an empty selection where the `unselected` are turned on for all points, whereas, any other non-array values means no selection all where the `selected` and `unselected` styles have no effect." + }, + "hoverinfo": { + "valType": "flaglist", + "role": "info", + "flags": [ + "x", + "y", + "z", + "text", + "name" + ], + "extras": [ + "all", + "none", + "skip" + ], + "arrayOk": true, + "dflt": "all", + "editType": "none", + "description": "Determines which trace information appear on hover. If `none` or `skip` are set, no information is displayed upon hovering. But, if `none` is set, click and hover events are still fired." + }, + "hoverlabel": { + "bgcolor": { + "valType": "color", + "role": "style", + "arrayOk": true, + "editType": "none", + "description": "Sets the background color of the hover labels for this trace" + }, + "bordercolor": { + "valType": "color", + "role": "style", + "arrayOk": true, + "editType": "none", + "description": "Sets the border color of the hover labels for this trace." + }, + "font": { + "family": { + "valType": "string", + "role": "style", + "noBlank": true, + "strict": true, + "editType": "none", + "description": "HTML font family - the typeface that will be applied by the web browser. The web browser will only be able to apply a font if it is available on the system which it operates. Provide multiple font families, separated by commas, to indicate the preference in which to apply fonts if they aren't available on the system. The plotly service (at https://plot.ly or on-premise) generates images on a server, where only a select number of fonts are installed and supported. These include *Arial*, *Balto*, *Courier New*, *Droid Sans*,, *Droid Serif*, *Droid Sans Mono*, *Gravitas One*, *Old Standard TT*, *Open Sans*, *Overpass*, *PT Sans Narrow*, *Raleway*, *Times New Roman*.", + "arrayOk": true + }, + "size": { + "valType": "number", + "role": "style", + "min": 1, + "editType": "none", + "arrayOk": true + }, + "color": { + "valType": "color", + "role": "style", + "editType": "none", + "arrayOk": true + }, + "editType": "none", + "description": "Sets the font used in hover labels.", + "role": "object", + "familysrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for family .", + "editType": "none" + }, + "sizesrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for size .", + "editType": "none" + }, + "colorsrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for color .", + "editType": "none" + } + }, + "namelength": { + "valType": "integer", + "min": -1, + "arrayOk": true, + "role": "style", + "editType": "none", + "description": "Sets the length (in number of characters) of the trace name in the hover labels for this trace. -1 shows the whole name regardless of length. 0-3 shows the first 0-3 characters, and an integer >3 will show the whole name if it is less than that many characters, but if it is longer, will truncate to `namelength - 3` characters and add an ellipsis." + }, + "editType": "calc", + "role": "object", + "bgcolorsrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for bgcolor .", + "editType": "none" + }, + "bordercolorsrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for bordercolor .", + "editType": "none" + }, + "namelengthsrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for namelength .", + "editType": "none" + } + }, + "stream": { + "token": { + "valType": "string", + "noBlank": true, + "strict": true, + "role": "info", + "editType": "calc", + "description": "The stream id number links a data trace on a plot with a stream. See https://plot.ly/settings for more details." + }, + "maxpoints": { + "valType": "number", + "min": 0, + "max": 10000, + "dflt": 500, + "role": "info", + "editType": "calc", + "description": "Sets the maximum number of points to keep on the plots from an incoming stream. If `maxpoints` is set to *50*, only the newest 50 points will be displayed on the plot." + }, + "editType": "calc", + "role": "object" + }, + "z": { + "valType": "data_array", + "editType": "calc", + "description": "Sets the z data.", + "role": "data" + }, + "x": { + "valType": "data_array", + "editType": "calc", + "description": "Sets the x coordinates.", + "impliedEdits": { + "xtype": "array" + }, + "role": "data" + }, + "x0": { + "valType": "any", + "dflt": 0, + "role": "info", + "editType": "calc", + "description": "Alternate to `x`. Builds a linear space of x coordinates. Use with `dx` where `x0` is the starting coordinate and `dx` the step.", + "impliedEdits": { + "xtype": "scaled" + } + }, + "dx": { + "valType": "number", + "dflt": 1, + "role": "info", + "editType": "calc", + "description": "Sets the x coordinate step. See `x0` for more info.", + "impliedEdits": { + "xtype": "scaled" + } + }, + "y": { + "valType": "data_array", + "editType": "calc", + "description": "Sets the y coordinates.", + "impliedEdits": { + "ytype": "array" + }, + "role": "data" + }, + "y0": { + "valType": "any", + "dflt": 0, + "role": "info", + "editType": "calc", + "description": "Alternate to `y`. Builds a linear space of y coordinates. Use with `dy` where `y0` is the starting coordinate and `dy` the step.", + "impliedEdits": { + "ytype": "scaled" + } + }, + "dy": { + "valType": "number", + "dflt": 1, + "role": "info", + "editType": "calc", + "description": "Sets the y coordinate step. See `y0` for more info.", + "impliedEdits": { + "ytype": "scaled" + } + }, + "text": { + "valType": "data_array", + "editType": "calc", + "description": "Sets the text elements associated with each z value.", + "role": "data" + }, + "transpose": { + "valType": "boolean", + "dflt": false, + "role": "info", + "editType": "calc", + "description": "Transposes the z data." + }, + "xtype": { + "valType": "enumerated", + "values": [ + "array", + "scaled" + ], + "role": "info", + "editType": "calc", + "description": "If *array*, the heatmap's x coordinates are given by *x* (the default behavior when `x` is provided). If *scaled*, the heatmap's x coordinates are given by *x0* and *dx* (the default behavior when `x` is not provided)." + }, + "ytype": { + "valType": "enumerated", + "values": [ + "array", + "scaled" + ], + "role": "info", + "editType": "calc", + "description": "If *array*, the heatmap's y coordinates are given by *y* (the default behavior when `y` is provided) If *scaled*, the heatmap's y coordinates are given by *y0* and *dy* (the default behavior when `y` is not provided)" + }, + "zauto": { + "valType": "boolean", + "role": "info", + "dflt": true, + "editType": "calc", + "impliedEdits": {}, + "description": "Determines the whether or not the color domain is computed with respect to the input data." + }, + "zmin": { + "valType": "number", + "role": "info", + "dflt": null, + "editType": "calc", + "impliedEdits": { + "zauto": false + }, + "description": "Sets the lower bound of color domain." + }, + "zmax": { + "valType": "number", + "role": "info", + "dflt": null, + "editType": "calc", + "impliedEdits": { + "zauto": false + }, + "description": "Sets the upper bound of color domain." + }, + "colorscale": { + "valType": "colorscale", + "role": "style", + "editType": "calc", + "impliedEdits": { + "autocolorscale": false + }, + "description": "Sets the colorscale. The colorscale must be an array containing arrays mapping a normalized value to an rgb, rgba, hex, hsl, hsv, or named color string. At minimum, a mapping for the lowest (0) and highest (1) values are required. For example, `[[0, 'rgb(0,0,255)', [1, 'rgb(255,0,0)']]`. To control the bounds of the colorscale in z space, use zmin and zmax" + }, + "autocolorscale": { + "valType": "boolean", + "role": "style", + "dflt": false, + "editType": "calc", + "impliedEdits": {}, + "description": "Determines whether or not the colorscale is picked using the sign of the input z values." + }, + "reversescale": { + "valType": "boolean", + "role": "style", + "dflt": false, + "editType": "calc", + "description": "Reverses the colorscale." + }, + "showscale": { + "valType": "boolean", + "role": "info", + "dflt": true, + "editType": "calc", + "description": "Determines whether or not a colorbar is displayed for this trace." + }, + "colorbar": { + "thicknessmode": { + "valType": "enumerated", + "values": [ + "fraction", + "pixels" + ], + "role": "style", + "dflt": "pixels", + "description": "Determines whether this color bar's thickness (i.e. the measure in the constant color direction) is set in units of plot *fraction* or in *pixels*. Use `thickness` to set the value.", + "editType": "calc" + }, + "thickness": { + "valType": "number", + "role": "style", + "min": 0, + "dflt": 30, + "description": "Sets the thickness of the color bar This measure excludes the size of the padding, ticks and labels.", + "editType": "calc" + }, + "lenmode": { + "valType": "enumerated", + "values": [ + "fraction", + "pixels" + ], + "role": "info", + "dflt": "fraction", + "description": "Determines whether this color bar's length (i.e. the measure in the color variation direction) is set in units of plot *fraction* or in *pixels. Use `len` to set the value.", + "editType": "calc" + }, + "len": { + "valType": "number", + "min": 0, + "dflt": 1, + "role": "style", + "description": "Sets the length of the color bar This measure excludes the padding of both ends. That is, the color bar length is this length minus the padding on both ends.", + "editType": "calc" + }, + "x": { + "valType": "number", + "dflt": 1.02, + "min": -2, + "max": 3, + "role": "style", + "description": "Sets the x position of the color bar (in plot fraction).", + "editType": "calc" + }, + "xanchor": { + "valType": "enumerated", + "values": [ + "left", + "center", + "right" + ], + "dflt": "left", + "role": "style", + "description": "Sets this color bar's horizontal position anchor. This anchor binds the `x` position to the *left*, *center* or *right* of the color bar.", + "editType": "calc" + }, + "xpad": { + "valType": "number", + "role": "style", + "min": 0, + "dflt": 10, + "description": "Sets the amount of padding (in px) along the x direction.", + "editType": "calc" + }, + "y": { + "valType": "number", + "role": "style", + "dflt": 0.5, + "min": -2, + "max": 3, + "description": "Sets the y position of the color bar (in plot fraction).", + "editType": "calc" + }, + "yanchor": { + "valType": "enumerated", + "values": [ + "top", + "middle", + "bottom" + ], + "role": "style", + "dflt": "middle", + "description": "Sets this color bar's vertical position anchor This anchor binds the `y` position to the *top*, *middle* or *bottom* of the color bar.", + "editType": "calc" + }, + "ypad": { + "valType": "number", + "role": "style", + "min": 0, + "dflt": 10, + "description": "Sets the amount of padding (in px) along the y direction.", + "editType": "calc" + }, + "outlinecolor": { + "valType": "color", + "dflt": "#444", + "role": "style", + "editType": "calc", + "description": "Sets the axis line color." + }, + "outlinewidth": { + "valType": "number", + "min": 0, + "dflt": 1, + "role": "style", + "editType": "calc", + "description": "Sets the width (in px) of the axis line." + }, + "bordercolor": { + "valType": "color", + "dflt": "#444", + "role": "style", + "editType": "calc", + "description": "Sets the axis line color." + }, + "borderwidth": { + "valType": "number", + "role": "style", + "min": 0, + "dflt": 0, + "description": "Sets the width (in px) or the border enclosing this color bar.", + "editType": "calc" + }, + "bgcolor": { + "valType": "color", + "role": "style", + "dflt": "rgba(0,0,0,0)", + "description": "Sets the color of padded area.", + "editType": "calc" + }, + "tickmode": { + "valType": "enumerated", + "values": [ + "auto", + "linear", + "array" + ], + "role": "info", + "editType": "calc", + "impliedEdits": {}, + "description": "Sets the tick mode for this axis. If *auto*, the number of ticks is set via `nticks`. If *linear*, the placement of the ticks is determined by a starting position `tick0` and a tick step `dtick` (*linear* is the default value if `tick0` and `dtick` are provided). If *array*, the placement of the ticks is set via `tickvals` and the tick text is `ticktext`. (*array* is the default value if `tickvals` is provided)." + }, + "nticks": { + "valType": "integer", + "min": 0, + "dflt": 0, + "role": "style", + "editType": "calc", + "description": "Specifies the maximum number of ticks for the particular axis. The actual number of ticks will be chosen automatically to be less than or equal to `nticks`. Has an effect only if `tickmode` is set to *auto*." + }, + "tick0": { + "valType": "any", + "role": "style", + "editType": "calc", + "impliedEdits": { + "tickmode": "linear" + }, + "description": "Sets the placement of the first tick on this axis. Use with `dtick`. If the axis `type` is *log*, then you must take the log of your starting tick (e.g. to set the starting tick to 100, set the `tick0` to 2) except when `dtick`=*L* (see `dtick` for more info). If the axis `type` is *date*, it should be a date string, like date data. If the axis `type` is *category*, it should be a number, using the scale where each category is assigned a serial number from zero in the order it appears." + }, + "dtick": { + "valType": "any", + "role": "style", + "editType": "calc", + "impliedEdits": { + "tickmode": "linear" + }, + "description": "Sets the step in-between ticks on this axis. Use with `tick0`. Must be a positive number, or special strings available to *log* and *date* axes. If the axis `type` is *log*, then ticks are set every 10^(n*dtick) where n is the tick number. For example, to set a tick mark at 1, 10, 100, 1000, ... set dtick to 1. To set tick marks at 1, 100, 10000, ... set dtick to 2. To set tick marks at 1, 5, 25, 125, 625, 3125, ... set dtick to log_10(5), or 0.69897000433. *log* has several special values; *L*, where `f` is a positive number, gives ticks linearly spaced in value (but not position). For example `tick0` = 0.1, `dtick` = *L0.5* will put ticks at 0.1, 0.6, 1.1, 1.6 etc. To show powers of 10 plus small digits between, use *D1* (all digits) or *D2* (only 2 and 5). `tick0` is ignored for *D1* and *D2*. If the axis `type` is *date*, then you must convert the time to milliseconds. For example, to set the interval between ticks to one day, set `dtick` to 86400000.0. *date* also has special values *M* gives ticks spaced by a number of months. `n` must be a positive integer. To set ticks on the 15th of every third month, set `tick0` to *2000-01-15* and `dtick` to *M3*. To set ticks every 4 years, set `dtick` to *M48*" + }, + "tickvals": { + "valType": "data_array", + "editType": "calc", + "description": "Sets the values at which ticks on this axis appear. Only has an effect if `tickmode` is set to *array*. Used with `ticktext`.", + "role": "data" + }, + "ticktext": { + "valType": "data_array", + "editType": "calc", + "description": "Sets the text displayed at the ticks position via `tickvals`. Only has an effect if `tickmode` is set to *array*. Used with `tickvals`.", + "role": "data" + }, + "ticks": { + "valType": "enumerated", + "values": [ + "outside", + "inside", + "" + ], + "role": "style", + "editType": "calc", + "description": "Determines whether ticks are drawn or not. If **, this axis' ticks are not drawn. If *outside* (*inside*), this axis' are drawn outside (inside) the axis lines.", + "dflt": "" + }, + "ticklen": { + "valType": "number", + "min": 0, + "dflt": 5, + "role": "style", + "editType": "calc", + "description": "Sets the tick length (in px)." + }, + "tickwidth": { + "valType": "number", + "min": 0, + "dflt": 1, + "role": "style", + "editType": "calc", + "description": "Sets the tick width (in px)." + }, + "tickcolor": { + "valType": "color", + "dflt": "#444", + "role": "style", + "editType": "calc", + "description": "Sets the tick color." + }, + "showticklabels": { + "valType": "boolean", + "dflt": true, + "role": "style", + "editType": "calc", + "description": "Determines whether or not the tick labels are drawn." + }, + "tickfont": { + "family": { + "valType": "string", + "role": "style", + "noBlank": true, + "strict": true, + "description": "HTML font family - the typeface that will be applied by the web browser. The web browser will only be able to apply a font if it is available on the system which it operates. Provide multiple font families, separated by commas, to indicate the preference in which to apply fonts if they aren't available on the system. The plotly service (at https://plot.ly or on-premise) generates images on a server, where only a select number of fonts are installed and supported. These include *Arial*, *Balto*, *Courier New*, *Droid Sans*,, *Droid Serif*, *Droid Sans Mono*, *Gravitas One*, *Old Standard TT*, *Open Sans*, *Overpass*, *PT Sans Narrow*, *Raleway*, *Times New Roman*.", + "editType": "calc" + }, + "size": { + "valType": "number", + "role": "style", + "min": 1, + "editType": "calc" + }, + "color": { + "valType": "color", + "role": "style", + "editType": "calc" + }, + "description": "Sets the color bar's tick label font", + "editType": "calc", + "role": "object" + }, + "tickangle": { + "valType": "angle", + "dflt": "auto", + "role": "style", + "editType": "calc", + "description": "Sets the angle of the tick labels with respect to the horizontal. For example, a `tickangle` of -90 draws the tick labels vertically." + }, + "tickformat": { + "valType": "string", + "dflt": "", + "role": "style", + "editType": "calc", + "description": "Sets the tick label formatting rule using d3 formatting mini-languages which are very similar to those in Python. For numbers, see: https://github.com/d3/d3-format/blob/master/README.md#locale_format And for dates see: https://github.com/d3/d3-time-format/blob/master/README.md#locale_format We add one item to d3's date formatter: *%{n}f* for fractional seconds with n digits. For example, *2016-10-13 09:15:23.456* with tickformat *%H~%M~%S.%2f* would display *09~15~23.46*" + }, + "tickformatstops": { + "items": { + "tickformatstop": { + "dtickrange": { + "valType": "info_array", + "role": "info", + "items": [ + { + "valType": "any", + "editType": "calc" + }, + { + "valType": "any", + "editType": "calc" + } + ], + "editType": "calc", + "description": "range [*min*, *max*], where *min*, *max* - dtick values which describe some zoom level, it is possible to omit *min* or *max* value by passing *null*" + }, + "value": { + "valType": "string", + "dflt": "", + "role": "style", + "editType": "calc", + "description": "string - dtickformat for described zoom level, the same as *tickformat*" + }, + "editType": "calc", + "role": "object" + } + }, + "role": "object" + }, + "tickprefix": { + "valType": "string", + "dflt": "", + "role": "style", + "editType": "calc", + "description": "Sets a tick label prefix." + }, + "showtickprefix": { + "valType": "enumerated", + "values": [ + "all", + "first", + "last", + "none" + ], + "dflt": "all", + "role": "style", + "editType": "calc", + "description": "If *all*, all tick labels are displayed with a prefix. If *first*, only the first tick is displayed with a prefix. If *last*, only the last tick is displayed with a suffix. If *none*, tick prefixes are hidden." + }, + "ticksuffix": { + "valType": "string", + "dflt": "", + "role": "style", + "editType": "calc", + "description": "Sets a tick label suffix." + }, + "showticksuffix": { + "valType": "enumerated", + "values": [ + "all", + "first", + "last", + "none" + ], + "dflt": "all", + "role": "style", + "editType": "calc", + "description": "Same as `showtickprefix` but for tick suffixes." + }, + "separatethousands": { + "valType": "boolean", + "dflt": false, + "role": "style", + "editType": "calc", + "description": "If \"true\", even 4-digit integers are separated" + }, + "exponentformat": { + "valType": "enumerated", + "values": [ + "none", + "e", + "E", + "power", + "SI", + "B" + ], + "dflt": "B", + "role": "style", + "editType": "calc", + "description": "Determines a formatting rule for the tick exponents. For example, consider the number 1,000,000,000. If *none*, it appears as 1,000,000,000. If *e*, 1e+9. If *E*, 1E+9. If *power*, 1x10^9 (with 9 in a super script). If *SI*, 1G. If *B*, 1B." + }, + "showexponent": { + "valType": "enumerated", + "values": [ + "all", + "first", + "last", + "none" + ], + "dflt": "all", + "role": "style", + "editType": "calc", + "description": "If *all*, all exponents are shown besides their significands. If *first*, only the exponent of the first tick is shown. If *last*, only the exponent of the last tick is shown. If *none*, no exponents appear." + }, + "title": { + "valType": "string", + "role": "info", + "dflt": "Click to enter colorscale title", + "description": "Sets the title of the color bar.", + "editType": "calc" + }, + "titlefont": { + "family": { + "valType": "string", + "role": "style", + "noBlank": true, + "strict": true, + "description": "HTML font family - the typeface that will be applied by the web browser. The web browser will only be able to apply a font if it is available on the system which it operates. Provide multiple font families, separated by commas, to indicate the preference in which to apply fonts if they aren't available on the system. The plotly service (at https://plot.ly or on-premise) generates images on a server, where only a select number of fonts are installed and supported. These include *Arial*, *Balto*, *Courier New*, *Droid Sans*,, *Droid Serif*, *Droid Sans Mono*, *Gravitas One*, *Old Standard TT*, *Open Sans*, *Overpass*, *PT Sans Narrow*, *Raleway*, *Times New Roman*.", + "editType": "calc" + }, + "size": { + "valType": "number", + "role": "style", + "min": 1, + "editType": "calc" + }, + "color": { + "valType": "color", + "role": "style", + "editType": "calc" + }, + "description": "Sets this color bar's title font.", + "editType": "calc", + "role": "object" + }, + "titleside": { + "valType": "enumerated", + "values": [ + "right", + "top", + "bottom" + ], + "role": "style", + "dflt": "top", + "description": "Determines the location of the colorbar title with respect to the color bar.", + "editType": "calc" + }, + "editType": "calc", + "role": "object", + "tickvalssrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for tickvals .", + "editType": "none" + }, + "ticktextsrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for ticktext .", + "editType": "none" + } + }, + "xaxis": { + "valType": "subplotid", + "role": "info", + "dflt": "x", + "editType": "calc+clearAxisTypes", + "description": "Sets a reference between this trace's x coordinates and a 2D cartesian x axis. If *x* (the default value), the x coordinates refer to `layout.xaxis`. If *x2*, the x coordinates refer to `layout.xaxis2`, and so on." + }, + "yaxis": { + "valType": "subplotid", + "role": "info", + "dflt": "y", + "editType": "calc+clearAxisTypes", + "description": "Sets a reference between this trace's y coordinates and a 2D cartesian y axis. If *y* (the default value), the y coordinates refer to `layout.yaxis`. If *y2*, the y coordinates refer to `layout.xaxis2`, and so on." + }, + "idssrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for ids .", + "editType": "none" + }, + "customdatasrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for customdata .", + "editType": "none" + }, + "hoverinfosrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for hoverinfo .", + "editType": "none" + }, + "zsrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for z .", + "editType": "none" + }, + "xsrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for x .", + "editType": "none" + }, + "ysrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for y .", + "editType": "none" + }, + "textsrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for text .", + "editType": "none" + } + } + }, + "parcoords": { + "meta": { + "description": "Parallel coordinates for multidimensional exploratory data analysis. The samples are specified in `dimensions`. The colors are set in `line.color`." + }, + "attributes": { + "type": "parcoords", + "visible": { + "valType": "enumerated", + "values": [ + true, + false, + "legendonly" + ], + "role": "info", + "dflt": true, + "editType": "calc", + "description": "Determines whether or not this trace is visible. If *legendonly*, the trace is not drawn, but can appear as a legend item (provided that the legend itself is visible)." + }, + "showlegend": { + "valType": "boolean", + "role": "info", + "dflt": true, + "editType": "style", + "description": "Determines whether or not an item corresponding to this trace is shown in the legend." + }, + "legendgroup": { + "valType": "string", + "role": "info", + "dflt": "", + "editType": "style", + "description": "Sets the legend group for this trace. Traces part of the same legend group hide/show at the same time when toggling legend items." + }, + "opacity": { + "valType": "number", + "role": "style", + "min": 0, + "max": 1, + "dflt": 1, + "editType": "style", + "description": "Sets the opacity of the trace." + }, + "name": { + "valType": "string", + "role": "info", + "editType": "style", + "description": "Sets the trace name. The trace name appear as the legend item and on hover." + }, + "uid": { + "valType": "string", + "role": "info", + "dflt": "", + "editType": "calc" + }, + "ids": { + "valType": "data_array", + "editType": "calc", + "description": "Assigns id labels to each datum. These ids for object constancy of data points during animation.", + "role": "data" + }, + "customdata": { + "valType": "data_array", + "editType": "calc", + "description": "Assigns extra data each datum. This may be useful when listening to hover, click and selection events. Note that, *scatter* traces also appends customdata items in the markers DOM elements", + "role": "data" + }, + "selectedpoints": { + "valType": "any", + "role": "info", + "editType": "calc", + "description": "Array containing integer indices of selected points. Has an effect only for traces that support selections. Note that an empty array means an empty selection where the `unselected` are turned on for all points, whereas, any other non-array values means no selection all where the `selected` and `unselected` styles have no effect." + }, + "hoverinfo": { + "valType": "flaglist", + "role": "info", + "flags": [ + "x", + "y", + "z", + "text", + "name" + ], + "extras": [ + "all", + "none", + "skip" + ], + "arrayOk": true, + "dflt": "all", + "editType": "none", + "description": "Determines which trace information appear on hover. If `none` or `skip` are set, no information is displayed upon hovering. But, if `none` is set, click and hover events are still fired." + }, + "hoverlabel": { + "bgcolor": { + "valType": "color", + "role": "style", + "arrayOk": true, + "editType": "none", + "description": "Sets the background color of the hover labels for this trace" + }, + "bordercolor": { + "valType": "color", + "role": "style", + "arrayOk": true, + "editType": "none", + "description": "Sets the border color of the hover labels for this trace." + }, + "font": { + "family": { + "valType": "string", + "role": "style", + "noBlank": true, + "strict": true, + "editType": "none", + "description": "HTML font family - the typeface that will be applied by the web browser. The web browser will only be able to apply a font if it is available on the system which it operates. Provide multiple font families, separated by commas, to indicate the preference in which to apply fonts if they aren't available on the system. The plotly service (at https://plot.ly or on-premise) generates images on a server, where only a select number of fonts are installed and supported. These include *Arial*, *Balto*, *Courier New*, *Droid Sans*,, *Droid Serif*, *Droid Sans Mono*, *Gravitas One*, *Old Standard TT*, *Open Sans*, *Overpass*, *PT Sans Narrow*, *Raleway*, *Times New Roman*.", + "arrayOk": true + }, + "size": { + "valType": "number", + "role": "style", + "min": 1, + "editType": "none", + "arrayOk": true + }, + "color": { + "valType": "color", + "role": "style", + "editType": "none", + "arrayOk": true + }, + "editType": "none", + "description": "Sets the font used in hover labels.", + "role": "object", + "familysrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for family .", + "editType": "none" + }, + "sizesrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for size .", + "editType": "none" + }, + "colorsrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for color .", + "editType": "none" + } + }, + "namelength": { + "valType": "integer", + "min": -1, + "arrayOk": true, + "role": "style", + "editType": "none", + "description": "Sets the length (in number of characters) of the trace name in the hover labels for this trace. -1 shows the whole name regardless of length. 0-3 shows the first 0-3 characters, and an integer >3 will show the whole name if it is less than that many characters, but if it is longer, will truncate to `namelength - 3` characters and add an ellipsis." + }, + "editType": "calc", + "role": "object", + "bgcolorsrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for bgcolor .", + "editType": "none" + }, + "bordercolorsrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for bordercolor .", + "editType": "none" + }, + "namelengthsrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for namelength .", + "editType": "none" + } + }, + "stream": { + "token": { + "valType": "string", + "noBlank": true, + "strict": true, + "role": "info", + "editType": "calc", + "description": "The stream id number links a data trace on a plot with a stream. See https://plot.ly/settings for more details." + }, + "maxpoints": { + "valType": "number", + "min": 0, + "max": 10000, + "dflt": 500, + "role": "info", + "editType": "calc", + "description": "Sets the maximum number of points to keep on the plots from an incoming stream. If `maxpoints` is set to *50*, only the newest 50 points will be displayed on the plot." + }, + "editType": "calc", + "role": "object" + }, + "domain": { + "x": { + "valType": "info_array", + "role": "info", + "items": [ + { + "valType": "number", + "min": 0, + "max": 1, + "editType": "calc" + }, + { + "valType": "number", + "min": 0, + "max": 1, + "editType": "calc" + } + ], + "dflt": [ + 0, + 1 + ], + "editType": "calc", + "description": "Sets the horizontal domain of this `parcoords` trace (in plot fraction)." + }, + "y": { + "valType": "info_array", + "role": "info", + "items": [ + { + "valType": "number", + "min": 0, + "max": 1, + "editType": "calc" + }, + { + "valType": "number", + "min": 0, + "max": 1, + "editType": "calc" + } + ], + "dflt": [ + 0, + 1 + ], + "editType": "calc", + "description": "Sets the vertical domain of this `parcoords` trace (in plot fraction)." + }, + "editType": "calc", + "role": "object" + }, + "labelfont": { + "family": { + "valType": "string", + "role": "style", + "noBlank": true, + "strict": true, + "editType": "calc", + "description": "HTML font family - the typeface that will be applied by the web browser. The web browser will only be able to apply a font if it is available on the system which it operates. Provide multiple font families, separated by commas, to indicate the preference in which to apply fonts if they aren't available on the system. The plotly service (at https://plot.ly or on-premise) generates images on a server, where only a select number of fonts are installed and supported. These include *Arial*, *Balto*, *Courier New*, *Droid Sans*,, *Droid Serif*, *Droid Sans Mono*, *Gravitas One*, *Old Standard TT*, *Open Sans*, *Overpass*, *PT Sans Narrow*, *Raleway*, *Times New Roman*." + }, + "size": { + "valType": "number", + "role": "style", + "min": 1, + "editType": "calc" + }, + "color": { + "valType": "color", + "role": "style", + "editType": "calc" + }, + "editType": "calc", + "description": "Sets the font for the `dimension` labels.", + "role": "object" + }, + "tickfont": { + "family": { + "valType": "string", + "role": "style", + "noBlank": true, + "strict": true, + "editType": "calc", + "description": "HTML font family - the typeface that will be applied by the web browser. The web browser will only be able to apply a font if it is available on the system which it operates. Provide multiple font families, separated by commas, to indicate the preference in which to apply fonts if they aren't available on the system. The plotly service (at https://plot.ly or on-premise) generates images on a server, where only a select number of fonts are installed and supported. These include *Arial*, *Balto*, *Courier New*, *Droid Sans*,, *Droid Serif*, *Droid Sans Mono*, *Gravitas One*, *Old Standard TT*, *Open Sans*, *Overpass*, *PT Sans Narrow*, *Raleway*, *Times New Roman*." + }, + "size": { + "valType": "number", + "role": "style", + "min": 1, + "editType": "calc" + }, + "color": { + "valType": "color", + "role": "style", + "editType": "calc" + }, + "editType": "calc", + "description": "Sets the font for the `dimension` tick values.", + "role": "object" + }, + "rangefont": { + "family": { + "valType": "string", + "role": "style", + "noBlank": true, + "strict": true, + "editType": "calc", + "description": "HTML font family - the typeface that will be applied by the web browser. The web browser will only be able to apply a font if it is available on the system which it operates. Provide multiple font families, separated by commas, to indicate the preference in which to apply fonts if they aren't available on the system. The plotly service (at https://plot.ly or on-premise) generates images on a server, where only a select number of fonts are installed and supported. These include *Arial*, *Balto*, *Courier New*, *Droid Sans*,, *Droid Serif*, *Droid Sans Mono*, *Gravitas One*, *Old Standard TT*, *Open Sans*, *Overpass*, *PT Sans Narrow*, *Raleway*, *Times New Roman*." + }, + "size": { + "valType": "number", + "role": "style", + "min": 1, + "editType": "calc" + }, + "color": { + "valType": "color", + "role": "style", + "editType": "calc" + }, + "editType": "calc", + "description": "Sets the font for the `dimension` range values.", + "role": "object" + }, + "dimensions": { + "items": { + "dimension": { + "label": { + "valType": "string", + "role": "info", + "editType": "calc", + "description": "The shown name of the dimension." + }, + "tickvals": { + "valType": "data_array", + "editType": "calc", + "description": "Sets the values at which ticks on this axis appear. Only has an effect if `tickmode` is set to *array*. Used with `ticktext`.", + "role": "data" + }, + "ticktext": { + "valType": "data_array", + "editType": "calc", + "description": "Sets the text displayed at the ticks position via `tickvals`. Only has an effect if `tickmode` is set to *array*. Used with `tickvals`.", + "role": "data" + }, + "tickformat": { + "valType": "string", + "dflt": "3s", + "role": "style", + "editType": "calc", + "description": "Sets the tick label formatting rule using d3 formatting mini-language which is similar to those of Python. See https://github.com/d3/d3-format/blob/master/README.md#locale_format" + }, + "visible": { + "valType": "boolean", + "dflt": true, + "role": "info", + "editType": "calc", + "description": "Shows the dimension when set to `true` (the default). Hides the dimension for `false`." + }, + "range": { + "valType": "info_array", + "role": "info", + "items": [ + { + "valType": "number", + "editType": "calc" + }, + { + "valType": "number", + "editType": "calc" + } + ], + "editType": "calc", + "description": "The domain range that represents the full, shown axis extent. Defaults to the `values` extent. Must be an array of `[fromValue, toValue]` with finite numbers as elements." + }, + "constraintrange": { + "valType": "info_array", + "role": "info", + "items": [ + { + "valType": "number", + "editType": "calc" + }, + { + "valType": "number", + "editType": "calc" + } + ], + "editType": "calc", + "description": "The domain range to which the filter on the dimension is constrained. Must be an array of `[fromValue, toValue]` with finite numbers as elements." + }, + "values": { + "valType": "data_array", + "role": "data", + "dflt": [], + "editType": "calc", + "description": "Dimension values. `values[n]` represents the value of the `n`th point in the dataset, therefore the `values` vector for all dimensions must be the same (longer vectors will be truncated). Each value must be a finite number." + }, + "editType": "calc", + "description": "The dimensions (variables) of the parallel coordinates chart. 2..60 dimensions are supported.", + "role": "object", + "tickvalssrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for tickvals .", + "editType": "none" + }, + "ticktextsrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for ticktext .", + "editType": "none" + }, + "valuessrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for values .", + "editType": "none" + } + } + }, + "role": "object" + }, + "line": { + "color": { + "valType": "color", + "arrayOk": true, + "role": "style", + "editType": "calc", + "description": "Sets the line color. It accepts either a specific color or an array of numbers that are mapped to the colorscale relative to the max and min values of the array or relative to `cmin` and `cmax` if set." + }, + "colorscale": { + "valType": "colorscale", + "role": "style", + "editType": "calc", + "impliedEdits": { + "autocolorscale": false + }, + "description": "Sets the colorscale and only has an effect if `line.color` is set to a numerical array. The colorscale must be an array containing arrays mapping a normalized value to an rgb, rgba, hex, hsl, hsv, or named color string. At minimum, a mapping for the lowest (0) and highest (1) values are required. For example, `[[0, 'rgb(0,0,255)', [1, 'rgb(255,0,0)']]`. To control the bounds of the colorscale in color space, use `line.cmin` and `line.cmax`. Alternatively, `colorscale` may be a palette name string of the following list: Greys, YlGnBu, Greens, YlOrRd, Bluered, RdBu, Reds, Blues, Picnic, Rainbow, Portland, Jet, Hot, Blackbody, Earth, Electric, Viridis", + "dflt": [ + [ + 0, + "#440154" + ], + [ + 0.06274509803921569, + "#48186a" + ], + [ + 0.12549019607843137, + "#472d7b" + ], + [ + 0.18823529411764706, + "#424086" + ], + [ + 0.25098039215686274, + "#3b528b" + ], + [ + 0.3137254901960784, + "#33638d" + ], + [ + 0.3764705882352941, + "#2c728e" + ], + [ + 0.4392156862745098, + "#26828e" + ], + [ + 0.5019607843137255, + "#21918c" + ], + [ + 0.5647058823529412, + "#1fa088" + ], + [ + 0.6274509803921569, + "#28ae80" + ], + [ + 0.6901960784313725, + "#3fbc73" + ], + [ + 0.7529411764705882, + "#5ec962" + ], + [ + 0.8156862745098039, + "#84d44b" + ], + [ + 0.8784313725490196, + "#addc30" + ], + [ + 0.9411764705882353, + "#d8e219" + ], + [ + 1, + "#fde725" + ] + ] + }, + "cauto": { + "valType": "boolean", + "role": "info", + "dflt": true, + "editType": "calc", + "impliedEdits": {}, + "description": "Has an effect only if `line.color` is set to a numerical array and `cmin`, `cmax` are set by the user. In this case, it controls whether the range of colors in `colorscale` is mapped to the range of values in the `color` array (`cauto: true`), or the `cmin`/`cmax` values (`cauto: false`). Defaults to `false` when `cmin`, `cmax` are set by the user." + }, + "cmax": { + "valType": "number", + "role": "info", + "dflt": null, + "editType": "calc", + "impliedEdits": { + "cauto": false + }, + "description": "Has an effect only if `line.color` is set to a numerical array. Sets the upper bound of the color domain. Value should be associated to the `line.color` array index, and if set, `line.cmin` must be set as well." + }, + "cmin": { + "valType": "number", + "role": "info", + "dflt": null, + "editType": "calc", + "impliedEdits": { + "cauto": false + }, + "description": "Has an effect only if `line.color` is set to a numerical array. Sets the lower bound of the color domain. Value should be associated to the `line.color` array index, and if set, `line.cmax` must be set as well." + }, + "autocolorscale": { + "valType": "boolean", + "role": "style", + "dflt": false, + "editType": "calc", + "impliedEdits": {}, + "description": "Has an effect only if line.color` is set to a numerical array. Determines whether the colorscale is a default palette (`autocolorscale: true`) or the palette determined by `line.colorscale`. In case `colorscale` is unspecified or `autocolorscale` is true, the default palette will be chosen according to whether numbers in the `color` array are all positive, all negative or mixed. The default value is false, so that `parcoords` colorscale can default to `Viridis`." + }, + "reversescale": { + "valType": "boolean", + "role": "style", + "dflt": false, + "editType": "calc", + "description": "Has an effect only if `line.color` is set to a numerical array. Reverses the color mapping if true (`cmin` will correspond to the last color in the array and `cmax` will correspond to the first color)." + }, + "showscale": { + "valType": "boolean", + "role": "info", + "dflt": false, + "editType": "calc", + "description": "Has an effect only if `line.color` is set to a numerical array. Determines whether or not a colorbar is displayed." + }, + "colorbar": { + "thicknessmode": { + "valType": "enumerated", + "values": [ + "fraction", + "pixels" + ], + "role": "style", + "dflt": "pixels", + "description": "Determines whether this color bar's thickness (i.e. the measure in the constant color direction) is set in units of plot *fraction* or in *pixels*. Use `thickness` to set the value.", + "editType": "colorbars" + }, + "thickness": { + "valType": "number", + "role": "style", + "min": 0, + "dflt": 30, + "description": "Sets the thickness of the color bar This measure excludes the size of the padding, ticks and labels.", + "editType": "colorbars" + }, + "lenmode": { + "valType": "enumerated", + "values": [ + "fraction", + "pixels" + ], + "role": "info", + "dflt": "fraction", + "description": "Determines whether this color bar's length (i.e. the measure in the color variation direction) is set in units of plot *fraction* or in *pixels. Use `len` to set the value.", + "editType": "colorbars" + }, + "len": { + "valType": "number", + "min": 0, + "dflt": 1, + "role": "style", + "description": "Sets the length of the color bar This measure excludes the padding of both ends. That is, the color bar length is this length minus the padding on both ends.", + "editType": "colorbars" + }, + "x": { + "valType": "number", + "dflt": 1.02, + "min": -2, + "max": 3, + "role": "style", + "description": "Sets the x position of the color bar (in plot fraction).", + "editType": "colorbars" + }, + "xanchor": { + "valType": "enumerated", + "values": [ + "left", + "center", + "right" + ], + "dflt": "left", + "role": "style", + "description": "Sets this color bar's horizontal position anchor. This anchor binds the `x` position to the *left*, *center* or *right* of the color bar.", + "editType": "colorbars" + }, + "xpad": { + "valType": "number", + "role": "style", + "min": 0, + "dflt": 10, + "description": "Sets the amount of padding (in px) along the x direction.", + "editType": "colorbars" + }, + "y": { + "valType": "number", + "role": "style", + "dflt": 0.5, + "min": -2, + "max": 3, + "description": "Sets the y position of the color bar (in plot fraction).", + "editType": "colorbars" + }, + "yanchor": { + "valType": "enumerated", + "values": [ + "top", + "middle", + "bottom" + ], + "role": "style", + "dflt": "middle", + "description": "Sets this color bar's vertical position anchor This anchor binds the `y` position to the *top*, *middle* or *bottom* of the color bar.", + "editType": "colorbars" + }, + "ypad": { + "valType": "number", + "role": "style", + "min": 0, + "dflt": 10, + "description": "Sets the amount of padding (in px) along the y direction.", + "editType": "colorbars" + }, + "outlinecolor": { + "valType": "color", + "dflt": "#444", + "role": "style", + "editType": "colorbars", + "description": "Sets the axis line color." + }, + "outlinewidth": { + "valType": "number", + "min": 0, + "dflt": 1, + "role": "style", + "editType": "colorbars", + "description": "Sets the width (in px) of the axis line." + }, + "bordercolor": { + "valType": "color", + "dflt": "#444", + "role": "style", + "editType": "colorbars", + "description": "Sets the axis line color." + }, + "borderwidth": { + "valType": "number", + "role": "style", + "min": 0, + "dflt": 0, + "description": "Sets the width (in px) or the border enclosing this color bar.", + "editType": "colorbars" + }, + "bgcolor": { + "valType": "color", + "role": "style", + "dflt": "rgba(0,0,0,0)", + "description": "Sets the color of padded area.", + "editType": "colorbars" + }, + "tickmode": { + "valType": "enumerated", + "values": [ + "auto", + "linear", + "array" + ], + "role": "info", + "editType": "colorbars", + "impliedEdits": {}, + "description": "Sets the tick mode for this axis. If *auto*, the number of ticks is set via `nticks`. If *linear*, the placement of the ticks is determined by a starting position `tick0` and a tick step `dtick` (*linear* is the default value if `tick0` and `dtick` are provided). If *array*, the placement of the ticks is set via `tickvals` and the tick text is `ticktext`. (*array* is the default value if `tickvals` is provided)." + }, + "nticks": { + "valType": "integer", + "min": 0, + "dflt": 0, + "role": "style", + "editType": "colorbars", + "description": "Specifies the maximum number of ticks for the particular axis. The actual number of ticks will be chosen automatically to be less than or equal to `nticks`. Has an effect only if `tickmode` is set to *auto*." + }, + "tick0": { + "valType": "any", + "role": "style", + "editType": "colorbars", + "impliedEdits": { + "tickmode": "linear" + }, + "description": "Sets the placement of the first tick on this axis. Use with `dtick`. If the axis `type` is *log*, then you must take the log of your starting tick (e.g. to set the starting tick to 100, set the `tick0` to 2) except when `dtick`=*L* (see `dtick` for more info). If the axis `type` is *date*, it should be a date string, like date data. If the axis `type` is *category*, it should be a number, using the scale where each category is assigned a serial number from zero in the order it appears." + }, + "dtick": { + "valType": "any", + "role": "style", + "editType": "colorbars", + "impliedEdits": { + "tickmode": "linear" + }, + "description": "Sets the step in-between ticks on this axis. Use with `tick0`. Must be a positive number, or special strings available to *log* and *date* axes. If the axis `type` is *log*, then ticks are set every 10^(n*dtick) where n is the tick number. For example, to set a tick mark at 1, 10, 100, 1000, ... set dtick to 1. To set tick marks at 1, 100, 10000, ... set dtick to 2. To set tick marks at 1, 5, 25, 125, 625, 3125, ... set dtick to log_10(5), or 0.69897000433. *log* has several special values; *L*, where `f` is a positive number, gives ticks linearly spaced in value (but not position). For example `tick0` = 0.1, `dtick` = *L0.5* will put ticks at 0.1, 0.6, 1.1, 1.6 etc. To show powers of 10 plus small digits between, use *D1* (all digits) or *D2* (only 2 and 5). `tick0` is ignored for *D1* and *D2*. If the axis `type` is *date*, then you must convert the time to milliseconds. For example, to set the interval between ticks to one day, set `dtick` to 86400000.0. *date* also has special values *M* gives ticks spaced by a number of months. `n` must be a positive integer. To set ticks on the 15th of every third month, set `tick0` to *2000-01-15* and `dtick` to *M3*. To set ticks every 4 years, set `dtick` to *M48*" + }, + "tickvals": { + "valType": "data_array", + "editType": "colorbars", + "description": "Sets the values at which ticks on this axis appear. Only has an effect if `tickmode` is set to *array*. Used with `ticktext`.", + "role": "data" + }, + "ticktext": { + "valType": "data_array", + "editType": "colorbars", + "description": "Sets the text displayed at the ticks position via `tickvals`. Only has an effect if `tickmode` is set to *array*. Used with `tickvals`.", + "role": "data" + }, + "ticks": { + "valType": "enumerated", + "values": [ + "outside", + "inside", + "" + ], + "role": "style", + "editType": "colorbars", + "description": "Determines whether ticks are drawn or not. If **, this axis' ticks are not drawn. If *outside* (*inside*), this axis' are drawn outside (inside) the axis lines.", + "dflt": "" + }, + "ticklen": { + "valType": "number", + "min": 0, + "dflt": 5, + "role": "style", + "editType": "colorbars", + "description": "Sets the tick length (in px)." + }, + "tickwidth": { + "valType": "number", + "min": 0, + "dflt": 1, + "role": "style", + "editType": "colorbars", + "description": "Sets the tick width (in px)." + }, + "tickcolor": { + "valType": "color", + "dflt": "#444", + "role": "style", + "editType": "colorbars", + "description": "Sets the tick color." + }, + "showticklabels": { + "valType": "boolean", + "dflt": true, + "role": "style", + "editType": "colorbars", + "description": "Determines whether or not the tick labels are drawn." + }, + "tickfont": { + "family": { + "valType": "string", + "role": "style", + "noBlank": true, + "strict": true, + "description": "HTML font family - the typeface that will be applied by the web browser. The web browser will only be able to apply a font if it is available on the system which it operates. Provide multiple font families, separated by commas, to indicate the preference in which to apply fonts if they aren't available on the system. The plotly service (at https://plot.ly or on-premise) generates images on a server, where only a select number of fonts are installed and supported. These include *Arial*, *Balto*, *Courier New*, *Droid Sans*,, *Droid Serif*, *Droid Sans Mono*, *Gravitas One*, *Old Standard TT*, *Open Sans*, *Overpass*, *PT Sans Narrow*, *Raleway*, *Times New Roman*.", + "editType": "colorbars" + }, + "size": { + "valType": "number", + "role": "style", + "min": 1, + "editType": "colorbars" + }, + "color": { + "valType": "color", + "role": "style", + "editType": "colorbars" + }, + "description": "Sets the color bar's tick label font", + "editType": "colorbars", + "role": "object" + }, + "tickangle": { + "valType": "angle", + "dflt": "auto", + "role": "style", + "editType": "colorbars", + "description": "Sets the angle of the tick labels with respect to the horizontal. For example, a `tickangle` of -90 draws the tick labels vertically." + }, + "tickformat": { + "valType": "string", + "dflt": "", + "role": "style", + "editType": "colorbars", + "description": "Sets the tick label formatting rule using d3 formatting mini-languages which are very similar to those in Python. For numbers, see: https://github.com/d3/d3-format/blob/master/README.md#locale_format And for dates see: https://github.com/d3/d3-time-format/blob/master/README.md#locale_format We add one item to d3's date formatter: *%{n}f* for fractional seconds with n digits. For example, *2016-10-13 09:15:23.456* with tickformat *%H~%M~%S.%2f* would display *09~15~23.46*" + }, + "tickformatstops": { + "items": { + "tickformatstop": { + "dtickrange": { + "valType": "info_array", + "role": "info", + "items": [ + { + "valType": "any", + "editType": "colorbars" + }, + { + "valType": "any", + "editType": "colorbars" + } + ], + "editType": "colorbars", + "description": "range [*min*, *max*], where *min*, *max* - dtick values which describe some zoom level, it is possible to omit *min* or *max* value by passing *null*" + }, + "value": { + "valType": "string", + "dflt": "", + "role": "style", + "editType": "colorbars", + "description": "string - dtickformat for described zoom level, the same as *tickformat*" + }, + "editType": "colorbars", + "role": "object" + } + }, + "role": "object" + }, + "tickprefix": { + "valType": "string", + "dflt": "", + "role": "style", + "editType": "colorbars", + "description": "Sets a tick label prefix." + }, + "showtickprefix": { + "valType": "enumerated", + "values": [ + "all", + "first", + "last", + "none" + ], + "dflt": "all", + "role": "style", + "editType": "colorbars", + "description": "If *all*, all tick labels are displayed with a prefix. If *first*, only the first tick is displayed with a prefix. If *last*, only the last tick is displayed with a suffix. If *none*, tick prefixes are hidden." + }, + "ticksuffix": { + "valType": "string", + "dflt": "", + "role": "style", + "editType": "colorbars", + "description": "Sets a tick label suffix." + }, + "showticksuffix": { + "valType": "enumerated", + "values": [ + "all", + "first", + "last", + "none" + ], + "dflt": "all", + "role": "style", + "editType": "colorbars", + "description": "Same as `showtickprefix` but for tick suffixes." + }, + "separatethousands": { + "valType": "boolean", + "dflt": false, + "role": "style", + "editType": "colorbars", + "description": "If \"true\", even 4-digit integers are separated" + }, + "exponentformat": { + "valType": "enumerated", + "values": [ + "none", + "e", + "E", + "power", + "SI", + "B" + ], + "dflt": "B", + "role": "style", + "editType": "colorbars", + "description": "Determines a formatting rule for the tick exponents. For example, consider the number 1,000,000,000. If *none*, it appears as 1,000,000,000. If *e*, 1e+9. If *E*, 1E+9. If *power*, 1x10^9 (with 9 in a super script). If *SI*, 1G. If *B*, 1B." + }, + "showexponent": { + "valType": "enumerated", + "values": [ + "all", + "first", + "last", + "none" + ], + "dflt": "all", + "role": "style", + "editType": "colorbars", + "description": "If *all*, all exponents are shown besides their significands. If *first*, only the exponent of the first tick is shown. If *last*, only the exponent of the last tick is shown. If *none*, no exponents appear." + }, + "title": { + "valType": "string", + "role": "info", + "dflt": "Click to enter colorscale title", + "description": "Sets the title of the color bar.", + "editType": "colorbars" + }, + "titlefont": { + "family": { + "valType": "string", + "role": "style", + "noBlank": true, + "strict": true, + "description": "HTML font family - the typeface that will be applied by the web browser. The web browser will only be able to apply a font if it is available on the system which it operates. Provide multiple font families, separated by commas, to indicate the preference in which to apply fonts if they aren't available on the system. The plotly service (at https://plot.ly or on-premise) generates images on a server, where only a select number of fonts are installed and supported. These include *Arial*, *Balto*, *Courier New*, *Droid Sans*,, *Droid Serif*, *Droid Sans Mono*, *Gravitas One*, *Old Standard TT*, *Open Sans*, *Overpass*, *PT Sans Narrow*, *Raleway*, *Times New Roman*.", + "editType": "colorbars" + }, + "size": { + "valType": "number", + "role": "style", + "min": 1, + "editType": "colorbars" + }, + "color": { + "valType": "color", + "role": "style", + "editType": "colorbars" + }, + "description": "Sets this color bar's title font.", + "editType": "colorbars", + "role": "object" + }, + "titleside": { + "valType": "enumerated", + "values": [ + "right", + "top", + "bottom" + ], + "role": "style", + "dflt": "top", + "description": "Determines the location of the colorbar title with respect to the color bar.", + "editType": "colorbars" + }, + "editType": "colorbars", + "role": "object", + "tickvalssrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for tickvals .", + "editType": "none" + }, + "ticktextsrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for ticktext .", + "editType": "none" + } + }, + "editType": "calc", + "role": "object", + "colorsrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for color .", + "editType": "none" + } + }, + "idssrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for ids .", + "editType": "none" + }, + "customdatasrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for customdata .", + "editType": "none" + }, + "hoverinfosrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for hoverinfo .", + "editType": "none" + } + } + }, + "parcats": { + "meta": { + "description": "Parallel categories diagram for multidimensional categorical data." + }, + "attributes": { + "type": "parcats", + "visible": { + "valType": "enumerated", + "values": [ + true, + false, + "legendonly" + ], + "role": "info", + "dflt": true, + "editType": "calc", + "description": "Determines whether or not this trace is visible. If *legendonly*, the trace is not drawn, but can appear as a legend item (provided that the legend itself is visible)." + }, + "showlegend": { + "valType": "boolean", + "role": "info", + "dflt": true, + "editType": "style", + "description": "Determines whether or not an item corresponding to this trace is shown in the legend." + }, + "legendgroup": { + "valType": "string", + "role": "info", + "dflt": "", + "editType": "style", + "description": "Sets the legend group for this trace. Traces part of the same legend group hide/show at the same time when toggling legend items." + }, + "opacity": { + "valType": "number", + "role": "style", + "min": 0, + "max": 1, + "dflt": 1, + "editType": "style", + "description": "Sets the opacity of the trace." + }, + "name": { + "valType": "string", + "role": "info", + "editType": "style", + "description": "Sets the trace name. The trace name appear as the legend item and on hover." + }, + "uid": { + "valType": "string", + "role": "info", + "dflt": "", + "editType": "calc" + }, + "ids": { + "valType": "data_array", + "editType": "calc", + "description": "Assigns id labels to each datum. These ids for object constancy of data points during animation.", + "role": "data" + }, + "customdata": { + "valType": "data_array", + "editType": "calc", + "description": "Assigns extra data each datum. This may be useful when listening to hover, click and selection events. Note that, *scatter* traces also appends customdata items in the markers DOM elements", + "role": "data" + }, + "selectedpoints": { + "valType": "any", + "role": "info", + "editType": "calc", + "description": "Array containing integer indices of selected points. Has an effect only for traces that support selections. Note that an empty array means an empty selection where the `unselected` are turned on for all points, whereas, any other non-array values means no selection all where the `selected` and `unselected` styles have no effect." + }, + "hoverinfo": { + "valType": "flaglist", + "role": "info", + "flags": [ + "x", + "y", + "z", + "text", + "name" + ], + "extras": [ + "all", + "none", + "skip" + ], + "arrayOk": true, + "dflt": "all", + "editType": "none", + "description": "Determines which trace information appear on hover. If `none` or `skip` are set, no information is displayed upon hovering. But, if `none` is set, click and hover events are still fired." + }, + "hoverlabel": { + "bgcolor": { + "valType": "color", + "role": "style", + "arrayOk": true, + "editType": "none", + "description": "Sets the background color of the hover labels for this trace" + }, + "bordercolor": { + "valType": "color", + "role": "style", + "arrayOk": true, + "editType": "none", + "description": "Sets the border color of the hover labels for this trace." + }, + "font": { + "family": { + "valType": "string", + "role": "style", + "noBlank": true, + "strict": true, + "editType": "none", + "description": "HTML font family - the typeface that will be applied by the web browser. The web browser will only be able to apply a font if it is available on the system which it operates. Provide multiple font families, separated by commas, to indicate the preference in which to apply fonts if they aren't available on the system. The plotly service (at https://plot.ly or on-premise) generates images on a server, where only a select number of fonts are installed and supported. These include *Arial*, *Balto*, *Courier New*, *Droid Sans*,, *Droid Serif*, *Droid Sans Mono*, *Gravitas One*, *Old Standard TT*, *Open Sans*, *Overpass*, *PT Sans Narrow*, *Raleway*, *Times New Roman*.", + "arrayOk": true + }, + "size": { + "valType": "number", + "role": "style", + "min": 1, + "editType": "none", + "arrayOk": true + }, + "color": { + "valType": "color", + "role": "style", + "editType": "none", + "arrayOk": true + }, + "editType": "none", + "description": "Sets the font used in hover labels.", + "role": "object", + "familysrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for family .", + "editType": "none" + }, + "sizesrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for size .", + "editType": "none" + }, + "colorsrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for color .", + "editType": "none" + } + }, + "namelength": { + "valType": "integer", + "min": -1, + "arrayOk": true, + "role": "style", + "editType": "none", + "description": "Sets the length (in number of characters) of the trace name in the hover labels for this trace. -1 shows the whole name regardless of length. 0-3 shows the first 0-3 characters, and an integer >3 will show the whole name if it is less than that many characters, but if it is longer, will truncate to `namelength - 3` characters and add an ellipsis." + }, + "editType": "calc", + "role": "object", + "bgcolorsrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for bgcolor .", + "editType": "none" + }, + "bordercolorsrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for bordercolor .", + "editType": "none" + }, + "namelengthsrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for namelength .", + "editType": "none" + } + }, + "stream": { + "token": { + "valType": "string", + "noBlank": true, + "strict": true, + "role": "info", + "editType": "calc", + "description": "The stream id number links a data trace on a plot with a stream. See https://plot.ly/settings for more details." + }, + "maxpoints": { + "valType": "number", + "min": 0, + "max": 10000, + "dflt": 500, + "role": "info", + "editType": "calc", + "description": "Sets the maximum number of points to keep on the plots from an incoming stream. If `maxpoints` is set to *50*, only the newest 50 points will be displayed on the plot." + }, + "editType": "calc", + "role": "object" + }, + "domain": { + "x": { + "valType": "info_array", + "role": "info", + "items": [ + { + "valType": "number", + "min": 0, + "max": 1, + "editType": "calc" + }, + { + "valType": "number", + "min": 0, + "max": 1, + "editType": "calc" + } + ], + "dflt": [ + 0, + 1 + ], + "editType": "calc", + "description": "Sets the horizontal domain of this `parcats` trace (in plot fraction)." + }, + "y": { + "valType": "info_array", + "role": "info", + "items": [ + { + "valType": "number", + "min": 0, + "max": 1, + "editType": "calc" + }, + { + "valType": "number", + "min": 0, + "max": 1, + "editType": "calc" + } + ], + "dflt": [ + 0, + 1 + ], + "editType": "calc", + "description": "Sets the vertical domain of this `parcats` trace (in plot fraction)." + }, + "editType": "calc", + "role": "object" + }, + "tooltip": { + "valType": "boolean", + "dflt": true, + "role": "info", + "editType": "plot", + "description": "Shows a tooltip when hover mode is `category` or `color`." + }, + "hovermode": { + "valType": "enumerated", + "values": [ + "none", + "category", + "color" + ], + "dflt": "category", + "role": "info", + "editType": "plot", + "description": "Sets the hover mode of the parcats diagram" + }, + "bundlecolors": { + "valType": "boolean", + "dflt": true, + "role": "info", + "editType": "plot", + "description": "Sort paths so that like colors are bundled together" + }, + "dimensions": { + "items": { + "dimension": { + "label": { + "valType": "string", + "role": "info", + "editType": "calc", + "description": "The shown name of the dimension." + }, + "catDisplayInds": { + "valType": "data_array", + "role": "data", + "editType": "calc", + "dflt": [], + "description": "" + }, + "catValues": { + "valType": "data_array", + "role": "data", + "editType": "calc", + "dflt": [], + "description": "" + }, + "catLabels": { + "valType": "data_array", + "role": "data", + "editType": "calc", + "dflt": [], + "description": "" + }, + "visible": { + "valType": "boolean", + "dflt": true, + "role": "info", + "editType": "calc", + "description": "Shows the dimension when set to `true` (the default). Hides the dimension for `false`." + }, + "values": { + "valType": "data_array", + "role": "data", + "dflt": [], + "editType": "calc", + "description": "Dimension values. `values[n]` represents the category value of the `n`th point in the dataset, therefore the `values` vector for all dimensions must be the same (longer vectors will be truncated). Each value must an element of `catValues`." + }, + "displayInd": { + "valType": "integer", + "role": "info", + "editType": "calc", + "description": "The display index of dimension, from left to right, zero indexed, defaults to dimensionindex." + }, + "editType": "calc", + "description": "The dimensions (variables) of the parallel categories diagram.", + "role": "object", + "catDisplayIndssrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for catDisplayInds .", + "editType": "none" + }, + "catValuessrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for catValues .", + "editType": "none" + }, + "catLabelssrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for catLabels .", + "editType": "none" + }, + "valuessrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for values .", + "editType": "none" + } + } + }, + "role": "object" + }, + "marker": { + "editType": "calc", + "color": { + "valType": "color", + "arrayOk": true, + "role": "style", + "editType": "calc", + "description": "Sets the marker color. It accepts either a specific color or an array of numbers that are mapped to the colorscale relative to the max and min values of the array or relative to `cmin` and `cmax` if set." + }, + "colorscale": { + "valType": "colorscale", + "role": "style", + "editType": "calc", + "impliedEdits": { + "autocolorscale": false + }, + "description": "Sets the colorscale and only has an effect if `marker.color` is set to a numerical array. The colorscale must be an array containing arrays mapping a normalized value to an rgb, rgba, hex, hsl, hsv, or named color string. At minimum, a mapping for the lowest (0) and highest (1) values are required. For example, `[[0, 'rgb(0,0,255)', [1, 'rgb(255,0,0)']]`. To control the bounds of the colorscale in color space, use `marker.cmin` and `marker.cmax`. Alternatively, `colorscale` may be a palette name string of the following list: Greys, YlGnBu, Greens, YlOrRd, Bluered, RdBu, Reds, Blues, Picnic, Rainbow, Portland, Jet, Hot, Blackbody, Earth, Electric, Viridis" + }, + "cauto": { + "valType": "boolean", + "role": "info", + "dflt": true, + "editType": "calc", + "impliedEdits": {}, + "description": "Has an effect only if `marker.color` is set to a numerical array and `cmin`, `cmax` are set by the user. In this case, it controls whether the range of colors in `colorscale` is mapped to the range of values in the `color` array (`cauto: true`), or the `cmin`/`cmax` values (`cauto: false`). Defaults to `false` when `cmin`, `cmax` are set by the user." + }, + "cmax": { + "valType": "number", + "role": "info", + "dflt": null, + "editType": "calc", + "impliedEdits": { + "cauto": false + }, + "description": "Has an effect only if `marker.color` is set to a numerical array. Sets the upper bound of the color domain. Value should be associated to the `marker.color` array index, and if set, `marker.cmin` must be set as well." + }, + "cmin": { + "valType": "number", + "role": "info", + "dflt": null, + "editType": "calc", + "impliedEdits": { + "cauto": false + }, + "description": "Has an effect only if `marker.color` is set to a numerical array. Sets the lower bound of the color domain. Value should be associated to the `marker.color` array index, and if set, `marker.cmax` must be set as well." + }, + "autocolorscale": { + "valType": "boolean", + "role": "style", + "dflt": true, + "editType": "calc", + "impliedEdits": {}, + "description": "Has an effect only if `marker.color` is set to a numerical array. Determines whether the colorscale is a default palette (`autocolorscale: true`) or the palette determined by `marker.colorscale`. In case `colorscale` is unspecified or `autocolorscale` is true, the default palette will be chosen according to whether numbers in the `color` array are all positive, all negative or mixed." + }, + "reversescale": { + "valType": "boolean", + "role": "style", + "dflt": false, + "editType": "calc", + "description": "Has an effect only if `marker.color` is set to a numerical array. Reverses the color mapping if true (`cmin` will correspond to the last color in the array and `cmax` will correspond to the first color)." + }, + "showscale": { + "valType": "boolean", + "role": "info", + "dflt": false, + "editType": "calc", + "description": "Has an effect only if `marker.color` is set to a numerical array. Determines whether or not a colorbar is displayed." + }, + "colorbar": { + "thicknessmode": { + "valType": "enumerated", + "values": [ + "fraction", + "pixels" + ], + "role": "style", + "dflt": "pixels", + "description": "Determines whether this color bar's thickness (i.e. the measure in the constant color direction) is set in units of plot *fraction* or in *pixels*. Use `thickness` to set the value.", + "editType": "colorbars" + }, + "thickness": { + "valType": "number", + "role": "style", + "min": 0, + "dflt": 30, + "description": "Sets the thickness of the color bar This measure excludes the size of the padding, ticks and labels.", + "editType": "colorbars" + }, + "lenmode": { + "valType": "enumerated", + "values": [ + "fraction", + "pixels" + ], + "role": "info", + "dflt": "fraction", + "description": "Determines whether this color bar's length (i.e. the measure in the color variation direction) is set in units of plot *fraction* or in *pixels. Use `len` to set the value.", + "editType": "colorbars" + }, + "len": { + "valType": "number", + "min": 0, + "dflt": 1, + "role": "style", + "description": "Sets the length of the color bar This measure excludes the padding of both ends. That is, the color bar length is this length minus the padding on both ends.", + "editType": "colorbars" + }, + "x": { + "valType": "number", + "dflt": 1.02, + "min": -2, + "max": 3, + "role": "style", + "description": "Sets the x position of the color bar (in plot fraction).", + "editType": "colorbars" + }, + "xanchor": { + "valType": "enumerated", + "values": [ + "left", + "center", + "right" + ], + "dflt": "left", + "role": "style", + "description": "Sets this color bar's horizontal position anchor. This anchor binds the `x` position to the *left*, *center* or *right* of the color bar.", + "editType": "colorbars" + }, + "xpad": { + "valType": "number", + "role": "style", + "min": 0, + "dflt": 10, + "description": "Sets the amount of padding (in px) along the x direction.", + "editType": "colorbars" + }, + "y": { + "valType": "number", + "role": "style", + "dflt": 0.5, + "min": -2, + "max": 3, + "description": "Sets the y position of the color bar (in plot fraction).", + "editType": "colorbars" + }, + "yanchor": { + "valType": "enumerated", + "values": [ + "top", + "middle", + "bottom" + ], + "role": "style", + "dflt": "middle", + "description": "Sets this color bar's vertical position anchor This anchor binds the `y` position to the *top*, *middle* or *bottom* of the color bar.", + "editType": "colorbars" + }, + "ypad": { + "valType": "number", + "role": "style", + "min": 0, + "dflt": 10, + "description": "Sets the amount of padding (in px) along the y direction.", + "editType": "colorbars" + }, + "outlinecolor": { + "valType": "color", + "dflt": "#444", + "role": "style", + "editType": "colorbars", + "description": "Sets the axis line color." + }, + "outlinewidth": { + "valType": "number", + "min": 0, + "dflt": 1, + "role": "style", + "editType": "colorbars", + "description": "Sets the width (in px) of the axis line." + }, + "bordercolor": { + "valType": "color", + "dflt": "#444", + "role": "style", + "editType": "colorbars", + "description": "Sets the axis line color." + }, + "borderwidth": { + "valType": "number", + "role": "style", + "min": 0, + "dflt": 0, + "description": "Sets the width (in px) or the border enclosing this color bar.", + "editType": "colorbars" + }, + "bgcolor": { + "valType": "color", + "role": "style", + "dflt": "rgba(0,0,0,0)", + "description": "Sets the color of padded area.", + "editType": "colorbars" + }, + "tickmode": { + "valType": "enumerated", + "values": [ + "auto", + "linear", + "array" + ], + "role": "info", + "editType": "colorbars", + "impliedEdits": {}, + "description": "Sets the tick mode for this axis. If *auto*, the number of ticks is set via `nticks`. If *linear*, the placement of the ticks is determined by a starting position `tick0` and a tick step `dtick` (*linear* is the default value if `tick0` and `dtick` are provided). If *array*, the placement of the ticks is set via `tickvals` and the tick text is `ticktext`. (*array* is the default value if `tickvals` is provided)." + }, + "nticks": { + "valType": "integer", + "min": 0, + "dflt": 0, + "role": "style", + "editType": "colorbars", + "description": "Specifies the maximum number of ticks for the particular axis. The actual number of ticks will be chosen automatically to be less than or equal to `nticks`. Has an effect only if `tickmode` is set to *auto*." + }, + "tick0": { + "valType": "any", + "role": "style", + "editType": "colorbars", + "impliedEdits": { + "tickmode": "linear" + }, + "description": "Sets the placement of the first tick on this axis. Use with `dtick`. If the axis `type` is *log*, then you must take the log of your starting tick (e.g. to set the starting tick to 100, set the `tick0` to 2) except when `dtick`=*L* (see `dtick` for more info). If the axis `type` is *date*, it should be a date string, like date data. If the axis `type` is *category*, it should be a number, using the scale where each category is assigned a serial number from zero in the order it appears." + }, + "dtick": { + "valType": "any", + "role": "style", + "editType": "colorbars", + "impliedEdits": { + "tickmode": "linear" + }, + "description": "Sets the step in-between ticks on this axis. Use with `tick0`. Must be a positive number, or special strings available to *log* and *date* axes. If the axis `type` is *log*, then ticks are set every 10^(n*dtick) where n is the tick number. For example, to set a tick mark at 1, 10, 100, 1000, ... set dtick to 1. To set tick marks at 1, 100, 10000, ... set dtick to 2. To set tick marks at 1, 5, 25, 125, 625, 3125, ... set dtick to log_10(5), or 0.69897000433. *log* has several special values; *L*, where `f` is a positive number, gives ticks linearly spaced in value (but not position). For example `tick0` = 0.1, `dtick` = *L0.5* will put ticks at 0.1, 0.6, 1.1, 1.6 etc. To show powers of 10 plus small digits between, use *D1* (all digits) or *D2* (only 2 and 5). `tick0` is ignored for *D1* and *D2*. If the axis `type` is *date*, then you must convert the time to milliseconds. For example, to set the interval between ticks to one day, set `dtick` to 86400000.0. *date* also has special values *M* gives ticks spaced by a number of months. `n` must be a positive integer. To set ticks on the 15th of every third month, set `tick0` to *2000-01-15* and `dtick` to *M3*. To set ticks every 4 years, set `dtick` to *M48*" + }, + "tickvals": { + "valType": "data_array", + "editType": "colorbars", + "description": "Sets the values at which ticks on this axis appear. Only has an effect if `tickmode` is set to *array*. Used with `ticktext`.", + "role": "data" + }, + "ticktext": { + "valType": "data_array", + "editType": "colorbars", + "description": "Sets the text displayed at the ticks position via `tickvals`. Only has an effect if `tickmode` is set to *array*. Used with `tickvals`.", + "role": "data" + }, + "ticks": { + "valType": "enumerated", + "values": [ + "outside", + "inside", + "" + ], + "role": "style", + "editType": "colorbars", + "description": "Determines whether ticks are drawn or not. If **, this axis' ticks are not drawn. If *outside* (*inside*), this axis' are drawn outside (inside) the axis lines.", + "dflt": "" + }, + "ticklen": { + "valType": "number", + "min": 0, + "dflt": 5, + "role": "style", + "editType": "colorbars", + "description": "Sets the tick length (in px)." + }, + "tickwidth": { + "valType": "number", + "min": 0, + "dflt": 1, + "role": "style", + "editType": "colorbars", + "description": "Sets the tick width (in px)." + }, + "tickcolor": { + "valType": "color", + "dflt": "#444", + "role": "style", + "editType": "colorbars", + "description": "Sets the tick color." + }, + "showticklabels": { + "valType": "boolean", + "dflt": true, + "role": "style", + "editType": "colorbars", + "description": "Determines whether or not the tick labels are drawn." + }, + "tickfont": { + "family": { + "valType": "string", + "role": "style", + "noBlank": true, + "strict": true, + "description": "HTML font family - the typeface that will be applied by the web browser. The web browser will only be able to apply a font if it is available on the system which it operates. Provide multiple font families, separated by commas, to indicate the preference in which to apply fonts if they aren't available on the system. The plotly service (at https://plot.ly or on-premise) generates images on a server, where only a select number of fonts are installed and supported. These include *Arial*, *Balto*, *Courier New*, *Droid Sans*,, *Droid Serif*, *Droid Sans Mono*, *Gravitas One*, *Old Standard TT*, *Open Sans*, *Overpass*, *PT Sans Narrow*, *Raleway*, *Times New Roman*.", + "editType": "colorbars" + }, + "size": { + "valType": "number", + "role": "style", + "min": 1, + "editType": "colorbars" + }, + "color": { + "valType": "color", + "role": "style", + "editType": "colorbars" + }, + "description": "Sets the color bar's tick label font", + "editType": "colorbars", + "role": "object" + }, + "tickangle": { + "valType": "angle", + "dflt": "auto", + "role": "style", + "editType": "colorbars", + "description": "Sets the angle of the tick labels with respect to the horizontal. For example, a `tickangle` of -90 draws the tick labels vertically." + }, + "tickformat": { + "valType": "string", + "dflt": "", + "role": "style", + "editType": "colorbars", + "description": "Sets the tick label formatting rule using d3 formatting mini-languages which are very similar to those in Python. For numbers, see: https://github.com/d3/d3-format/blob/master/README.md#locale_format And for dates see: https://github.com/d3/d3-time-format/blob/master/README.md#locale_format We add one item to d3's date formatter: *%{n}f* for fractional seconds with n digits. For example, *2016-10-13 09:15:23.456* with tickformat *%H~%M~%S.%2f* would display *09~15~23.46*" + }, + "tickformatstops": { + "items": { + "tickformatstop": { + "dtickrange": { + "valType": "info_array", + "role": "info", + "items": [ + { + "valType": "any", + "editType": "colorbars" + }, + { + "valType": "any", + "editType": "colorbars" + } + ], + "editType": "colorbars", + "description": "range [*min*, *max*], where *min*, *max* - dtick values which describe some zoom level, it is possible to omit *min* or *max* value by passing *null*" + }, + "value": { + "valType": "string", + "dflt": "", + "role": "style", + "editType": "colorbars", + "description": "string - dtickformat for described zoom level, the same as *tickformat*" + }, + "editType": "colorbars", + "role": "object" + } + }, + "role": "object" + }, + "tickprefix": { + "valType": "string", + "dflt": "", + "role": "style", + "editType": "colorbars", + "description": "Sets a tick label prefix." + }, + "showtickprefix": { + "valType": "enumerated", + "values": [ + "all", + "first", + "last", + "none" + ], + "dflt": "all", + "role": "style", + "editType": "colorbars", + "description": "If *all*, all tick labels are displayed with a prefix. If *first*, only the first tick is displayed with a prefix. If *last*, only the last tick is displayed with a suffix. If *none*, tick prefixes are hidden." + }, + "ticksuffix": { + "valType": "string", + "dflt": "", + "role": "style", + "editType": "colorbars", + "description": "Sets a tick label suffix." + }, + "showticksuffix": { + "valType": "enumerated", + "values": [ + "all", + "first", + "last", + "none" + ], + "dflt": "all", + "role": "style", + "editType": "colorbars", + "description": "Same as `showtickprefix` but for tick suffixes." + }, + "separatethousands": { + "valType": "boolean", + "dflt": false, + "role": "style", + "editType": "colorbars", + "description": "If \"true\", even 4-digit integers are separated" + }, + "exponentformat": { + "valType": "enumerated", + "values": [ + "none", + "e", + "E", + "power", + "SI", + "B" + ], + "dflt": "B", + "role": "style", + "editType": "colorbars", + "description": "Determines a formatting rule for the tick exponents. For example, consider the number 1,000,000,000. If *none*, it appears as 1,000,000,000. If *e*, 1e+9. If *E*, 1E+9. If *power*, 1x10^9 (with 9 in a super script). If *SI*, 1G. If *B*, 1B." + }, + "showexponent": { + "valType": "enumerated", + "values": [ + "all", + "first", + "last", + "none" + ], + "dflt": "all", + "role": "style", + "editType": "colorbars", + "description": "If *all*, all exponents are shown besides their significands. If *first*, only the exponent of the first tick is shown. If *last*, only the exponent of the last tick is shown. If *none*, no exponents appear." + }, + "title": { + "valType": "string", + "role": "info", + "dflt": "Click to enter colorscale title", + "description": "Sets the title of the color bar.", + "editType": "colorbars" + }, + "titlefont": { + "family": { + "valType": "string", + "role": "style", + "noBlank": true, + "strict": true, + "description": "HTML font family - the typeface that will be applied by the web browser. The web browser will only be able to apply a font if it is available on the system which it operates. Provide multiple font families, separated by commas, to indicate the preference in which to apply fonts if they aren't available on the system. The plotly service (at https://plot.ly or on-premise) generates images on a server, where only a select number of fonts are installed and supported. These include *Arial*, *Balto*, *Courier New*, *Droid Sans*,, *Droid Serif*, *Droid Sans Mono*, *Gravitas One*, *Old Standard TT*, *Open Sans*, *Overpass*, *PT Sans Narrow*, *Raleway*, *Times New Roman*.", + "editType": "colorbars" + }, + "size": { + "valType": "number", + "role": "style", + "min": 1, + "editType": "colorbars" + }, + "color": { + "valType": "color", + "role": "style", + "editType": "colorbars" + }, + "description": "Sets this color bar's title font.", + "editType": "colorbars", + "role": "object" + }, + "titleside": { + "valType": "enumerated", + "values": [ + "right", + "top", + "bottom" + ], + "role": "style", + "dflt": "top", + "description": "Determines the location of the colorbar title with respect to the color bar.", + "editType": "colorbars" + }, + "editType": "colorbars", + "role": "object", + "tickvalssrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for tickvals .", + "editType": "none" + }, + "ticktextsrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for ticktext .", + "editType": "none" + } + }, + "shape": { + "valType": "enumerated", + "values": [ + "straight", + "curved" + ], + "dflt": "curved", + "role": "info", + "editType": "plot", + "description": "Sets the shape of the paths" + }, + "role": "object", + "colorsrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for color .", + "editType": "none" + } + }, + "counts": { + "valType": "number", + "min": 0, + "dflt": 1, + "arrayOk": true, + "role": "info", + "editType": "calc", + "description": [ + "The number of observations represented by each state. Defaults to 1 so that each state represents one observation" + ] + }, + "idssrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for ids .", + "editType": "none" + }, + "customdatasrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for customdata .", + "editType": "none" + }, + "hoverinfosrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for hoverinfo .", + "editType": "none" + }, + "countssrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for counts .", + "editType": "none" + } + } + }, + "scattermapbox": { + "meta": { + "hrName": "scatter_mapbox", + "description": "The data visualized as scatter point, lines or marker symbols on a Mapbox GL geographic map is provided by longitude/latitude pairs in `lon` and `lat`." + }, + "attributes": { + "type": "scattermapbox", + "visible": { + "valType": "enumerated", + "values": [ + true, + false, + "legendonly" + ], + "role": "info", + "dflt": true, + "editType": "calc", + "description": "Determines whether or not this trace is visible. If *legendonly*, the trace is not drawn, but can appear as a legend item (provided that the legend itself is visible)." + }, + "showlegend": { + "valType": "boolean", + "role": "info", + "dflt": true, + "editType": "style", + "description": "Determines whether or not an item corresponding to this trace is shown in the legend." + }, + "legendgroup": { + "valType": "string", + "role": "info", + "dflt": "", + "editType": "style", + "description": "Sets the legend group for this trace. Traces part of the same legend group hide/show at the same time when toggling legend items." + }, + "opacity": { + "valType": "number", + "role": "style", + "min": 0, + "max": 1, + "dflt": 1, + "editType": "style", + "description": "Sets the opacity of the trace." + }, + "name": { + "valType": "string", + "role": "info", + "editType": "style", + "description": "Sets the trace name. The trace name appear as the legend item and on hover." + }, + "uid": { + "valType": "string", + "role": "info", + "dflt": "", + "editType": "calc" + }, + "ids": { + "valType": "data_array", + "editType": "calc", + "description": "Assigns id labels to each datum. These ids for object constancy of data points during animation.", + "role": "data" + }, + "customdata": { + "valType": "data_array", + "editType": "calc", + "description": "Assigns extra data each datum. This may be useful when listening to hover, click and selection events. Note that, *scatter* traces also appends customdata items in the markers DOM elements", + "role": "data" + }, + "selectedpoints": { + "valType": "any", + "role": "info", + "editType": "calc", + "description": "Array containing integer indices of selected points. Has an effect only for traces that support selections. Note that an empty array means an empty selection where the `unselected` are turned on for all points, whereas, any other non-array values means no selection all where the `selected` and `unselected` styles have no effect." + }, + "hoverinfo": { + "valType": "flaglist", + "role": "info", + "flags": [ + "lon", + "lat", + "text", + "name", + "name" + ], + "extras": [ + "all", + "none", + "skip" + ], + "arrayOk": true, + "dflt": "all", + "editType": "calc", + "description": "Determines which trace information appear on hover. If `none` or `skip` are set, no information is displayed upon hovering. But, if `none` is set, click and hover events are still fired." + }, + "hoverlabel": { + "bgcolor": { + "valType": "color", + "role": "style", + "arrayOk": true, + "editType": "none", + "description": "Sets the background color of the hover labels for this trace" + }, + "bordercolor": { + "valType": "color", + "role": "style", + "arrayOk": true, + "editType": "none", + "description": "Sets the border color of the hover labels for this trace." + }, + "font": { + "family": { + "valType": "string", + "role": "style", + "noBlank": true, + "strict": true, + "editType": "none", + "description": "HTML font family - the typeface that will be applied by the web browser. The web browser will only be able to apply a font if it is available on the system which it operates. Provide multiple font families, separated by commas, to indicate the preference in which to apply fonts if they aren't available on the system. The plotly service (at https://plot.ly or on-premise) generates images on a server, where only a select number of fonts are installed and supported. These include *Arial*, *Balto*, *Courier New*, *Droid Sans*,, *Droid Serif*, *Droid Sans Mono*, *Gravitas One*, *Old Standard TT*, *Open Sans*, *Overpass*, *PT Sans Narrow*, *Raleway*, *Times New Roman*.", + "arrayOk": true + }, + "size": { + "valType": "number", + "role": "style", + "min": 1, + "editType": "none", + "arrayOk": true + }, + "color": { + "valType": "color", + "role": "style", + "editType": "none", + "arrayOk": true + }, + "editType": "none", + "description": "Sets the font used in hover labels.", + "role": "object", + "familysrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for family .", + "editType": "none" + }, + "sizesrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for size .", + "editType": "none" + }, + "colorsrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for color .", + "editType": "none" + } + }, + "namelength": { + "valType": "integer", + "min": -1, + "arrayOk": true, + "role": "style", + "editType": "none", + "description": "Sets the length (in number of characters) of the trace name in the hover labels for this trace. -1 shows the whole name regardless of length. 0-3 shows the first 0-3 characters, and an integer >3 will show the whole name if it is less than that many characters, but if it is longer, will truncate to `namelength - 3` characters and add an ellipsis." + }, + "editType": "calc", + "role": "object", + "bgcolorsrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for bgcolor .", + "editType": "none" + }, + "bordercolorsrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for bordercolor .", + "editType": "none" + }, + "namelengthsrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for namelength .", + "editType": "none" + } + }, + "stream": { + "token": { + "valType": "string", + "noBlank": true, + "strict": true, + "role": "info", + "editType": "calc", + "description": "The stream id number links a data trace on a plot with a stream. See https://plot.ly/settings for more details." + }, + "maxpoints": { + "valType": "number", + "min": 0, + "max": 10000, + "dflt": 500, + "role": "info", + "editType": "calc", + "description": "Sets the maximum number of points to keep on the plots from an incoming stream. If `maxpoints` is set to *50*, only the newest 50 points will be displayed on the plot." + }, + "editType": "calc", + "role": "object" + }, + "lon": { + "valType": "data_array", + "description": "Sets the longitude coordinates (in degrees East).", + "editType": "calc", + "role": "data" + }, + "lat": { + "valType": "data_array", + "description": "Sets the latitude coordinates (in degrees North).", + "editType": "calc", + "role": "data" + }, + "mode": { + "valType": "flaglist", + "flags": [ + "lines", + "markers", + "text" + ], + "extras": [ + "none" + ], + "role": "info", + "editType": "calc", + "description": "Determines the drawing mode for this scatter trace. If the provided `mode` includes *text* then the `text` elements appear at the coordinates. Otherwise, the `text` elements appear on hover.", + "dflt": "markers" + }, + "text": { + "valType": "string", + "role": "info", + "dflt": "", + "arrayOk": true, + "editType": "calc", + "description": "Sets text elements associated with each (lon,lat) pair If a single string, the same string appears over all the data points. If an array of string, the items are mapped in order to the this trace's (lon,lat) coordinates. If trace `hoverinfo` contains a *text* flag and *hovertext* is not set, these elements will be seen in the hover labels." + }, + "hovertext": { + "valType": "string", + "role": "info", + "dflt": "", + "arrayOk": true, + "editType": "calc", + "description": "Sets hover text elements associated with each (lon,lat) pair If a single string, the same string appears over all the data points. If an array of string, the items are mapped in order to the this trace's (lon,lat) coordinates. To be seen, trace `hoverinfo` must contain a *text* flag." + }, + "line": { + "color": { + "valType": "color", + "role": "style", + "editType": "calc", + "description": "Sets the line color." + }, + "width": { + "valType": "number", + "min": 0, + "dflt": 2, + "role": "style", + "editType": "calc", + "description": "Sets the line width (in px)." + }, + "editType": "calc", + "role": "object" + }, + "connectgaps": { + "valType": "boolean", + "dflt": false, + "role": "info", + "editType": "calc", + "description": "Determines whether or not gaps (i.e. {nan} or missing values) in the provided data arrays are connected." + }, + "marker": { + "symbol": { + "valType": "string", + "dflt": "circle", + "role": "style", + "arrayOk": true, + "description": "Sets the marker symbol. Full list: https://www.mapbox.com/maki-icons/ Note that the array `marker.color` and `marker.size` are only available for *circle* symbols.", + "editType": "calc" + }, + "opacity": { + "valType": "number", + "min": 0, + "max": 1, + "arrayOk": true, + "role": "style", + "editType": "calc", + "description": "Sets the marker opacity." + }, + "size": { + "valType": "number", + "min": 0, + "dflt": 6, + "arrayOk": true, + "role": "style", + "editType": "calc", + "description": "Sets the marker size (in px)." + }, + "sizeref": { + "valType": "number", + "dflt": 1, + "role": "style", + "editType": "calc", + "description": "Has an effect only if `marker.size` is set to a numerical array. Sets the scale factor used to determine the rendered size of marker points. Use with `sizemin` and `sizemode`." + }, + "sizemin": { + "valType": "number", + "min": 0, + "dflt": 0, + "role": "style", + "editType": "calc", + "description": "Has an effect only if `marker.size` is set to a numerical array. Sets the minimum size (in px) of the rendered marker points." + }, + "sizemode": { + "valType": "enumerated", + "values": [ + "diameter", + "area" + ], + "dflt": "diameter", + "role": "info", + "editType": "calc", + "description": "Has an effect only if `marker.size` is set to a numerical array. Sets the rule for which the data in `size` is converted to pixels." + }, + "color": { + "valType": "color", + "arrayOk": true, + "role": "style", + "editType": "calc", + "description": "Sets the marker color. It accepts either a specific color or an array of numbers that are mapped to the colorscale relative to the max and min values of the array or relative to `cmin` and `cmax` if set." + }, + "colorscale": { + "valType": "colorscale", + "role": "style", + "editType": "calc", + "impliedEdits": { + "autocolorscale": false + }, + "description": "Sets the colorscale and only has an effect if `marker.color` is set to a numerical array. The colorscale must be an array containing arrays mapping a normalized value to an rgb, rgba, hex, hsl, hsv, or named color string. At minimum, a mapping for the lowest (0) and highest (1) values are required. For example, `[[0, 'rgb(0,0,255)', [1, 'rgb(255,0,0)']]`. To control the bounds of the colorscale in color space, use `marker.cmin` and `marker.cmax`. Alternatively, `colorscale` may be a palette name string of the following list: Greys, YlGnBu, Greens, YlOrRd, Bluered, RdBu, Reds, Blues, Picnic, Rainbow, Portland, Jet, Hot, Blackbody, Earth, Electric, Viridis" + }, + "cauto": { + "valType": "boolean", + "role": "info", + "dflt": true, + "editType": "calc", + "impliedEdits": {}, + "description": "Has an effect only if `marker.color` is set to a numerical array and `cmin`, `cmax` are set by the user. In this case, it controls whether the range of colors in `colorscale` is mapped to the range of values in the `color` array (`cauto: true`), or the `cmin`/`cmax` values (`cauto: false`). Defaults to `false` when `cmin`, `cmax` are set by the user." + }, + "cmax": { + "valType": "number", + "role": "info", + "dflt": null, + "editType": "calc", + "impliedEdits": { + "cauto": false + }, + "description": "Has an effect only if `marker.color` is set to a numerical array. Sets the upper bound of the color domain. Value should be associated to the `marker.color` array index, and if set, `marker.cmin` must be set as well." + }, + "cmin": { + "valType": "number", + "role": "info", + "dflt": null, + "editType": "calc", + "impliedEdits": { + "cauto": false + }, + "description": "Has an effect only if `marker.color` is set to a numerical array. Sets the lower bound of the color domain. Value should be associated to the `marker.color` array index, and if set, `marker.cmax` must be set as well." + }, + "autocolorscale": { + "valType": "boolean", + "role": "style", + "dflt": true, + "editType": "calc", + "impliedEdits": {}, + "description": "Has an effect only if `marker.color` is set to a numerical array. Determines whether the colorscale is a default palette (`autocolorscale: true`) or the palette determined by `marker.colorscale`. In case `colorscale` is unspecified or `autocolorscale` is true, the default palette will be chosen according to whether numbers in the `color` array are all positive, all negative or mixed." + }, + "reversescale": { + "valType": "boolean", + "role": "style", + "dflt": false, + "editType": "calc", + "description": "Has an effect only if `marker.color` is set to a numerical array. Reverses the color mapping if true (`cmin` will correspond to the last color in the array and `cmax` will correspond to the first color)." + }, + "showscale": { + "valType": "boolean", + "role": "info", + "dflt": false, + "editType": "calc", + "description": "Has an effect only if `marker.color` is set to a numerical array. Determines whether or not a colorbar is displayed." + }, + "colorbar": { + "thicknessmode": { + "valType": "enumerated", + "values": [ + "fraction", + "pixels" + ], + "role": "style", + "dflt": "pixels", + "description": "Determines whether this color bar's thickness (i.e. the measure in the constant color direction) is set in units of plot *fraction* or in *pixels*. Use `thickness` to set the value.", + "editType": "calc" + }, + "thickness": { + "valType": "number", + "role": "style", + "min": 0, + "dflt": 30, + "description": "Sets the thickness of the color bar This measure excludes the size of the padding, ticks and labels.", + "editType": "calc" + }, + "lenmode": { + "valType": "enumerated", + "values": [ + "fraction", + "pixels" + ], + "role": "info", + "dflt": "fraction", + "description": "Determines whether this color bar's length (i.e. the measure in the color variation direction) is set in units of plot *fraction* or in *pixels. Use `len` to set the value.", + "editType": "calc" + }, + "len": { + "valType": "number", + "min": 0, + "dflt": 1, + "role": "style", + "description": "Sets the length of the color bar This measure excludes the padding of both ends. That is, the color bar length is this length minus the padding on both ends.", + "editType": "calc" + }, + "x": { + "valType": "number", + "dflt": 1.02, + "min": -2, + "max": 3, + "role": "style", + "description": "Sets the x position of the color bar (in plot fraction).", + "editType": "calc" + }, + "xanchor": { + "valType": "enumerated", + "values": [ + "left", + "center", + "right" + ], + "dflt": "left", + "role": "style", + "description": "Sets this color bar's horizontal position anchor. This anchor binds the `x` position to the *left*, *center* or *right* of the color bar.", + "editType": "calc" + }, + "xpad": { + "valType": "number", + "role": "style", + "min": 0, + "dflt": 10, + "description": "Sets the amount of padding (in px) along the x direction.", + "editType": "calc" + }, + "y": { + "valType": "number", + "role": "style", + "dflt": 0.5, + "min": -2, + "max": 3, + "description": "Sets the y position of the color bar (in plot fraction).", + "editType": "calc" + }, + "yanchor": { + "valType": "enumerated", + "values": [ + "top", + "middle", + "bottom" + ], + "role": "style", + "dflt": "middle", + "description": "Sets this color bar's vertical position anchor This anchor binds the `y` position to the *top*, *middle* or *bottom* of the color bar.", + "editType": "calc" + }, + "ypad": { + "valType": "number", + "role": "style", + "min": 0, + "dflt": 10, + "description": "Sets the amount of padding (in px) along the y direction.", + "editType": "calc" + }, + "outlinecolor": { + "valType": "color", + "dflt": "#444", + "role": "style", + "editType": "calc", + "description": "Sets the axis line color." + }, + "outlinewidth": { + "valType": "number", + "min": 0, + "dflt": 1, + "role": "style", + "editType": "calc", + "description": "Sets the width (in px) of the axis line." + }, + "bordercolor": { + "valType": "color", + "dflt": "#444", + "role": "style", + "editType": "calc", + "description": "Sets the axis line color." + }, + "borderwidth": { + "valType": "number", + "role": "style", + "min": 0, + "dflt": 0, + "description": "Sets the width (in px) or the border enclosing this color bar.", + "editType": "calc" + }, + "bgcolor": { + "valType": "color", + "role": "style", + "dflt": "rgba(0,0,0,0)", + "description": "Sets the color of padded area.", + "editType": "calc" + }, + "tickmode": { + "valType": "enumerated", + "values": [ + "auto", + "linear", + "array" + ], + "role": "info", + "editType": "calc", + "impliedEdits": {}, + "description": "Sets the tick mode for this axis. If *auto*, the number of ticks is set via `nticks`. If *linear*, the placement of the ticks is determined by a starting position `tick0` and a tick step `dtick` (*linear* is the default value if `tick0` and `dtick` are provided). If *array*, the placement of the ticks is set via `tickvals` and the tick text is `ticktext`. (*array* is the default value if `tickvals` is provided)." + }, + "nticks": { + "valType": "integer", + "min": 0, + "dflt": 0, + "role": "style", + "editType": "calc", + "description": "Specifies the maximum number of ticks for the particular axis. The actual number of ticks will be chosen automatically to be less than or equal to `nticks`. Has an effect only if `tickmode` is set to *auto*." + }, + "tick0": { + "valType": "any", + "role": "style", + "editType": "calc", + "impliedEdits": { + "tickmode": "linear" + }, + "description": "Sets the placement of the first tick on this axis. Use with `dtick`. If the axis `type` is *log*, then you must take the log of your starting tick (e.g. to set the starting tick to 100, set the `tick0` to 2) except when `dtick`=*L* (see `dtick` for more info). If the axis `type` is *date*, it should be a date string, like date data. If the axis `type` is *category*, it should be a number, using the scale where each category is assigned a serial number from zero in the order it appears." + }, + "dtick": { + "valType": "any", + "role": "style", + "editType": "calc", + "impliedEdits": { + "tickmode": "linear" + }, + "description": "Sets the step in-between ticks on this axis. Use with `tick0`. Must be a positive number, or special strings available to *log* and *date* axes. If the axis `type` is *log*, then ticks are set every 10^(n*dtick) where n is the tick number. For example, to set a tick mark at 1, 10, 100, 1000, ... set dtick to 1. To set tick marks at 1, 100, 10000, ... set dtick to 2. To set tick marks at 1, 5, 25, 125, 625, 3125, ... set dtick to log_10(5), or 0.69897000433. *log* has several special values; *L*, where `f` is a positive number, gives ticks linearly spaced in value (but not position). For example `tick0` = 0.1, `dtick` = *L0.5* will put ticks at 0.1, 0.6, 1.1, 1.6 etc. To show powers of 10 plus small digits between, use *D1* (all digits) or *D2* (only 2 and 5). `tick0` is ignored for *D1* and *D2*. If the axis `type` is *date*, then you must convert the time to milliseconds. For example, to set the interval between ticks to one day, set `dtick` to 86400000.0. *date* also has special values *M* gives ticks spaced by a number of months. `n` must be a positive integer. To set ticks on the 15th of every third month, set `tick0` to *2000-01-15* and `dtick` to *M3*. To set ticks every 4 years, set `dtick` to *M48*" + }, + "tickvals": { + "valType": "data_array", + "editType": "calc", + "description": "Sets the values at which ticks on this axis appear. Only has an effect if `tickmode` is set to *array*. Used with `ticktext`.", + "role": "data" + }, + "ticktext": { + "valType": "data_array", + "editType": "calc", + "description": "Sets the text displayed at the ticks position via `tickvals`. Only has an effect if `tickmode` is set to *array*. Used with `tickvals`.", + "role": "data" + }, + "ticks": { + "valType": "enumerated", + "values": [ + "outside", + "inside", + "" + ], + "role": "style", + "editType": "calc", + "description": "Determines whether ticks are drawn or not. If **, this axis' ticks are not drawn. If *outside* (*inside*), this axis' are drawn outside (inside) the axis lines.", + "dflt": "" + }, + "ticklen": { + "valType": "number", + "min": 0, + "dflt": 5, + "role": "style", + "editType": "calc", + "description": "Sets the tick length (in px)." + }, + "tickwidth": { + "valType": "number", + "min": 0, + "dflt": 1, + "role": "style", + "editType": "calc", + "description": "Sets the tick width (in px)." + }, + "tickcolor": { + "valType": "color", + "dflt": "#444", + "role": "style", + "editType": "calc", + "description": "Sets the tick color." + }, + "showticklabels": { + "valType": "boolean", + "dflt": true, + "role": "style", + "editType": "calc", + "description": "Determines whether or not the tick labels are drawn." + }, + "tickfont": { + "family": { + "valType": "string", + "role": "style", + "noBlank": true, + "strict": true, + "description": "HTML font family - the typeface that will be applied by the web browser. The web browser will only be able to apply a font if it is available on the system which it operates. Provide multiple font families, separated by commas, to indicate the preference in which to apply fonts if they aren't available on the system. The plotly service (at https://plot.ly or on-premise) generates images on a server, where only a select number of fonts are installed and supported. These include *Arial*, *Balto*, *Courier New*, *Droid Sans*,, *Droid Serif*, *Droid Sans Mono*, *Gravitas One*, *Old Standard TT*, *Open Sans*, *Overpass*, *PT Sans Narrow*, *Raleway*, *Times New Roman*.", + "editType": "calc" + }, + "size": { + "valType": "number", + "role": "style", + "min": 1, + "editType": "calc" + }, + "color": { + "valType": "color", + "role": "style", + "editType": "calc" + }, + "description": "Sets the color bar's tick label font", + "editType": "calc", + "role": "object" + }, + "tickangle": { + "valType": "angle", + "dflt": "auto", + "role": "style", + "editType": "calc", + "description": "Sets the angle of the tick labels with respect to the horizontal. For example, a `tickangle` of -90 draws the tick labels vertically." + }, + "tickformat": { + "valType": "string", + "dflt": "", + "role": "style", + "editType": "calc", + "description": "Sets the tick label formatting rule using d3 formatting mini-languages which are very similar to those in Python. For numbers, see: https://github.com/d3/d3-format/blob/master/README.md#locale_format And for dates see: https://github.com/d3/d3-time-format/blob/master/README.md#locale_format We add one item to d3's date formatter: *%{n}f* for fractional seconds with n digits. For example, *2016-10-13 09:15:23.456* with tickformat *%H~%M~%S.%2f* would display *09~15~23.46*" + }, + "tickformatstops": { + "items": { + "tickformatstop": { + "dtickrange": { + "valType": "info_array", + "role": "info", + "items": [ + { + "valType": "any", + "editType": "calc" + }, + { + "valType": "any", + "editType": "calc" + } + ], + "editType": "calc", + "description": "range [*min*, *max*], where *min*, *max* - dtick values which describe some zoom level, it is possible to omit *min* or *max* value by passing *null*" + }, + "value": { + "valType": "string", + "dflt": "", + "role": "style", + "editType": "calc", + "description": "string - dtickformat for described zoom level, the same as *tickformat*" + }, + "editType": "calc", + "role": "object" + } + }, + "role": "object" + }, + "tickprefix": { + "valType": "string", + "dflt": "", + "role": "style", + "editType": "calc", + "description": "Sets a tick label prefix." + }, + "showtickprefix": { + "valType": "enumerated", + "values": [ + "all", + "first", + "last", + "none" + ], + "dflt": "all", + "role": "style", + "editType": "calc", + "description": "If *all*, all tick labels are displayed with a prefix. If *first*, only the first tick is displayed with a prefix. If *last*, only the last tick is displayed with a suffix. If *none*, tick prefixes are hidden." + }, + "ticksuffix": { + "valType": "string", + "dflt": "", + "role": "style", + "editType": "calc", + "description": "Sets a tick label suffix." + }, + "showticksuffix": { + "valType": "enumerated", + "values": [ + "all", + "first", + "last", + "none" + ], + "dflt": "all", + "role": "style", + "editType": "calc", + "description": "Same as `showtickprefix` but for tick suffixes." + }, + "separatethousands": { + "valType": "boolean", + "dflt": false, + "role": "style", + "editType": "calc", + "description": "If \"true\", even 4-digit integers are separated" + }, + "exponentformat": { + "valType": "enumerated", + "values": [ + "none", + "e", + "E", + "power", + "SI", + "B" + ], + "dflt": "B", + "role": "style", + "editType": "calc", + "description": "Determines a formatting rule for the tick exponents. For example, consider the number 1,000,000,000. If *none*, it appears as 1,000,000,000. If *e*, 1e+9. If *E*, 1E+9. If *power*, 1x10^9 (with 9 in a super script). If *SI*, 1G. If *B*, 1B." + }, + "showexponent": { + "valType": "enumerated", + "values": [ + "all", + "first", + "last", + "none" + ], + "dflt": "all", + "role": "style", + "editType": "calc", + "description": "If *all*, all exponents are shown besides their significands. If *first*, only the exponent of the first tick is shown. If *last*, only the exponent of the last tick is shown. If *none*, no exponents appear." + }, + "title": { + "valType": "string", + "role": "info", + "dflt": "Click to enter colorscale title", + "description": "Sets the title of the color bar.", + "editType": "calc" + }, + "titlefont": { + "family": { + "valType": "string", + "role": "style", + "noBlank": true, + "strict": true, + "description": "HTML font family - the typeface that will be applied by the web browser. The web browser will only be able to apply a font if it is available on the system which it operates. Provide multiple font families, separated by commas, to indicate the preference in which to apply fonts if they aren't available on the system. The plotly service (at https://plot.ly or on-premise) generates images on a server, where only a select number of fonts are installed and supported. These include *Arial*, *Balto*, *Courier New*, *Droid Sans*,, *Droid Serif*, *Droid Sans Mono*, *Gravitas One*, *Old Standard TT*, *Open Sans*, *Overpass*, *PT Sans Narrow*, *Raleway*, *Times New Roman*.", + "editType": "calc" + }, + "size": { + "valType": "number", + "role": "style", + "min": 1, + "editType": "calc" + }, + "color": { + "valType": "color", + "role": "style", + "editType": "calc" + }, + "description": "Sets this color bar's title font.", + "editType": "calc", + "role": "object" + }, + "titleside": { + "valType": "enumerated", + "values": [ + "right", + "top", + "bottom" + ], + "role": "style", + "dflt": "top", + "description": "Determines the location of the colorbar title with respect to the color bar.", + "editType": "calc" + }, + "editType": "calc", + "role": "object", + "tickvalssrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for tickvals .", + "editType": "none" + }, + "ticktextsrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for ticktext .", + "editType": "none" + } + }, + "editType": "calc", + "role": "object", + "symbolsrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for symbol .", + "editType": "none" + }, + "opacitysrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for opacity .", + "editType": "none" + }, + "sizesrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for size .", + "editType": "none" + }, + "colorsrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for color .", + "editType": "none" + } + }, + "fill": { + "valType": "enumerated", + "values": [ + "none", + "toself" + ], + "dflt": "none", + "role": "style", + "description": "Sets the area to fill with a solid color. Use with `fillcolor` if not *none*. *toself* connects the endpoints of the trace (or each segment of the trace if it has gaps) into a closed shape.", + "editType": "calc" + }, + "fillcolor": { + "valType": "color", + "role": "style", + "editType": "calc", + "description": "Sets the fill color. Defaults to a half-transparent variant of the line color, marker color, or marker line color, whichever is available." + }, + "textfont": { + "family": { + "valType": "string", + "role": "style", + "noBlank": true, + "strict": true, + "description": "HTML font family - the typeface that will be applied by the web browser. The web browser will only be able to apply a font if it is available on the system which it operates. Provide multiple font families, separated by commas, to indicate the preference in which to apply fonts if they aren't available on the system. The plotly service (at https://plot.ly or on-premise) generates images on a server, where only a select number of fonts are installed and supported. These include *Arial*, *Balto*, *Courier New*, *Droid Sans*,, *Droid Serif*, *Droid Sans Mono*, *Gravitas One*, *Old Standard TT*, *Open Sans*, *Overpass*, *PT Sans Narrow*, *Raleway*, *Times New Roman*.", + "dflt": "Open Sans Regular, Arial Unicode MS Regular", + "editType": "calc" + }, + "size": { + "valType": "number", + "role": "style", + "min": 1, + "editType": "calc" + }, + "color": { + "valType": "color", + "role": "style", + "editType": "calc" + }, + "description": "Sets the icon text font. Has an effect only when `type` is set to *symbol*.", + "editType": "calc", + "role": "object" + }, + "textposition": { + "valType": "enumerated", + "values": [ + "top left", + "top center", + "top right", + "middle left", + "middle center", + "middle right", + "bottom left", + "bottom center", + "bottom right" + ], + "dflt": "middle center", + "arrayOk": false, + "role": "style", + "editType": "calc", + "description": "Sets the positions of the `text` elements with respects to the (x,y) coordinates." + }, + "selected": { + "marker": { + "opacity": { + "valType": "number", + "min": 0, + "max": 1, + "role": "style", + "editType": "calc", + "description": "Sets the marker opacity of selected points." + }, + "editType": "calc", + "role": "object" + }, + "editType": "calc", + "role": "object" + }, + "unselected": { + "marker": { + "opacity": { + "valType": "number", + "min": 0, + "max": 1, + "role": "style", + "editType": "calc", + "description": "Sets the marker opacity of unselected points, applied only when a selection exists." + }, + "editType": "calc", + "role": "object" + }, + "editType": "calc", + "role": "object" + }, + "subplot": { + "valType": "subplotid", + "role": "info", + "dflt": "mapbox", + "editType": "calc", + "description": "Sets a reference between this trace's data coordinates and a mapbox subplot. If *mapbox* (the default value), the data refer to `layout.mapbox`. If *mapbox2*, the data refer to `layout.mapbox2`, and so on." + }, + "idssrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for ids .", + "editType": "none" + }, + "customdatasrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for customdata .", + "editType": "none" + }, + "hoverinfosrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for hoverinfo .", + "editType": "none" + }, + "lonsrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for lon .", + "editType": "none" + }, + "latsrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for lat .", + "editType": "none" + }, + "textsrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for text .", + "editType": "none" + }, + "hovertextsrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for hovertext .", + "editType": "none" + } + } + }, + "sankey": { + "meta": { + "description": "Sankey plots for network flow data analysis. The nodes are specified in `nodes` and the links between sources and targets in `links`. The colors are set in `nodes[i].color` and `links[i].color`; otherwise defaults are used." + }, + "attributes": { + "type": "sankey", + "visible": { + "valType": "enumerated", + "values": [ + true, + false, + "legendonly" + ], + "role": "info", + "dflt": true, + "editType": "calc", + "description": "Determines whether or not this trace is visible. If *legendonly*, the trace is not drawn, but can appear as a legend item (provided that the legend itself is visible)." + }, + "showlegend": { + "valType": "boolean", + "role": "info", + "dflt": true, + "editType": "style", + "description": "Determines whether or not an item corresponding to this trace is shown in the legend." + }, + "legendgroup": { + "valType": "string", + "role": "info", + "dflt": "", + "editType": "style", + "description": "Sets the legend group for this trace. Traces part of the same legend group hide/show at the same time when toggling legend items." + }, + "opacity": { + "valType": "number", + "role": "style", + "min": 0, + "max": 1, + "dflt": 1, + "editType": "style", + "description": "Sets the opacity of the trace." + }, + "name": { + "valType": "string", + "role": "info", + "editType": "style", + "description": "Sets the trace name. The trace name appear as the legend item and on hover." + }, + "uid": { + "valType": "string", + "role": "info", + "dflt": "", + "editType": "calc" + }, + "ids": { + "valType": "data_array", + "editType": "calc", + "description": "Assigns id labels to each datum. These ids for object constancy of data points during animation.", + "role": "data" + }, + "customdata": { + "valType": "data_array", + "editType": "calc", + "description": "Assigns extra data each datum. This may be useful when listening to hover, click and selection events. Note that, *scatter* traces also appends customdata items in the markers DOM elements", + "role": "data" + }, + "selectedpoints": { + "valType": "any", + "role": "info", + "editType": "calc", + "description": "Array containing integer indices of selected points. Has an effect only for traces that support selections. Note that an empty array means an empty selection where the `unselected` are turned on for all points, whereas, any other non-array values means no selection all where the `selected` and `unselected` styles have no effect." + }, + "hoverinfo": { + "valType": "flaglist", + "role": "info", + "flags": [ + "label", + "text", + "value", + "percent", + "name" + ], + "extras": [ + "all", + "none", + "skip" + ], + "arrayOk": true, + "dflt": "all", + "editType": "calc", + "description": "Determines which trace information appear on hover. If `none` or `skip` are set, no information is displayed upon hovering. But, if `none` is set, click and hover events are still fired." + }, + "hoverlabel": { + "bgcolor": { + "valType": "color", + "role": "style", + "arrayOk": true, + "editType": "calc", + "description": "Sets the background color of the hover labels for this trace" + }, + "bordercolor": { + "valType": "color", + "role": "style", + "arrayOk": true, + "editType": "calc", + "description": "Sets the border color of the hover labels for this trace." + }, + "font": { + "family": { + "valType": "string", + "role": "style", + "noBlank": true, + "strict": true, + "editType": "calc", + "description": "HTML font family - the typeface that will be applied by the web browser. The web browser will only be able to apply a font if it is available on the system which it operates. Provide multiple font families, separated by commas, to indicate the preference in which to apply fonts if they aren't available on the system. The plotly service (at https://plot.ly or on-premise) generates images on a server, where only a select number of fonts are installed and supported. These include *Arial*, *Balto*, *Courier New*, *Droid Sans*,, *Droid Serif*, *Droid Sans Mono*, *Gravitas One*, *Old Standard TT*, *Open Sans*, *Overpass*, *PT Sans Narrow*, *Raleway*, *Times New Roman*.", + "arrayOk": true + }, + "size": { + "valType": "number", + "role": "style", + "min": 1, + "editType": "calc", + "arrayOk": true + }, + "color": { + "valType": "color", + "role": "style", + "editType": "calc", + "arrayOk": true + }, + "editType": "calc", + "description": "Sets the font used in hover labels.", + "role": "object", + "familysrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for family .", + "editType": "none" + }, + "sizesrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for size .", + "editType": "none" + }, + "colorsrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for color .", + "editType": "none" + } + }, + "namelength": { + "valType": "integer", + "min": -1, + "arrayOk": true, + "role": "style", + "editType": "calc", + "description": "Sets the length (in number of characters) of the trace name in the hover labels for this trace. -1 shows the whole name regardless of length. 0-3 shows the first 0-3 characters, and an integer >3 will show the whole name if it is less than that many characters, but if it is longer, will truncate to `namelength - 3` characters and add an ellipsis." + }, + "editType": "calc", + "role": "object", + "bgcolorsrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for bgcolor .", + "editType": "none" + }, + "bordercolorsrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for bordercolor .", + "editType": "none" + }, + "namelengthsrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for namelength .", + "editType": "none" + } + }, + "stream": { + "token": { + "valType": "string", + "noBlank": true, + "strict": true, + "role": "info", + "editType": "calc", + "description": "The stream id number links a data trace on a plot with a stream. See https://plot.ly/settings for more details." + }, + "maxpoints": { + "valType": "number", + "min": 0, + "max": 10000, + "dflt": 500, + "role": "info", + "editType": "calc", + "description": "Sets the maximum number of points to keep on the plots from an incoming stream. If `maxpoints` is set to *50*, only the newest 50 points will be displayed on the plot." + }, + "editType": "calc", + "role": "object" + }, + "domain": { + "x": { + "valType": "info_array", + "role": "info", + "items": [ + { + "valType": "number", + "min": 0, + "max": 1, + "editType": "calc" + }, + { + "valType": "number", + "min": 0, + "max": 1, + "editType": "calc" + } + ], + "dflt": [ + 0, + 1 + ], + "description": "Sets the horizontal domain of this `sankey` trace (in plot fraction).", + "editType": "calc" + }, + "y": { + "valType": "info_array", + "role": "info", + "items": [ + { + "valType": "number", + "min": 0, + "max": 1, + "editType": "calc" + }, + { + "valType": "number", + "min": 0, + "max": 1, + "editType": "calc" + } + ], + "dflt": [ + 0, + 1 + ], + "description": "Sets the vertical domain of this `sankey` trace (in plot fraction).", + "editType": "calc" + }, + "editType": "calc", + "role": "object" + }, + "orientation": { + "valType": "enumerated", + "values": [ + "v", + "h" + ], + "dflt": "h", + "role": "style", + "description": "Sets the orientation of the Sankey diagram.", + "editType": "calc" + }, + "valueformat": { + "valType": "string", + "dflt": ".3s", + "role": "style", + "description": "Sets the value formatting rule using d3 formatting mini-language which is similar to those of Python. See https://github.com/d3/d3-format/blob/master/README.md#locale_format", + "editType": "calc" + }, + "valuesuffix": { + "valType": "string", + "dflt": "", + "role": "style", + "description": "Adds a unit to follow the value in the hover tooltip. Add a space if a separation is necessary from the value.", + "editType": "calc" + }, + "arrangement": { + "valType": "enumerated", + "values": [ + "snap", + "perpendicular", + "freeform", + "fixed" + ], + "dflt": "snap", + "role": "style", + "description": "If value is `snap` (the default), the node arrangement is assisted by automatic snapping of elements to preserve space between nodes specified via `nodepad`. If value is `perpendicular`, the nodes can only move along a line perpendicular to the flow. If value is `freeform`, the nodes can freely move on the plane. If value is `fixed`, the nodes are stationary.", + "editType": "calc" + }, + "textfont": { + "family": { + "valType": "string", + "role": "style", + "noBlank": true, + "strict": true, + "description": "HTML font family - the typeface that will be applied by the web browser. The web browser will only be able to apply a font if it is available on the system which it operates. Provide multiple font families, separated by commas, to indicate the preference in which to apply fonts if they aren't available on the system. The plotly service (at https://plot.ly or on-premise) generates images on a server, where only a select number of fonts are installed and supported. These include *Arial*, *Balto*, *Courier New*, *Droid Sans*,, *Droid Serif*, *Droid Sans Mono*, *Gravitas One*, *Old Standard TT*, *Open Sans*, *Overpass*, *PT Sans Narrow*, *Raleway*, *Times New Roman*.", + "editType": "calc" + }, + "size": { + "valType": "number", + "role": "style", + "min": 1, + "editType": "calc" + }, + "color": { + "valType": "color", + "role": "style", + "editType": "calc" + }, + "description": "Sets the font for node labels", + "editType": "calc", + "role": "object" + }, + "node": { + "label": { + "valType": "data_array", + "dflt": [], + "role": "data", + "description": "The shown name of the node.", + "editType": "calc" + }, + "color": { + "valType": "color", + "role": "style", + "arrayOk": true, + "description": "Sets the `node` color. It can be a single value, or an array for specifying color for each `node`. If `node.color` is omitted, then the default `Plotly` color palette will be cycled through to have a variety of colors. These defaults are not fully opaque, to allow some visibility of what is beneath the node.", + "editType": "calc" + }, + "line": { + "color": { + "valType": "color", + "role": "style", + "dflt": "#444", + "arrayOk": true, + "description": "Sets the color of the `line` around each `node`.", + "editType": "calc" + }, + "width": { + "valType": "number", + "role": "style", + "min": 0, + "dflt": 0.5, + "arrayOk": true, + "description": "Sets the width (in px) of the `line` around each `node`.", + "editType": "calc" + }, + "editType": "calc", + "role": "object", + "colorsrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for color .", + "editType": "none" + }, + "widthsrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for width .", + "editType": "none" + } + }, + "pad": { + "valType": "number", + "arrayOk": false, + "min": 0, + "dflt": 20, + "role": "style", + "description": "Sets the padding (in px) between the `nodes`.", + "editType": "calc" + }, + "thickness": { + "valType": "number", + "arrayOk": false, + "min": 1, + "dflt": 20, + "role": "style", + "description": "Sets the thickness (in px) of the `nodes`.", + "editType": "calc" + }, + "description": "The nodes of the Sankey plot.", + "editType": "calc", + "role": "object", + "labelsrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for label .", + "editType": "none" + }, + "colorsrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for color .", + "editType": "none" + } + }, + "link": { + "label": { + "valType": "data_array", + "dflt": [], + "role": "data", + "description": "The shown name of the link.", + "editType": "calc" + }, + "color": { + "valType": "color", + "role": "style", + "arrayOk": true, + "description": "Sets the `link` color. It can be a single value, or an array for specifying color for each `link`. If `link.color` is omitted, then by default, a translucent grey link will be used.", + "editType": "calc" + }, + "line": { + "color": { + "valType": "color", + "role": "style", + "dflt": "#444", + "arrayOk": true, + "description": "Sets the color of the `line` around each `link`.", + "editType": "calc" + }, + "width": { + "valType": "number", + "role": "style", + "min": 0, + "dflt": 0, + "arrayOk": true, + "description": "Sets the width (in px) of the `line` around each `link`.", + "editType": "calc" + }, + "editType": "calc", + "role": "object", + "colorsrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for color .", + "editType": "none" + }, + "widthsrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for width .", + "editType": "none" + } + }, + "source": { + "valType": "data_array", + "role": "data", + "dflt": [], + "description": "An integer number `[0..nodes.length - 1]` that represents the source node.", + "editType": "calc" + }, + "target": { + "valType": "data_array", + "role": "data", + "dflt": [], + "description": "An integer number `[0..nodes.length - 1]` that represents the target node.", + "editType": "calc" + }, + "value": { + "valType": "data_array", + "dflt": [], + "role": "data", + "description": "A numeric value representing the flow volume value.", + "editType": "calc" + }, + "description": "The links of the Sankey plot.", + "editType": "calc", + "role": "object", + "labelsrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for label .", + "editType": "none" + }, + "colorsrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for color .", + "editType": "none" + }, + "sourcesrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for source .", + "editType": "none" + }, + "targetsrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for target .", + "editType": "none" + }, + "valuesrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for value .", + "editType": "none" + } + }, + "idssrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for ids .", + "editType": "none" + }, + "customdatasrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for customdata .", + "editType": "none" + }, + "hoverinfosrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for hoverinfo .", + "editType": "none" + } + } + }, + "table": { + "meta": { + "description": "Table view for detailed data viewing. The data are arranged in a grid of rows and columns. Most styling can be specified for columns, rows or individual cells. Table is using a column-major order, ie. the grid is represented as a vector of column vectors." + }, + "attributes": { + "type": "table", + "visible": { + "valType": "enumerated", + "values": [ + true, + false, + "legendonly" + ], + "role": "info", + "dflt": true, + "editType": "calc", + "description": "Determines whether or not this trace is visible. If *legendonly*, the trace is not drawn, but can appear as a legend item (provided that the legend itself is visible)." + }, + "showlegend": { + "valType": "boolean", + "role": "info", + "dflt": true, + "editType": "style", + "description": "Determines whether or not an item corresponding to this trace is shown in the legend." + }, + "legendgroup": { + "valType": "string", + "role": "info", + "dflt": "", + "editType": "style", + "description": "Sets the legend group for this trace. Traces part of the same legend group hide/show at the same time when toggling legend items." + }, + "opacity": { + "valType": "number", + "role": "style", + "min": 0, + "max": 1, + "dflt": 1, + "editType": "style", + "description": "Sets the opacity of the trace." + }, + "name": { + "valType": "string", + "role": "info", + "editType": "style", + "description": "Sets the trace name. The trace name appear as the legend item and on hover." + }, + "uid": { + "valType": "string", + "role": "info", + "dflt": "", + "editType": "calc" + }, + "ids": { + "valType": "data_array", + "editType": "calc", + "description": "Assigns id labels to each datum. These ids for object constancy of data points during animation.", + "role": "data" + }, + "customdata": { + "valType": "data_array", + "editType": "calc", + "description": "Assigns extra data each datum. This may be useful when listening to hover, click and selection events. Note that, *scatter* traces also appends customdata items in the markers DOM elements", + "role": "data" + }, + "selectedpoints": { + "valType": "any", + "role": "info", + "editType": "calc", + "description": "Array containing integer indices of selected points. Has an effect only for traces that support selections. Note that an empty array means an empty selection where the `unselected` are turned on for all points, whereas, any other non-array values means no selection all where the `selected` and `unselected` styles have no effect." + }, + "hoverinfo": { + "valType": "flaglist", + "role": "info", + "flags": [ + "x", + "y", + "z", + "text", + "name" + ], + "extras": [ + "all", + "none", + "skip" + ], + "arrayOk": true, + "dflt": "all", + "editType": "none", + "description": "Determines which trace information appear on hover. If `none` or `skip` are set, no information is displayed upon hovering. But, if `none` is set, click and hover events are still fired." + }, + "hoverlabel": { + "bgcolor": { + "valType": "color", + "role": "style", + "arrayOk": true, + "editType": "none", + "description": "Sets the background color of the hover labels for this trace" + }, + "bordercolor": { + "valType": "color", + "role": "style", + "arrayOk": true, + "editType": "none", + "description": "Sets the border color of the hover labels for this trace." + }, + "font": { + "family": { + "valType": "string", + "role": "style", + "noBlank": true, + "strict": true, + "editType": "none", + "description": "HTML font family - the typeface that will be applied by the web browser. The web browser will only be able to apply a font if it is available on the system which it operates. Provide multiple font families, separated by commas, to indicate the preference in which to apply fonts if they aren't available on the system. The plotly service (at https://plot.ly or on-premise) generates images on a server, where only a select number of fonts are installed and supported. These include *Arial*, *Balto*, *Courier New*, *Droid Sans*,, *Droid Serif*, *Droid Sans Mono*, *Gravitas One*, *Old Standard TT*, *Open Sans*, *Overpass*, *PT Sans Narrow*, *Raleway*, *Times New Roman*.", + "arrayOk": true + }, + "size": { + "valType": "number", + "role": "style", + "min": 1, + "editType": "none", + "arrayOk": true + }, + "color": { + "valType": "color", + "role": "style", + "editType": "none", + "arrayOk": true + }, + "editType": "none", + "description": "Sets the font used in hover labels.", + "role": "object", + "familysrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for family .", + "editType": "none" + }, + "sizesrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for size .", + "editType": "none" + }, + "colorsrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for color .", + "editType": "none" + } + }, + "namelength": { + "valType": "integer", + "min": -1, + "arrayOk": true, + "role": "style", + "editType": "none", + "description": "Sets the length (in number of characters) of the trace name in the hover labels for this trace. -1 shows the whole name regardless of length. 0-3 shows the first 0-3 characters, and an integer >3 will show the whole name if it is less than that many characters, but if it is longer, will truncate to `namelength - 3` characters and add an ellipsis." + }, + "editType": "calc", + "role": "object", + "bgcolorsrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for bgcolor .", + "editType": "none" + }, + "bordercolorsrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for bordercolor .", + "editType": "none" + }, + "namelengthsrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for namelength .", + "editType": "none" + } + }, + "stream": { + "token": { + "valType": "string", + "noBlank": true, + "strict": true, + "role": "info", + "editType": "calc", + "description": "The stream id number links a data trace on a plot with a stream. See https://plot.ly/settings for more details." + }, + "maxpoints": { + "valType": "number", + "min": 0, + "max": 10000, + "dflt": 500, + "role": "info", + "editType": "calc", + "description": "Sets the maximum number of points to keep on the plots from an incoming stream. If `maxpoints` is set to *50*, only the newest 50 points will be displayed on the plot." + }, + "editType": "calc", + "role": "object" + }, + "domain": { + "x": { + "valType": "info_array", + "role": "info", + "items": [ + { + "valType": "number", + "min": 0, + "max": 1, + "editType": "calc" + }, + { + "valType": "number", + "min": 0, + "max": 1, + "editType": "calc" + } + ], + "dflt": [ + 0, + 1 + ], + "description": "Sets the horizontal domain of this `table` trace (in plot fraction).", + "editType": "calc" + }, + "y": { + "valType": "info_array", + "role": "info", + "items": [ + { + "valType": "number", + "min": 0, + "max": 1, + "editType": "calc" + }, + { + "valType": "number", + "min": 0, + "max": 1, + "editType": "calc" + } + ], + "dflt": [ + 0, + 1 + ], + "description": "Sets the vertical domain of this `table` trace (in plot fraction).", + "editType": "calc" + }, + "editType": "calc", + "role": "object" + }, + "columnwidth": { + "valType": "number", + "arrayOk": true, + "dflt": null, + "role": "style", + "description": "The width of columns expressed as a ratio. Columns fill the available width in proportion of their specified column widths.", + "editType": "calc" + }, + "columnorder": { + "valType": "data_array", + "role": "data", + "description": "Specifies the rendered order of the data columns; for example, a value `2` at position `0` means that column index `0` in the data will be rendered as the third column, as columns have an index base of zero.", + "editType": "calc" + }, + "header": { + "values": { + "valType": "data_array", + "role": "data", + "dflt": [], + "description": "Header cell values. `values[m][n]` represents the value of the `n`th point in column `m`, therefore the `values[m]` vector length for all columns must be the same (longer vectors will be truncated). Each value must be a finite number or a string.", + "editType": "calc" + }, + "format": { + "valType": "data_array", + "role": "data", + "dflt": [], + "description": "Sets the cell value formatting rule using d3 formatting mini-language which is similar to those of Python. See https://github.com/d3/d3-format/blob/master/README.md#locale_format", + "editType": "calc" + }, + "prefix": { + "valType": "string", + "arrayOk": true, + "dflt": null, + "role": "style", + "description": "Prefix for cell values.", + "editType": "calc" + }, + "suffix": { + "valType": "string", + "arrayOk": true, + "dflt": null, + "role": "style", + "description": "Suffix for cell values.", + "editType": "calc" + }, + "height": { + "valType": "number", + "dflt": 28, + "role": "style", + "description": "The height of cells.", + "editType": "calc" + }, + "align": { + "valType": "enumerated", + "values": [ + "left", + "center", + "right" + ], + "dflt": "center", + "role": "style", + "editType": "calc", + "description": "Sets the horizontal alignment of the `text` within the box. Has an effect only if `text` spans more two or more lines (i.e. `text` contains one or more
HTML tags) or if an explicit width is set to override the text width.", + "arrayOk": true + }, + "line": { + "width": { + "valType": "number", + "arrayOk": true, + "dflt": 1, + "role": "style", + "editType": "calc" + }, + "color": { + "valType": "color", + "arrayOk": true, + "dflt": "grey", + "role": "style", + "editType": "calc" + }, + "editType": "calc", + "role": "object", + "widthsrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for width .", + "editType": "none" + }, + "colorsrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for color .", + "editType": "none" + } + }, + "fill": { + "color": { + "valType": "color", + "arrayOk": true, + "dflt": "white", + "role": "style", + "description": "Sets the cell fill color. It accepts either a specific color or an array of colors.", + "editType": "calc" + }, + "editType": "calc", + "role": "object", + "colorsrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for color .", + "editType": "none" + } + }, + "font": { + "family": { + "valType": "string", + "role": "style", + "noBlank": true, + "strict": true, + "description": "HTML font family - the typeface that will be applied by the web browser. The web browser will only be able to apply a font if it is available on the system which it operates. Provide multiple font families, separated by commas, to indicate the preference in which to apply fonts if they aren't available on the system. The plotly service (at https://plot.ly or on-premise) generates images on a server, where only a select number of fonts are installed and supported. These include *Arial*, *Balto*, *Courier New*, *Droid Sans*,, *Droid Serif*, *Droid Sans Mono*, *Gravitas One*, *Old Standard TT*, *Open Sans*, *Overpass*, *PT Sans Narrow*, *Raleway*, *Times New Roman*.", + "arrayOk": true, + "editType": "calc" + }, + "size": { + "valType": "number", + "role": "style", + "min": 1, + "arrayOk": true, + "editType": "calc" + }, + "color": { + "valType": "color", + "role": "style", + "arrayOk": true, + "editType": "calc" + }, + "description": "", + "editType": "calc", + "role": "object", + "familysrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for family .", + "editType": "none" + }, + "sizesrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for size .", + "editType": "none" + }, + "colorsrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for color .", + "editType": "none" + } + }, + "editType": "calc", + "role": "object", + "valuessrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for values .", + "editType": "none" + }, + "formatsrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for format .", + "editType": "none" + }, + "prefixsrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for prefix .", + "editType": "none" + }, + "suffixsrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for suffix .", + "editType": "none" + }, + "alignsrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for align .", + "editType": "none" + } + }, + "cells": { + "values": { + "valType": "data_array", + "role": "data", + "dflt": [], + "description": "Cell values. `values[m][n]` represents the value of the `n`th point in column `m`, therefore the `values[m]` vector length for all columns must be the same (longer vectors will be truncated). Each value must be a finite number or a string.", + "editType": "calc" + }, + "format": { + "valType": "data_array", + "role": "data", + "dflt": [], + "description": "Sets the cell value formatting rule using d3 formatting mini-language which is similar to those of Python. See https://github.com/d3/d3-format/blob/master/README.md#locale_format", + "editType": "calc" + }, + "prefix": { + "valType": "string", + "arrayOk": true, + "dflt": null, + "role": "style", + "description": "Prefix for cell values.", + "editType": "calc" + }, + "suffix": { + "valType": "string", + "arrayOk": true, + "dflt": null, + "role": "style", + "description": "Suffix for cell values.", + "editType": "calc" + }, + "height": { + "valType": "number", + "dflt": 20, + "role": "style", + "description": "The height of cells.", + "editType": "calc" + }, + "align": { + "valType": "enumerated", + "values": [ + "left", + "center", + "right" + ], + "dflt": "center", + "role": "style", + "editType": "calc", + "description": "Sets the horizontal alignment of the `text` within the box. Has an effect only if `text` spans more two or more lines (i.e. `text` contains one or more
HTML tags) or if an explicit width is set to override the text width.", + "arrayOk": true + }, + "line": { + "width": { + "valType": "number", + "arrayOk": true, + "dflt": 1, + "role": "style", + "editType": "calc" + }, + "color": { + "valType": "color", + "arrayOk": true, + "dflt": "grey", + "role": "style", + "editType": "calc" + }, + "editType": "calc", + "role": "object", + "widthsrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for width .", + "editType": "none" + }, + "colorsrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for color .", + "editType": "none" + } + }, + "fill": { + "color": { + "valType": "color", + "arrayOk": true, + "role": "style", + "dflt": "white", + "description": "Sets the cell fill color. It accepts either a specific color or an array of colors.", + "editType": "calc" + }, + "editType": "calc", + "role": "object", + "colorsrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for color .", + "editType": "none" + } + }, + "font": { + "family": { + "valType": "string", + "role": "style", + "noBlank": true, + "strict": true, + "description": "HTML font family - the typeface that will be applied by the web browser. The web browser will only be able to apply a font if it is available on the system which it operates. Provide multiple font families, separated by commas, to indicate the preference in which to apply fonts if they aren't available on the system. The plotly service (at https://plot.ly or on-premise) generates images on a server, where only a select number of fonts are installed and supported. These include *Arial*, *Balto*, *Courier New*, *Droid Sans*,, *Droid Serif*, *Droid Sans Mono*, *Gravitas One*, *Old Standard TT*, *Open Sans*, *Overpass*, *PT Sans Narrow*, *Raleway*, *Times New Roman*.", + "arrayOk": true, + "editType": "calc" + }, + "size": { + "valType": "number", + "role": "style", + "min": 1, + "arrayOk": true, + "editType": "calc" + }, + "color": { + "valType": "color", + "role": "style", + "arrayOk": true, + "editType": "calc" + }, + "description": "", + "editType": "calc", + "role": "object", + "familysrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for family .", + "editType": "none" + }, + "sizesrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for size .", + "editType": "none" + }, + "colorsrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for color .", + "editType": "none" + } + }, + "editType": "calc", + "role": "object", + "valuessrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for values .", + "editType": "none" + }, + "formatsrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for format .", + "editType": "none" + }, + "prefixsrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for prefix .", + "editType": "none" + }, + "suffixsrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for suffix .", + "editType": "none" + }, + "alignsrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for align .", + "editType": "none" + } + }, + "editType": "calc", + "idssrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for ids .", + "editType": "none" + }, + "customdatasrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for customdata .", + "editType": "none" + }, + "hoverinfosrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for hoverinfo .", + "editType": "none" + }, + "columnwidthsrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for columnwidth .", + "editType": "none" + }, + "columnordersrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for columnorder .", + "editType": "none" + } + } + }, + "carpet": { + "meta": { + "description": "The data describing carpet axis layout is set in `y` and (optionally) also `x`. If only `y` is present, `x` the plot is interpreted as a cheater plot and is filled in using the `y` values. `x` and `y` may either be 2D arrays matching with each dimension matching that of `a` and `b`, or they may be 1D arrays with total length equal to that of `a` and `b`." + }, + "attributes": { + "type": "carpet", + "visible": { + "valType": "enumerated", + "values": [ + true, + false, + "legendonly" + ], + "role": "info", + "dflt": true, + "editType": "calc", + "description": "Determines whether or not this trace is visible. If *legendonly*, the trace is not drawn, but can appear as a legend item (provided that the legend itself is visible)." + }, + "showlegend": { + "valType": "boolean", + "role": "info", + "dflt": true, + "editType": "style", + "description": "Determines whether or not an item corresponding to this trace is shown in the legend." + }, + "legendgroup": { + "valType": "string", + "role": "info", + "dflt": "", + "editType": "style", + "description": "Sets the legend group for this trace. Traces part of the same legend group hide/show at the same time when toggling legend items." + }, + "opacity": { + "valType": "number", + "role": "style", + "min": 0, + "max": 1, + "dflt": 1, + "editType": "style", + "description": "Sets the opacity of the trace." + }, + "name": { + "valType": "string", + "role": "info", + "editType": "style", + "description": "Sets the trace name. The trace name appear as the legend item and on hover." + }, + "uid": { + "valType": "string", + "role": "info", + "dflt": "", + "editType": "calc" + }, + "ids": { + "valType": "data_array", + "editType": "calc", + "description": "Assigns id labels to each datum. These ids for object constancy of data points during animation.", + "role": "data" + }, + "customdata": { + "valType": "data_array", + "editType": "calc", + "description": "Assigns extra data each datum. This may be useful when listening to hover, click and selection events. Note that, *scatter* traces also appends customdata items in the markers DOM elements", + "role": "data" + }, + "selectedpoints": { + "valType": "any", + "role": "info", + "editType": "calc", + "description": "Array containing integer indices of selected points. Has an effect only for traces that support selections. Note that an empty array means an empty selection where the `unselected` are turned on for all points, whereas, any other non-array values means no selection all where the `selected` and `unselected` styles have no effect." + }, + "hoverinfo": { + "valType": "flaglist", + "role": "info", + "flags": [ + "x", + "y", + "z", + "text", + "name" + ], + "extras": [ + "all", + "none", + "skip" + ], + "arrayOk": true, + "dflt": "all", + "editType": "none", + "description": "Determines which trace information appear on hover. If `none` or `skip` are set, no information is displayed upon hovering. But, if `none` is set, click and hover events are still fired." + }, + "hoverlabel": { + "bgcolor": { + "valType": "color", + "role": "style", + "arrayOk": true, + "editType": "none", + "description": "Sets the background color of the hover labels for this trace" + }, + "bordercolor": { + "valType": "color", + "role": "style", + "arrayOk": true, + "editType": "none", + "description": "Sets the border color of the hover labels for this trace." + }, + "font": { + "family": { + "valType": "string", + "role": "style", + "noBlank": true, + "strict": true, + "editType": "none", + "description": "HTML font family - the typeface that will be applied by the web browser. The web browser will only be able to apply a font if it is available on the system which it operates. Provide multiple font families, separated by commas, to indicate the preference in which to apply fonts if they aren't available on the system. The plotly service (at https://plot.ly or on-premise) generates images on a server, where only a select number of fonts are installed and supported. These include *Arial*, *Balto*, *Courier New*, *Droid Sans*,, *Droid Serif*, *Droid Sans Mono*, *Gravitas One*, *Old Standard TT*, *Open Sans*, *Overpass*, *PT Sans Narrow*, *Raleway*, *Times New Roman*.", + "arrayOk": true + }, + "size": { + "valType": "number", + "role": "style", + "min": 1, + "editType": "none", + "arrayOk": true + }, + "color": { + "valType": "color", + "role": "style", + "editType": "none", + "arrayOk": true + }, + "editType": "none", + "description": "Sets the font used in hover labels.", + "role": "object", + "familysrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for family .", + "editType": "none" + }, + "sizesrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for size .", + "editType": "none" + }, + "colorsrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for color .", + "editType": "none" + } + }, + "namelength": { + "valType": "integer", + "min": -1, + "arrayOk": true, + "role": "style", + "editType": "none", + "description": "Sets the length (in number of characters) of the trace name in the hover labels for this trace. -1 shows the whole name regardless of length. 0-3 shows the first 0-3 characters, and an integer >3 will show the whole name if it is less than that many characters, but if it is longer, will truncate to `namelength - 3` characters and add an ellipsis." + }, + "editType": "calc", + "role": "object", + "bgcolorsrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for bgcolor .", + "editType": "none" + }, + "bordercolorsrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for bordercolor .", + "editType": "none" + }, + "namelengthsrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for namelength .", + "editType": "none" + } + }, + "stream": { + "token": { + "valType": "string", + "noBlank": true, + "strict": true, + "role": "info", + "editType": "calc", + "description": "The stream id number links a data trace on a plot with a stream. See https://plot.ly/settings for more details." + }, + "maxpoints": { + "valType": "number", + "min": 0, + "max": 10000, + "dflt": 500, + "role": "info", + "editType": "calc", + "description": "Sets the maximum number of points to keep on the plots from an incoming stream. If `maxpoints` is set to *50*, only the newest 50 points will be displayed on the plot." + }, + "editType": "calc", + "role": "object" + }, + "carpet": { + "valType": "string", + "role": "info", + "editType": "calc", + "description": "An identifier for this carpet, so that `scattercarpet` and `scattercontour` traces can specify a carpet plot on which they lie" + }, + "x": { + "valType": "data_array", + "editType": "calc+clearAxisTypes", + "description": "A two dimensional array of x coordinates at each carpet point. If ommitted, the plot is a cheater plot and the xaxis is hidden by default.", + "role": "data" + }, + "y": { + "valType": "data_array", + "editType": "calc+clearAxisTypes", + "description": "A two dimensional array of y coordinates at each carpet point.", + "role": "data" + }, + "a": { + "valType": "data_array", + "editType": "calc", + "description": "An array containing values of the first parameter value", + "role": "data" + }, + "a0": { + "valType": "number", + "dflt": 0, + "role": "info", + "editType": "calc", + "description": "Alternate to `a`. Builds a linear space of a coordinates. Use with `da` where `a0` is the starting coordinate and `da` the step." + }, + "da": { + "valType": "number", + "dflt": 1, + "role": "info", + "editType": "calc", + "description": "Sets the a coordinate step. See `a0` for more info." + }, + "b": { + "valType": "data_array", + "editType": "calc", + "description": "A two dimensional array of y coordinates at each carpet point.", + "role": "data" + }, + "b0": { + "valType": "number", + "dflt": 0, + "role": "info", + "editType": "calc", + "description": "Alternate to `b`. Builds a linear space of a coordinates. Use with `db` where `b0` is the starting coordinate and `db` the step." + }, + "db": { + "valType": "number", + "dflt": 1, + "role": "info", + "editType": "calc", + "description": "Sets the b coordinate step. See `b0` for more info." + }, + "cheaterslope": { + "valType": "number", + "role": "info", + "dflt": 1, + "editType": "calc", + "description": "The shift applied to each successive row of data in creating a cheater plot. Only used if `x` is been ommitted." + }, + "aaxis": { + "color": { + "valType": "color", + "role": "style", + "editType": "calc", + "description": "Sets default for all colors associated with this axis all at once: line, font, tick, and grid colors. Grid color is lightened by blending this with the plot background Individual pieces can override this." + }, + "smoothing": { + "valType": "number", + "dflt": 1, + "min": 0, + "max": 1.3, + "role": "info", + "editType": "calc" + }, + "title": { + "valType": "string", + "role": "info", + "editType": "calc", + "description": "Sets the title of this axis." + }, + "titlefont": { + "family": { + "valType": "string", + "role": "style", + "noBlank": true, + "strict": true, + "editType": "calc", + "description": "HTML font family - the typeface that will be applied by the web browser. The web browser will only be able to apply a font if it is available on the system which it operates. Provide multiple font families, separated by commas, to indicate the preference in which to apply fonts if they aren't available on the system. The plotly service (at https://plot.ly or on-premise) generates images on a server, where only a select number of fonts are installed and supported. These include *Arial*, *Balto*, *Courier New*, *Droid Sans*,, *Droid Serif*, *Droid Sans Mono*, *Gravitas One*, *Old Standard TT*, *Open Sans*, *Overpass*, *PT Sans Narrow*, *Raleway*, *Times New Roman*." + }, + "size": { + "valType": "number", + "role": "style", + "min": 1, + "editType": "calc" + }, + "color": { + "valType": "color", + "role": "style", + "editType": "calc" + }, + "editType": "calc", + "description": "Sets this axis' title font.", + "role": "object" + }, + "titleoffset": { + "valType": "number", + "role": "info", + "dflt": 10, + "editType": "calc", + "description": "An additional amount by which to offset the title from the tick labels, given in pixels" + }, + "type": { + "valType": "enumerated", + "values": [ + "-", + "linear", + "date", + "category" + ], + "dflt": "-", + "role": "info", + "editType": "calc", + "description": "Sets the axis type. By default, plotly attempts to determined the axis type by looking into the data of the traces that referenced the axis in question." + }, + "autorange": { + "valType": "enumerated", + "values": [ + true, + false, + "reversed" + ], + "dflt": true, + "role": "style", + "editType": "calc", + "description": "Determines whether or not the range of this axis is computed in relation to the input data. See `rangemode` for more info. If `range` is provided, then `autorange` is set to *false*." + }, + "rangemode": { + "valType": "enumerated", + "values": [ + "normal", + "tozero", + "nonnegative" + ], + "dflt": "normal", + "role": "style", + "editType": "calc", + "description": "If *normal*, the range is computed in relation to the extrema of the input data. If *tozero*`, the range extends to 0, regardless of the input data If *nonnegative*, the range is non-negative, regardless of the input data." + }, + "range": { + "valType": "info_array", + "role": "info", + "editType": "calc", + "items": [ + { + "valType": "any", + "editType": "calc" + }, + { + "valType": "any", + "editType": "calc" + } + ], + "description": "Sets the range of this axis. If the axis `type` is *log*, then you must take the log of your desired range (e.g. to set the range from 1 to 100, set the range from 0 to 2). If the axis `type` is *date*, it should be date strings, like date data, though Date objects and unix milliseconds will be accepted and converted to strings. If the axis `type` is *category*, it should be numbers, using the scale where each category is assigned a serial number from zero in the order it appears." + }, + "fixedrange": { + "valType": "boolean", + "dflt": false, + "role": "info", + "editType": "calc", + "description": "Determines whether or not this axis is zoom-able. If true, then zoom is disabled." + }, + "cheatertype": { + "valType": "enumerated", + "values": [ + "index", + "value" + ], + "dflt": "value", + "role": "info", + "editType": "calc" + }, + "tickmode": { + "valType": "enumerated", + "values": [ + "linear", + "array" + ], + "dflt": "array", + "role": "info", + "editType": "calc" + }, + "nticks": { + "valType": "integer", + "min": 0, + "dflt": 0, + "role": "style", + "editType": "calc", + "description": "Specifies the maximum number of ticks for the particular axis. The actual number of ticks will be chosen automatically to be less than or equal to `nticks`. Has an effect only if `tickmode` is set to *auto*." + }, + "tickvals": { + "valType": "data_array", + "editType": "calc", + "description": "Sets the values at which ticks on this axis appear. Only has an effect if `tickmode` is set to *array*. Used with `ticktext`.", + "role": "data" + }, + "ticktext": { + "valType": "data_array", + "editType": "calc", + "description": "Sets the text displayed at the ticks position via `tickvals`. Only has an effect if `tickmode` is set to *array*. Used with `tickvals`.", + "role": "data" + }, + "showticklabels": { + "valType": "enumerated", + "values": [ + "start", + "end", + "both", + "none" + ], + "dflt": "start", + "role": "style", + "editType": "calc", + "description": "Determines whether axis labels are drawn on the low side, the high side, both, or neither side of the axis." + }, + "tickfont": { + "family": { + "valType": "string", + "role": "style", + "noBlank": true, + "strict": true, + "editType": "calc", + "description": "HTML font family - the typeface that will be applied by the web browser. The web browser will only be able to apply a font if it is available on the system which it operates. Provide multiple font families, separated by commas, to indicate the preference in which to apply fonts if they aren't available on the system. The plotly service (at https://plot.ly or on-premise) generates images on a server, where only a select number of fonts are installed and supported. These include *Arial*, *Balto*, *Courier New*, *Droid Sans*,, *Droid Serif*, *Droid Sans Mono*, *Gravitas One*, *Old Standard TT*, *Open Sans*, *Overpass*, *PT Sans Narrow*, *Raleway*, *Times New Roman*." + }, + "size": { + "valType": "number", + "role": "style", + "min": 1, + "editType": "calc" + }, + "color": { + "valType": "color", + "role": "style", + "editType": "calc" + }, + "editType": "calc", + "description": "Sets the tick font.", + "role": "object" + }, + "tickangle": { + "valType": "angle", + "dflt": "auto", + "role": "style", + "editType": "calc", + "description": "Sets the angle of the tick labels with respect to the horizontal. For example, a `tickangle` of -90 draws the tick labels vertically." + }, + "tickprefix": { + "valType": "string", + "dflt": "", + "role": "style", + "editType": "calc", + "description": "Sets a tick label prefix." + }, + "showtickprefix": { + "valType": "enumerated", + "values": [ + "all", + "first", + "last", + "none" + ], + "dflt": "all", + "role": "style", + "editType": "calc", + "description": "If *all*, all tick labels are displayed with a prefix. If *first*, only the first tick is displayed with a prefix. If *last*, only the last tick is displayed with a suffix. If *none*, tick prefixes are hidden." + }, + "ticksuffix": { + "valType": "string", + "dflt": "", + "role": "style", + "editType": "calc", + "description": "Sets a tick label suffix." + }, + "showticksuffix": { + "valType": "enumerated", + "values": [ + "all", + "first", + "last", + "none" + ], + "dflt": "all", + "role": "style", + "editType": "calc", + "description": "Same as `showtickprefix` but for tick suffixes." + }, + "showexponent": { + "valType": "enumerated", + "values": [ + "all", + "first", + "last", + "none" + ], + "dflt": "all", + "role": "style", + "editType": "calc", + "description": "If *all*, all exponents are shown besides their significands. If *first*, only the exponent of the first tick is shown. If *last*, only the exponent of the last tick is shown. If *none*, no exponents appear." + }, + "exponentformat": { + "valType": "enumerated", + "values": [ + "none", + "e", + "E", + "power", + "SI", + "B" + ], + "dflt": "B", + "role": "style", + "editType": "calc", + "description": "Determines a formatting rule for the tick exponents. For example, consider the number 1,000,000,000. If *none*, it appears as 1,000,000,000. If *e*, 1e+9. If *E*, 1E+9. If *power*, 1x10^9 (with 9 in a super script). If *SI*, 1G. If *B*, 1B." + }, + "separatethousands": { + "valType": "boolean", + "dflt": false, + "role": "style", + "editType": "calc", + "description": "If \"true\", even 4-digit integers are separated" + }, + "tickformat": { + "valType": "string", + "dflt": "", + "role": "style", + "editType": "calc", + "description": "Sets the tick label formatting rule using d3 formatting mini-languages which are very similar to those in Python. For numbers, see: https://github.com/d3/d3-format/blob/master/README.md#locale_format And for dates see: https://github.com/d3/d3-time-format/blob/master/README.md#locale_format We add one item to d3's date formatter: *%{n}f* for fractional seconds with n digits. For example, *2016-10-13 09:15:23.456* with tickformat *%H~%M~%S.%2f* would display *09~15~23.46*" + }, + "tickformatstops": { + "items": { + "tickformatstop": { + "dtickrange": { + "valType": "info_array", + "role": "info", + "items": [ + { + "valType": "any", + "editType": "calc" + }, + { + "valType": "any", + "editType": "calc" + } + ], + "editType": "calc", + "description": "range [*min*, *max*], where *min*, *max* - dtick values which describe some zoom level, it is possible to omit *min* or *max* value by passing *null*" + }, + "value": { + "valType": "string", + "dflt": "", + "role": "style", + "editType": "calc", + "description": "string - dtickformat for described zoom level, the same as *tickformat*" + }, + "editType": "calc", + "role": "object" + } + }, + "role": "object" + }, + "categoryorder": { + "valType": "enumerated", + "values": [ + "trace", + "category ascending", + "category descending", + "array" + ], + "dflt": "trace", + "role": "info", + "editType": "calc", + "description": "Specifies the ordering logic for the case of categorical variables. By default, plotly uses *trace*, which specifies the order that is present in the data supplied. Set `categoryorder` to *category ascending* or *category descending* if order should be determined by the alphanumerical order of the category names. Set `categoryorder` to *array* to derive the ordering from the attribute `categoryarray`. If a category is not found in the `categoryarray` array, the sorting behavior for that attribute will be identical to the *trace* mode. The unspecified categories will follow the categories in `categoryarray`." + }, + "categoryarray": { + "valType": "data_array", + "role": "data", + "editType": "calc", + "description": "Sets the order in which categories on this axis appear. Only has an effect if `categoryorder` is set to *array*. Used with `categoryorder`." + }, + "labelpadding": { + "valType": "integer", + "role": "style", + "dflt": 10, + "editType": "calc", + "description": "Extra padding between label and the axis" + }, + "labelprefix": { + "valType": "string", + "role": "style", + "editType": "calc", + "description": "Sets a axis label prefix." + }, + "labelsuffix": { + "valType": "string", + "dflt": "", + "role": "style", + "editType": "calc", + "description": "Sets a axis label suffix." + }, + "showline": { + "valType": "boolean", + "dflt": false, + "role": "style", + "editType": "calc", + "description": "Determines whether or not a line bounding this axis is drawn." + }, + "linecolor": { + "valType": "color", + "dflt": "#444", + "role": "style", + "editType": "calc", + "description": "Sets the axis line color." + }, + "linewidth": { + "valType": "number", + "min": 0, + "dflt": 1, + "role": "style", + "editType": "calc", + "description": "Sets the width (in px) of the axis line." + }, + "gridcolor": { + "valType": "color", + "role": "style", + "editType": "calc", + "description": "Sets the axis line color." + }, + "gridwidth": { + "valType": "number", + "min": 0, + "dflt": 1, + "role": "style", + "editType": "calc", + "description": "Sets the width (in px) of the axis line." + }, + "showgrid": { + "valType": "boolean", + "role": "style", + "dflt": true, + "editType": "calc", + "description": "Determines whether or not grid lines are drawn. If *true*, the grid lines are drawn at every tick mark." + }, + "minorgridcount": { + "valType": "integer", + "min": 0, + "dflt": 0, + "role": "info", + "editType": "calc", + "description": "Sets the number of minor grid ticks per major grid tick" + }, + "minorgridwidth": { + "valType": "number", + "min": 0, + "dflt": 1, + "role": "style", + "editType": "calc", + "description": "Sets the width (in px) of the grid lines." + }, + "minorgridcolor": { + "valType": "color", + "dflt": "#eee", + "role": "style", + "editType": "calc", + "description": "Sets the color of the grid lines." + }, + "startline": { + "valType": "boolean", + "role": "style", + "editType": "calc", + "description": "Determines whether or not a line is drawn at along the starting value of this axis. If *true*, the start line is drawn on top of the grid lines." + }, + "startlinecolor": { + "valType": "color", + "role": "style", + "editType": "calc", + "description": "Sets the line color of the start line." + }, + "startlinewidth": { + "valType": "number", + "dflt": 1, + "role": "style", + "editType": "calc", + "description": "Sets the width (in px) of the start line." + }, + "endline": { + "valType": "boolean", + "role": "style", + "editType": "calc", + "description": "Determines whether or not a line is drawn at along the final value of this axis. If *true*, the end line is drawn on top of the grid lines." + }, + "endlinewidth": { + "valType": "number", + "dflt": 1, + "role": "style", + "editType": "calc", + "description": "Sets the width (in px) of the end line." + }, + "endlinecolor": { + "valType": "color", + "role": "style", + "editType": "calc", + "description": "Sets the line color of the end line." + }, + "tick0": { + "valType": "number", + "min": 0, + "dflt": 0, + "role": "info", + "editType": "calc", + "description": "The starting index of grid lines along the axis" + }, + "dtick": { + "valType": "number", + "min": 0, + "dflt": 1, + "role": "info", + "editType": "calc", + "description": "The stride between grid lines along the axis" + }, + "arraytick0": { + "valType": "integer", + "min": 0, + "dflt": 0, + "role": "info", + "editType": "calc", + "description": "The starting index of grid lines along the axis" + }, + "arraydtick": { + "valType": "integer", + "min": 1, + "dflt": 1, + "role": "info", + "editType": "calc", + "description": "The stride between grid lines along the axis" + }, + "editType": "calc", + "role": "object", + "tickvalssrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for tickvals .", + "editType": "none" + }, + "ticktextsrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for ticktext .", + "editType": "none" + }, + "categoryarraysrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for categoryarray .", + "editType": "none" + } + }, + "baxis": { + "color": { + "valType": "color", + "role": "style", + "editType": "calc", + "description": "Sets default for all colors associated with this axis all at once: line, font, tick, and grid colors. Grid color is lightened by blending this with the plot background Individual pieces can override this." + }, + "smoothing": { + "valType": "number", + "dflt": 1, + "min": 0, + "max": 1.3, + "role": "info", + "editType": "calc" + }, + "title": { + "valType": "string", + "role": "info", + "editType": "calc", + "description": "Sets the title of this axis." + }, + "titlefont": { + "family": { + "valType": "string", + "role": "style", + "noBlank": true, + "strict": true, + "editType": "calc", + "description": "HTML font family - the typeface that will be applied by the web browser. The web browser will only be able to apply a font if it is available on the system which it operates. Provide multiple font families, separated by commas, to indicate the preference in which to apply fonts if they aren't available on the system. The plotly service (at https://plot.ly or on-premise) generates images on a server, where only a select number of fonts are installed and supported. These include *Arial*, *Balto*, *Courier New*, *Droid Sans*,, *Droid Serif*, *Droid Sans Mono*, *Gravitas One*, *Old Standard TT*, *Open Sans*, *Overpass*, *PT Sans Narrow*, *Raleway*, *Times New Roman*." + }, + "size": { + "valType": "number", + "role": "style", + "min": 1, + "editType": "calc" + }, + "color": { + "valType": "color", + "role": "style", + "editType": "calc" + }, + "editType": "calc", + "description": "Sets this axis' title font.", + "role": "object" + }, + "titleoffset": { + "valType": "number", + "role": "info", + "dflt": 10, + "editType": "calc", + "description": "An additional amount by which to offset the title from the tick labels, given in pixels" + }, + "type": { + "valType": "enumerated", + "values": [ + "-", + "linear", + "date", + "category" + ], + "dflt": "-", + "role": "info", + "editType": "calc", + "description": "Sets the axis type. By default, plotly attempts to determined the axis type by looking into the data of the traces that referenced the axis in question." + }, + "autorange": { + "valType": "enumerated", + "values": [ + true, + false, + "reversed" + ], + "dflt": true, + "role": "style", + "editType": "calc", + "description": "Determines whether or not the range of this axis is computed in relation to the input data. See `rangemode` for more info. If `range` is provided, then `autorange` is set to *false*." + }, + "rangemode": { + "valType": "enumerated", + "values": [ + "normal", + "tozero", + "nonnegative" + ], + "dflt": "normal", + "role": "style", + "editType": "calc", + "description": "If *normal*, the range is computed in relation to the extrema of the input data. If *tozero*`, the range extends to 0, regardless of the input data If *nonnegative*, the range is non-negative, regardless of the input data." + }, + "range": { + "valType": "info_array", + "role": "info", + "editType": "calc", + "items": [ + { + "valType": "any", + "editType": "calc" + }, + { + "valType": "any", + "editType": "calc" + } + ], + "description": "Sets the range of this axis. If the axis `type` is *log*, then you must take the log of your desired range (e.g. to set the range from 1 to 100, set the range from 0 to 2). If the axis `type` is *date*, it should be date strings, like date data, though Date objects and unix milliseconds will be accepted and converted to strings. If the axis `type` is *category*, it should be numbers, using the scale where each category is assigned a serial number from zero in the order it appears." + }, + "fixedrange": { + "valType": "boolean", + "dflt": false, + "role": "info", + "editType": "calc", + "description": "Determines whether or not this axis is zoom-able. If true, then zoom is disabled." + }, + "cheatertype": { + "valType": "enumerated", + "values": [ + "index", + "value" + ], + "dflt": "value", + "role": "info", + "editType": "calc" + }, + "tickmode": { + "valType": "enumerated", + "values": [ + "linear", + "array" + ], + "dflt": "array", + "role": "info", + "editType": "calc" + }, + "nticks": { + "valType": "integer", + "min": 0, + "dflt": 0, + "role": "style", + "editType": "calc", + "description": "Specifies the maximum number of ticks for the particular axis. The actual number of ticks will be chosen automatically to be less than or equal to `nticks`. Has an effect only if `tickmode` is set to *auto*." + }, + "tickvals": { + "valType": "data_array", + "editType": "calc", + "description": "Sets the values at which ticks on this axis appear. Only has an effect if `tickmode` is set to *array*. Used with `ticktext`.", + "role": "data" + }, + "ticktext": { + "valType": "data_array", + "editType": "calc", + "description": "Sets the text displayed at the ticks position via `tickvals`. Only has an effect if `tickmode` is set to *array*. Used with `tickvals`.", + "role": "data" + }, + "showticklabels": { + "valType": "enumerated", + "values": [ + "start", + "end", + "both", + "none" + ], + "dflt": "start", + "role": "style", + "editType": "calc", + "description": "Determines whether axis labels are drawn on the low side, the high side, both, or neither side of the axis." + }, + "tickfont": { + "family": { + "valType": "string", + "role": "style", + "noBlank": true, + "strict": true, + "editType": "calc", + "description": "HTML font family - the typeface that will be applied by the web browser. The web browser will only be able to apply a font if it is available on the system which it operates. Provide multiple font families, separated by commas, to indicate the preference in which to apply fonts if they aren't available on the system. The plotly service (at https://plot.ly or on-premise) generates images on a server, where only a select number of fonts are installed and supported. These include *Arial*, *Balto*, *Courier New*, *Droid Sans*,, *Droid Serif*, *Droid Sans Mono*, *Gravitas One*, *Old Standard TT*, *Open Sans*, *Overpass*, *PT Sans Narrow*, *Raleway*, *Times New Roman*." + }, + "size": { + "valType": "number", + "role": "style", + "min": 1, + "editType": "calc" + }, + "color": { + "valType": "color", + "role": "style", + "editType": "calc" + }, + "editType": "calc", + "description": "Sets the tick font.", + "role": "object" + }, + "tickangle": { + "valType": "angle", + "dflt": "auto", + "role": "style", + "editType": "calc", + "description": "Sets the angle of the tick labels with respect to the horizontal. For example, a `tickangle` of -90 draws the tick labels vertically." + }, + "tickprefix": { + "valType": "string", + "dflt": "", + "role": "style", + "editType": "calc", + "description": "Sets a tick label prefix." + }, + "showtickprefix": { + "valType": "enumerated", + "values": [ + "all", + "first", + "last", + "none" + ], + "dflt": "all", + "role": "style", + "editType": "calc", + "description": "If *all*, all tick labels are displayed with a prefix. If *first*, only the first tick is displayed with a prefix. If *last*, only the last tick is displayed with a suffix. If *none*, tick prefixes are hidden." + }, + "ticksuffix": { + "valType": "string", + "dflt": "", + "role": "style", + "editType": "calc", + "description": "Sets a tick label suffix." + }, + "showticksuffix": { + "valType": "enumerated", + "values": [ + "all", + "first", + "last", + "none" + ], + "dflt": "all", + "role": "style", + "editType": "calc", + "description": "Same as `showtickprefix` but for tick suffixes." + }, + "showexponent": { + "valType": "enumerated", + "values": [ + "all", + "first", + "last", + "none" + ], + "dflt": "all", + "role": "style", + "editType": "calc", + "description": "If *all*, all exponents are shown besides their significands. If *first*, only the exponent of the first tick is shown. If *last*, only the exponent of the last tick is shown. If *none*, no exponents appear." + }, + "exponentformat": { + "valType": "enumerated", + "values": [ + "none", + "e", + "E", + "power", + "SI", + "B" + ], + "dflt": "B", + "role": "style", + "editType": "calc", + "description": "Determines a formatting rule for the tick exponents. For example, consider the number 1,000,000,000. If *none*, it appears as 1,000,000,000. If *e*, 1e+9. If *E*, 1E+9. If *power*, 1x10^9 (with 9 in a super script). If *SI*, 1G. If *B*, 1B." + }, + "separatethousands": { + "valType": "boolean", + "dflt": false, + "role": "style", + "editType": "calc", + "description": "If \"true\", even 4-digit integers are separated" + }, + "tickformat": { + "valType": "string", + "dflt": "", + "role": "style", + "editType": "calc", + "description": "Sets the tick label formatting rule using d3 formatting mini-languages which are very similar to those in Python. For numbers, see: https://github.com/d3/d3-format/blob/master/README.md#locale_format And for dates see: https://github.com/d3/d3-time-format/blob/master/README.md#locale_format We add one item to d3's date formatter: *%{n}f* for fractional seconds with n digits. For example, *2016-10-13 09:15:23.456* with tickformat *%H~%M~%S.%2f* would display *09~15~23.46*" + }, + "tickformatstops": { + "items": { + "tickformatstop": { + "dtickrange": { + "valType": "info_array", + "role": "info", + "items": [ + { + "valType": "any", + "editType": "calc" + }, + { + "valType": "any", + "editType": "calc" + } + ], + "editType": "calc", + "description": "range [*min*, *max*], where *min*, *max* - dtick values which describe some zoom level, it is possible to omit *min* or *max* value by passing *null*" + }, + "value": { + "valType": "string", + "dflt": "", + "role": "style", + "editType": "calc", + "description": "string - dtickformat for described zoom level, the same as *tickformat*" + }, + "editType": "calc", + "role": "object" + } + }, + "role": "object" + }, + "categoryorder": { + "valType": "enumerated", + "values": [ + "trace", + "category ascending", + "category descending", + "array" + ], + "dflt": "trace", + "role": "info", + "editType": "calc", + "description": "Specifies the ordering logic for the case of categorical variables. By default, plotly uses *trace*, which specifies the order that is present in the data supplied. Set `categoryorder` to *category ascending* or *category descending* if order should be determined by the alphanumerical order of the category names. Set `categoryorder` to *array* to derive the ordering from the attribute `categoryarray`. If a category is not found in the `categoryarray` array, the sorting behavior for that attribute will be identical to the *trace* mode. The unspecified categories will follow the categories in `categoryarray`." + }, + "categoryarray": { + "valType": "data_array", + "role": "data", + "editType": "calc", + "description": "Sets the order in which categories on this axis appear. Only has an effect if `categoryorder` is set to *array*. Used with `categoryorder`." + }, + "labelpadding": { + "valType": "integer", + "role": "style", + "dflt": 10, + "editType": "calc", + "description": "Extra padding between label and the axis" + }, + "labelprefix": { + "valType": "string", + "role": "style", + "editType": "calc", + "description": "Sets a axis label prefix." + }, + "labelsuffix": { + "valType": "string", + "dflt": "", + "role": "style", + "editType": "calc", + "description": "Sets a axis label suffix." + }, + "showline": { + "valType": "boolean", + "dflt": false, + "role": "style", + "editType": "calc", + "description": "Determines whether or not a line bounding this axis is drawn." + }, + "linecolor": { + "valType": "color", + "dflt": "#444", + "role": "style", + "editType": "calc", + "description": "Sets the axis line color." + }, + "linewidth": { + "valType": "number", + "min": 0, + "dflt": 1, + "role": "style", + "editType": "calc", + "description": "Sets the width (in px) of the axis line." + }, + "gridcolor": { + "valType": "color", + "role": "style", + "editType": "calc", + "description": "Sets the axis line color." + }, + "gridwidth": { + "valType": "number", + "min": 0, + "dflt": 1, + "role": "style", + "editType": "calc", + "description": "Sets the width (in px) of the axis line." + }, + "showgrid": { + "valType": "boolean", + "role": "style", + "dflt": true, + "editType": "calc", + "description": "Determines whether or not grid lines are drawn. If *true*, the grid lines are drawn at every tick mark." + }, + "minorgridcount": { + "valType": "integer", + "min": 0, + "dflt": 0, + "role": "info", + "editType": "calc", + "description": "Sets the number of minor grid ticks per major grid tick" + }, + "minorgridwidth": { + "valType": "number", + "min": 0, + "dflt": 1, + "role": "style", + "editType": "calc", + "description": "Sets the width (in px) of the grid lines." + }, + "minorgridcolor": { + "valType": "color", + "dflt": "#eee", + "role": "style", + "editType": "calc", + "description": "Sets the color of the grid lines." + }, + "startline": { + "valType": "boolean", + "role": "style", + "editType": "calc", + "description": "Determines whether or not a line is drawn at along the starting value of this axis. If *true*, the start line is drawn on top of the grid lines." + }, + "startlinecolor": { + "valType": "color", + "role": "style", + "editType": "calc", + "description": "Sets the line color of the start line." + }, + "startlinewidth": { + "valType": "number", + "dflt": 1, + "role": "style", + "editType": "calc", + "description": "Sets the width (in px) of the start line." + }, + "endline": { + "valType": "boolean", + "role": "style", + "editType": "calc", + "description": "Determines whether or not a line is drawn at along the final value of this axis. If *true*, the end line is drawn on top of the grid lines." + }, + "endlinewidth": { + "valType": "number", + "dflt": 1, + "role": "style", + "editType": "calc", + "description": "Sets the width (in px) of the end line." + }, + "endlinecolor": { + "valType": "color", + "role": "style", + "editType": "calc", + "description": "Sets the line color of the end line." + }, + "tick0": { + "valType": "number", + "min": 0, + "dflt": 0, + "role": "info", + "editType": "calc", + "description": "The starting index of grid lines along the axis" + }, + "dtick": { + "valType": "number", + "min": 0, + "dflt": 1, + "role": "info", + "editType": "calc", + "description": "The stride between grid lines along the axis" + }, + "arraytick0": { + "valType": "integer", + "min": 0, + "dflt": 0, + "role": "info", + "editType": "calc", + "description": "The starting index of grid lines along the axis" + }, + "arraydtick": { + "valType": "integer", + "min": 1, + "dflt": 1, + "role": "info", + "editType": "calc", + "description": "The stride between grid lines along the axis" + }, + "editType": "calc", + "role": "object", + "tickvalssrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for tickvals .", + "editType": "none" + }, + "ticktextsrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for ticktext .", + "editType": "none" + }, + "categoryarraysrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for categoryarray .", + "editType": "none" + } + }, + "font": { + "family": { + "valType": "string", + "role": "style", + "noBlank": true, + "strict": true, + "editType": "calc", + "description": "HTML font family - the typeface that will be applied by the web browser. The web browser will only be able to apply a font if it is available on the system which it operates. Provide multiple font families, separated by commas, to indicate the preference in which to apply fonts if they aren't available on the system. The plotly service (at https://plot.ly or on-premise) generates images on a server, where only a select number of fonts are installed and supported. These include *Arial*, *Balto*, *Courier New*, *Droid Sans*,, *Droid Serif*, *Droid Sans Mono*, *Gravitas One*, *Old Standard TT*, *Open Sans*, *Overpass*, *PT Sans Narrow*, *Raleway*, *Times New Roman*.", + "dflt": "\"Open Sans\", verdana, arial, sans-serif" + }, + "size": { + "valType": "number", + "role": "style", + "min": 1, + "editType": "calc", + "dflt": 12 + }, + "color": { + "valType": "color", + "role": "style", + "editType": "calc", + "dflt": "#444" + }, + "editType": "calc", + "description": "The default font used for axis & tick labels on this carpet", + "role": "object" + }, + "color": { + "valType": "color", + "dflt": "#444", + "role": "style", + "editType": "plot", + "description": "Sets default for all colors associated with this axis all at once: line, font, tick, and grid colors. Grid color is lightened by blending this with the plot background Individual pieces can override this." + }, + "xaxis": { + "valType": "subplotid", + "role": "info", + "dflt": "x", + "editType": "calc+clearAxisTypes", + "description": "Sets a reference between this trace's x coordinates and a 2D cartesian x axis. If *x* (the default value), the x coordinates refer to `layout.xaxis`. If *x2*, the x coordinates refer to `layout.xaxis2`, and so on." + }, + "yaxis": { + "valType": "subplotid", + "role": "info", + "dflt": "y", + "editType": "calc+clearAxisTypes", + "description": "Sets a reference between this trace's y coordinates and a 2D cartesian y axis. If *y* (the default value), the y coordinates refer to `layout.yaxis`. If *y2*, the y coordinates refer to `layout.xaxis2`, and so on." + }, + "idssrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for ids .", + "editType": "none" + }, + "customdatasrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for customdata .", + "editType": "none" + }, + "hoverinfosrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for hoverinfo .", + "editType": "none" + }, + "xsrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for x .", + "editType": "none" + }, + "ysrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for y .", + "editType": "none" + }, + "asrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for a .", + "editType": "none" + }, + "bsrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for b .", + "editType": "none" + } + } + }, + "scattercarpet": { + "meta": { + "hrName": "scatter_carpet", + "description": "Plots a scatter trace on either the first carpet axis or the carpet axis with a matching `carpet` attribute." + }, + "attributes": { + "type": "scattercarpet", + "visible": { + "valType": "enumerated", + "values": [ + true, + false, + "legendonly" + ], + "role": "info", + "dflt": true, + "editType": "calc", + "description": "Determines whether or not this trace is visible. If *legendonly*, the trace is not drawn, but can appear as a legend item (provided that the legend itself is visible)." + }, + "showlegend": { + "valType": "boolean", + "role": "info", + "dflt": true, + "editType": "style", + "description": "Determines whether or not an item corresponding to this trace is shown in the legend." + }, + "legendgroup": { + "valType": "string", + "role": "info", + "dflt": "", + "editType": "style", + "description": "Sets the legend group for this trace. Traces part of the same legend group hide/show at the same time when toggling legend items." + }, + "opacity": { + "valType": "number", + "role": "style", + "min": 0, + "max": 1, + "dflt": 1, + "editType": "style", + "description": "Sets the opacity of the trace." + }, + "name": { + "valType": "string", + "role": "info", + "editType": "style", + "description": "Sets the trace name. The trace name appear as the legend item and on hover." + }, + "uid": { + "valType": "string", + "role": "info", + "dflt": "", + "editType": "calc" + }, + "ids": { + "valType": "data_array", + "editType": "calc", + "description": "Assigns id labels to each datum. These ids for object constancy of data points during animation.", + "role": "data" + }, + "customdata": { + "valType": "data_array", + "editType": "calc", + "description": "Assigns extra data each datum. This may be useful when listening to hover, click and selection events. Note that, *scatter* traces also appends customdata items in the markers DOM elements", + "role": "data" + }, + "selectedpoints": { + "valType": "any", + "role": "info", + "editType": "calc", + "description": "Array containing integer indices of selected points. Has an effect only for traces that support selections. Note that an empty array means an empty selection where the `unselected` are turned on for all points, whereas, any other non-array values means no selection all where the `selected` and `unselected` styles have no effect." + }, + "hoverinfo": { + "valType": "flaglist", + "role": "info", + "flags": [ + "a", + "b", + "text", + "name", + "name" + ], + "extras": [ + "all", + "none", + "skip" + ], + "arrayOk": true, + "dflt": "all", + "editType": "none", + "description": "Determines which trace information appear on hover. If `none` or `skip` are set, no information is displayed upon hovering. But, if `none` is set, click and hover events are still fired." + }, + "hoverlabel": { + "bgcolor": { + "valType": "color", + "role": "style", + "arrayOk": true, + "editType": "none", + "description": "Sets the background color of the hover labels for this trace" + }, + "bordercolor": { + "valType": "color", + "role": "style", + "arrayOk": true, + "editType": "none", + "description": "Sets the border color of the hover labels for this trace." + }, + "font": { + "family": { + "valType": "string", + "role": "style", + "noBlank": true, + "strict": true, + "editType": "none", + "description": "HTML font family - the typeface that will be applied by the web browser. The web browser will only be able to apply a font if it is available on the system which it operates. Provide multiple font families, separated by commas, to indicate the preference in which to apply fonts if they aren't available on the system. The plotly service (at https://plot.ly or on-premise) generates images on a server, where only a select number of fonts are installed and supported. These include *Arial*, *Balto*, *Courier New*, *Droid Sans*,, *Droid Serif*, *Droid Sans Mono*, *Gravitas One*, *Old Standard TT*, *Open Sans*, *Overpass*, *PT Sans Narrow*, *Raleway*, *Times New Roman*.", + "arrayOk": true + }, + "size": { + "valType": "number", + "role": "style", + "min": 1, + "editType": "none", + "arrayOk": true + }, + "color": { + "valType": "color", + "role": "style", + "editType": "none", + "arrayOk": true + }, + "editType": "none", + "description": "Sets the font used in hover labels.", + "role": "object", + "familysrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for family .", + "editType": "none" + }, + "sizesrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for size .", + "editType": "none" + }, + "colorsrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for color .", + "editType": "none" + } + }, + "namelength": { + "valType": "integer", + "min": -1, + "arrayOk": true, + "role": "style", + "editType": "none", + "description": "Sets the length (in number of characters) of the trace name in the hover labels for this trace. -1 shows the whole name regardless of length. 0-3 shows the first 0-3 characters, and an integer >3 will show the whole name if it is less than that many characters, but if it is longer, will truncate to `namelength - 3` characters and add an ellipsis." + }, + "editType": "calc", + "role": "object", + "bgcolorsrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for bgcolor .", + "editType": "none" + }, + "bordercolorsrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for bordercolor .", + "editType": "none" + }, + "namelengthsrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for namelength .", + "editType": "none" + } + }, + "stream": { + "token": { + "valType": "string", + "noBlank": true, + "strict": true, + "role": "info", + "editType": "calc", + "description": "The stream id number links a data trace on a plot with a stream. See https://plot.ly/settings for more details." + }, + "maxpoints": { + "valType": "number", + "min": 0, + "max": 10000, + "dflt": 500, + "role": "info", + "editType": "calc", + "description": "Sets the maximum number of points to keep on the plots from an incoming stream. If `maxpoints` is set to *50*, only the newest 50 points will be displayed on the plot." + }, + "editType": "calc", + "role": "object" + }, + "carpet": { + "valType": "string", + "role": "info", + "editType": "calc", + "description": "An identifier for this carpet, so that `scattercarpet` and `scattercontour` traces can specify a carpet plot on which they lie" + }, + "a": { + "valType": "data_array", + "editType": "calc", + "description": "Sets the quantity of component `a` in each data point. If `a`, `b`, and `c` are all provided, they need not be normalized, only the relative values matter. If only two arrays are provided they must be normalized to match `ternary.sum`.", + "role": "data" + }, + "b": { + "valType": "data_array", + "editType": "calc", + "description": "Sets the quantity of component `a` in each data point. If `a`, `b`, and `c` are all provided, they need not be normalized, only the relative values matter. If only two arrays are provided they must be normalized to match `ternary.sum`.", + "role": "data" + }, + "mode": { + "valType": "flaglist", + "flags": [ + "lines", + "markers", + "text" + ], + "extras": [ + "none" + ], + "role": "info", + "editType": "calc", + "description": "Determines the drawing mode for this scatter trace. If the provided `mode` includes *text* then the `text` elements appear at the coordinates. Otherwise, the `text` elements appear on hover. If there are less than 20 points, then the default is *lines+markers*. Otherwise, *lines*.", + "dflt": "markers" + }, + "text": { + "valType": "string", + "role": "info", + "dflt": "", + "arrayOk": true, + "editType": "calc", + "description": "Sets text elements associated with each (a,b,c) point. If a single string, the same string appears over all the data points. If an array of strings, the items are mapped in order to the the data points in (a,b,c)." + }, + "line": { + "color": { + "valType": "color", + "role": "style", + "editType": "style", + "description": "Sets the line color." + }, + "width": { + "valType": "number", + "min": 0, + "dflt": 2, + "role": "style", + "editType": "style", + "description": "Sets the line width (in px)." + }, + "dash": { + "valType": "string", + "values": [ + "solid", + "dot", + "dash", + "longdash", + "dashdot", + "longdashdot" + ], + "dflt": "solid", + "role": "style", + "editType": "style", + "description": "Sets the dash style of lines. Set to a dash type string (*solid*, *dot*, *dash*, *longdash*, *dashdot*, or *longdashdot*) or a dash length list in px (eg *5px,10px,2px,2px*)." + }, + "shape": { + "valType": "enumerated", + "values": [ + "linear", + "spline" + ], + "dflt": "linear", + "role": "style", + "editType": "plot", + "description": "Determines the line shape. With *spline* the lines are drawn using spline interpolation. The other available values correspond to step-wise line shapes." + }, + "smoothing": { + "valType": "number", + "min": 0, + "max": 1.3, + "dflt": 1, + "role": "style", + "editType": "plot", + "description": "Has an effect only if `shape` is set to *spline* Sets the amount of smoothing. *0* corresponds to no smoothing (equivalent to a *linear* shape)." + }, + "editType": "calc", + "role": "object" + }, + "connectgaps": { + "valType": "boolean", + "dflt": false, + "role": "info", + "editType": "calc", + "description": "Determines whether or not gaps (i.e. {nan} or missing values) in the provided data arrays are connected." + }, + "fill": { + "valType": "enumerated", + "values": [ + "none", + "toself", + "tonext" + ], + "dflt": "none", + "role": "style", + "editType": "calc", + "description": "Sets the area to fill with a solid color. Use with `fillcolor` if not *none*. scatterternary has a subset of the options available to scatter. *toself* connects the endpoints of the trace (or each segment of the trace if it has gaps) into a closed shape. *tonext* fills the space between two traces if one completely encloses the other (eg consecutive contour lines), and behaves like *toself* if there is no trace before it. *tonext* should not be used if one trace does not enclose the other." + }, + "fillcolor": { + "valType": "color", + "role": "style", + "editType": "style", + "description": "Sets the fill color. Defaults to a half-transparent variant of the line color, marker color, or marker line color, whichever is available." + }, + "marker": { + "symbol": { + "valType": "enumerated", + "values": [ + 0, + "circle", + 100, + "circle-open", + 200, + "circle-dot", + 300, + "circle-open-dot", + 1, + "square", + 101, + "square-open", + 201, + "square-dot", + 301, + "square-open-dot", + 2, + "diamond", + 102, + "diamond-open", + 202, + "diamond-dot", + 302, + "diamond-open-dot", + 3, + "cross", + 103, + "cross-open", + 203, + "cross-dot", + 303, + "cross-open-dot", + 4, + "x", + 104, + "x-open", + 204, + "x-dot", + 304, + "x-open-dot", + 5, + "triangle-up", + 105, + "triangle-up-open", + 205, + "triangle-up-dot", + 305, + "triangle-up-open-dot", + 6, + "triangle-down", + 106, + "triangle-down-open", + 206, + "triangle-down-dot", + 306, + "triangle-down-open-dot", + 7, + "triangle-left", + 107, + "triangle-left-open", + 207, + "triangle-left-dot", + 307, + "triangle-left-open-dot", + 8, + "triangle-right", + 108, + "triangle-right-open", + 208, + "triangle-right-dot", + 308, + "triangle-right-open-dot", + 9, + "triangle-ne", + 109, + "triangle-ne-open", + 209, + "triangle-ne-dot", + 309, + "triangle-ne-open-dot", + 10, + "triangle-se", + 110, + "triangle-se-open", + 210, + "triangle-se-dot", + 310, + "triangle-se-open-dot", + 11, + "triangle-sw", + 111, + "triangle-sw-open", + 211, + "triangle-sw-dot", + 311, + "triangle-sw-open-dot", + 12, + "triangle-nw", + 112, + "triangle-nw-open", + 212, + "triangle-nw-dot", + 312, + "triangle-nw-open-dot", + 13, + "pentagon", + 113, + "pentagon-open", + 213, + "pentagon-dot", + 313, + "pentagon-open-dot", + 14, + "hexagon", + 114, + "hexagon-open", + 214, + "hexagon-dot", + 314, + "hexagon-open-dot", + 15, + "hexagon2", + 115, + "hexagon2-open", + 215, + "hexagon2-dot", + 315, + "hexagon2-open-dot", + 16, + "octagon", + 116, + "octagon-open", + 216, + "octagon-dot", + 316, + "octagon-open-dot", + 17, + "star", + 117, + "star-open", + 217, + "star-dot", + 317, + "star-open-dot", + 18, + "hexagram", + 118, + "hexagram-open", + 218, + "hexagram-dot", + 318, + "hexagram-open-dot", + 19, + "star-triangle-up", + 119, + "star-triangle-up-open", + 219, + "star-triangle-up-dot", + 319, + "star-triangle-up-open-dot", + 20, + "star-triangle-down", + 120, + "star-triangle-down-open", + 220, + "star-triangle-down-dot", + 320, + "star-triangle-down-open-dot", + 21, + "star-square", + 121, + "star-square-open", + 221, + "star-square-dot", + 321, + "star-square-open-dot", + 22, + "star-diamond", + 122, + "star-diamond-open", + 222, + "star-diamond-dot", + 322, + "star-diamond-open-dot", + 23, + "diamond-tall", + 123, + "diamond-tall-open", + 223, + "diamond-tall-dot", + 323, + "diamond-tall-open-dot", + 24, + "diamond-wide", + 124, + "diamond-wide-open", + 224, + "diamond-wide-dot", + 324, + "diamond-wide-open-dot", + 25, + "hourglass", + 125, + "hourglass-open", + 26, + "bowtie", + 126, + "bowtie-open", + 27, + "circle-cross", + 127, + "circle-cross-open", + 28, + "circle-x", + 128, + "circle-x-open", + 29, + "square-cross", + 129, + "square-cross-open", + 30, + "square-x", + 130, + "square-x-open", + 31, + "diamond-cross", + 131, + "diamond-cross-open", + 32, + "diamond-x", + 132, + "diamond-x-open", + 33, + "cross-thin", + 133, + "cross-thin-open", + 34, + "x-thin", + 134, + "x-thin-open", + 35, + "asterisk", + 135, + "asterisk-open", + 36, + "hash", + 136, + "hash-open", + 236, + "hash-dot", + 336, + "hash-open-dot", + 37, + "y-up", + 137, + "y-up-open", + 38, + "y-down", + 138, + "y-down-open", + 39, + "y-left", + 139, + "y-left-open", + 40, + "y-right", + 140, + "y-right-open", + 41, + "line-ew", + 141, + "line-ew-open", + 42, + "line-ns", + 142, + "line-ns-open", + 43, + "line-ne", + 143, + "line-ne-open", + 44, + "line-nw", + 144, + "line-nw-open" + ], + "dflt": "circle", + "arrayOk": true, + "role": "style", + "editType": "style", + "description": "Sets the marker symbol type. Adding 100 is equivalent to appending *-open* to a symbol name. Adding 200 is equivalent to appending *-dot* to a symbol name. Adding 300 is equivalent to appending *-open-dot* or *dot-open* to a symbol name." + }, + "opacity": { + "valType": "number", + "min": 0, + "max": 1, + "arrayOk": true, + "role": "style", + "editType": "style", + "description": "Sets the marker opacity." + }, + "maxdisplayed": { + "valType": "number", + "min": 0, + "dflt": 0, + "role": "style", + "editType": "plot", + "description": "Sets a maximum number of points to be drawn on the graph. *0* corresponds to no limit." + }, + "size": { + "valType": "number", + "min": 0, + "dflt": 6, + "arrayOk": true, + "role": "style", + "editType": "calcIfAutorange", + "description": "Sets the marker size (in px)." + }, + "sizeref": { + "valType": "number", + "dflt": 1, + "role": "style", + "editType": "calc", + "description": "Has an effect only if `marker.size` is set to a numerical array. Sets the scale factor used to determine the rendered size of marker points. Use with `sizemin` and `sizemode`." + }, + "sizemin": { + "valType": "number", + "min": 0, + "dflt": 0, + "role": "style", + "editType": "calc", + "description": "Has an effect only if `marker.size` is set to a numerical array. Sets the minimum size (in px) of the rendered marker points." + }, + "sizemode": { + "valType": "enumerated", + "values": [ + "diameter", + "area" + ], + "dflt": "diameter", + "role": "info", + "editType": "calc", + "description": "Has an effect only if `marker.size` is set to a numerical array. Sets the rule for which the data in `size` is converted to pixels." + }, + "line": { + "width": { + "valType": "number", + "min": 0, + "arrayOk": true, + "role": "style", + "editType": "style", + "description": "Sets the width (in px) of the lines bounding the marker points." + }, + "editType": "calc", + "color": { + "valType": "color", + "arrayOk": true, + "role": "style", + "editType": "style", + "description": "Sets the color. It accepts either a specific color or an array of numbers that are mapped to the colorscale relative to the max and min values of the array or relative to `cmin` and `cmax` if set." + }, + "colorscale": { + "valType": "colorscale", + "role": "style", + "editType": "calc", + "impliedEdits": { + "autocolorscale": false + }, + "description": "Sets the colorscale and only has an effect if `color` is set to a numerical array. The colorscale must be an array containing arrays mapping a normalized value to an rgb, rgba, hex, hsl, hsv, or named color string. At minimum, a mapping for the lowest (0) and highest (1) values are required. For example, `[[0, 'rgb(0,0,255)', [1, 'rgb(255,0,0)']]`. To control the bounds of the colorscale in color space, use `cmin` and `cmax`. Alternatively, `colorscale` may be a palette name string of the following list: Greys, YlGnBu, Greens, YlOrRd, Bluered, RdBu, Reds, Blues, Picnic, Rainbow, Portland, Jet, Hot, Blackbody, Earth, Electric, Viridis" + }, + "cauto": { + "valType": "boolean", + "role": "info", + "dflt": true, + "editType": "calc", + "impliedEdits": {}, + "description": "Has an effect only if `color` is set to a numerical array and `cmin`, `cmax` are set by the user. In this case, it controls whether the range of colors in `colorscale` is mapped to the range of values in the `color` array (`cauto: true`), or the `cmin`/`cmax` values (`cauto: false`). Defaults to `false` when `cmin`, `cmax` are set by the user." + }, + "cmax": { + "valType": "number", + "role": "info", + "dflt": null, + "editType": "plot", + "impliedEdits": { + "cauto": false + }, + "description": "Has an effect only if `color` is set to a numerical array. Sets the upper bound of the color domain. Value should be associated to the `color` array index, and if set, `cmin` must be set as well." + }, + "cmin": { + "valType": "number", + "role": "info", + "dflt": null, + "editType": "plot", + "impliedEdits": { + "cauto": false + }, + "description": "Has an effect only if `color` is set to a numerical array. Sets the lower bound of the color domain. Value should be associated to the `color` array index, and if set, `cmax` must be set as well." + }, + "autocolorscale": { + "valType": "boolean", + "role": "style", + "dflt": true, + "editType": "calc", + "impliedEdits": {}, + "description": "Has an effect only if `color` is set to a numerical array. Determines whether the colorscale is a default palette (`autocolorscale: true`) or the palette determined by `colorscale`. In case `colorscale` is unspecified or `autocolorscale` is true, the default palette will be chosen according to whether numbers in the `color` array are all positive, all negative or mixed." + }, + "reversescale": { + "valType": "boolean", + "role": "style", + "dflt": false, + "editType": "calc", + "description": "Has an effect only if `color` is set to a numerical array. Reverses the color mapping if true (`cmin` will correspond to the last color in the array and `cmax` will correspond to the first color)." + }, + "role": "object", + "widthsrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for width .", + "editType": "none" + }, + "colorsrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for color .", + "editType": "none" + } + }, + "gradient": { + "type": { + "valType": "enumerated", + "values": [ + "radial", + "horizontal", + "vertical", + "none" + ], + "arrayOk": true, + "dflt": "none", + "role": "style", + "editType": "calc", + "description": "Sets the type of gradient used to fill the markers" + }, + "color": { + "valType": "color", + "arrayOk": true, + "role": "style", + "editType": "calc", + "description": "Sets the final color of the gradient fill: the center color for radial, the right for horizontal, or the bottom for vertical." + }, + "editType": "calc", + "role": "object", + "typesrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for type .", + "editType": "none" + }, + "colorsrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for color .", + "editType": "none" + } + }, + "editType": "calc", + "color": { + "valType": "color", + "arrayOk": true, + "role": "style", + "editType": "style", + "description": "Sets the marker color. It accepts either a specific color or an array of numbers that are mapped to the colorscale relative to the max and min values of the array or relative to `cmin` and `cmax` if set." + }, + "colorscale": { + "valType": "colorscale", + "role": "style", + "editType": "calc", + "impliedEdits": { + "autocolorscale": false + }, + "description": "Sets the colorscale and only has an effect if `marker.color` is set to a numerical array. The colorscale must be an array containing arrays mapping a normalized value to an rgb, rgba, hex, hsl, hsv, or named color string. At minimum, a mapping for the lowest (0) and highest (1) values are required. For example, `[[0, 'rgb(0,0,255)', [1, 'rgb(255,0,0)']]`. To control the bounds of the colorscale in color space, use `marker.cmin` and `marker.cmax`. Alternatively, `colorscale` may be a palette name string of the following list: Greys, YlGnBu, Greens, YlOrRd, Bluered, RdBu, Reds, Blues, Picnic, Rainbow, Portland, Jet, Hot, Blackbody, Earth, Electric, Viridis" + }, + "cauto": { + "valType": "boolean", + "role": "info", + "dflt": true, + "editType": "calc", + "impliedEdits": {}, + "description": "Has an effect only if `marker.color` is set to a numerical array and `cmin`, `cmax` are set by the user. In this case, it controls whether the range of colors in `colorscale` is mapped to the range of values in the `color` array (`cauto: true`), or the `cmin`/`cmax` values (`cauto: false`). Defaults to `false` when `cmin`, `cmax` are set by the user." + }, + "cmax": { + "valType": "number", + "role": "info", + "dflt": null, + "editType": "plot", + "impliedEdits": { + "cauto": false + }, + "description": "Has an effect only if `marker.color` is set to a numerical array. Sets the upper bound of the color domain. Value should be associated to the `marker.color` array index, and if set, `marker.cmin` must be set as well." + }, + "cmin": { + "valType": "number", + "role": "info", + "dflt": null, + "editType": "plot", + "impliedEdits": { + "cauto": false + }, + "description": "Has an effect only if `marker.color` is set to a numerical array. Sets the lower bound of the color domain. Value should be associated to the `marker.color` array index, and if set, `marker.cmax` must be set as well." + }, + "autocolorscale": { + "valType": "boolean", + "role": "style", + "dflt": true, + "editType": "calc", + "impliedEdits": {}, + "description": "Has an effect only if `marker.color` is set to a numerical array. Determines whether the colorscale is a default palette (`autocolorscale: true`) or the palette determined by `marker.colorscale`. In case `colorscale` is unspecified or `autocolorscale` is true, the default palette will be chosen according to whether numbers in the `color` array are all positive, all negative or mixed." + }, + "reversescale": { + "valType": "boolean", + "role": "style", + "dflt": false, + "editType": "calc", + "description": "Has an effect only if `marker.color` is set to a numerical array. Reverses the color mapping if true (`cmin` will correspond to the last color in the array and `cmax` will correspond to the first color)." + }, + "showscale": { + "valType": "boolean", + "role": "info", + "dflt": false, + "editType": "calc", + "description": "Has an effect only if `marker.color` is set to a numerical array. Determines whether or not a colorbar is displayed." + }, + "colorbar": { + "thicknessmode": { + "valType": "enumerated", + "values": [ + "fraction", + "pixels" + ], + "role": "style", + "dflt": "pixels", + "description": "Determines whether this color bar's thickness (i.e. the measure in the constant color direction) is set in units of plot *fraction* or in *pixels*. Use `thickness` to set the value.", + "editType": "colorbars" + }, + "thickness": { + "valType": "number", + "role": "style", + "min": 0, + "dflt": 30, + "description": "Sets the thickness of the color bar This measure excludes the size of the padding, ticks and labels.", + "editType": "colorbars" + }, + "lenmode": { + "valType": "enumerated", + "values": [ + "fraction", + "pixels" + ], + "role": "info", + "dflt": "fraction", + "description": "Determines whether this color bar's length (i.e. the measure in the color variation direction) is set in units of plot *fraction* or in *pixels. Use `len` to set the value.", + "editType": "colorbars" + }, + "len": { + "valType": "number", + "min": 0, + "dflt": 1, + "role": "style", + "description": "Sets the length of the color bar This measure excludes the padding of both ends. That is, the color bar length is this length minus the padding on both ends.", + "editType": "colorbars" + }, + "x": { + "valType": "number", + "dflt": 1.02, + "min": -2, + "max": 3, + "role": "style", + "description": "Sets the x position of the color bar (in plot fraction).", + "editType": "colorbars" + }, + "xanchor": { + "valType": "enumerated", + "values": [ + "left", + "center", + "right" + ], + "dflt": "left", + "role": "style", + "description": "Sets this color bar's horizontal position anchor. This anchor binds the `x` position to the *left*, *center* or *right* of the color bar.", + "editType": "colorbars" + }, + "xpad": { + "valType": "number", + "role": "style", + "min": 0, + "dflt": 10, + "description": "Sets the amount of padding (in px) along the x direction.", + "editType": "colorbars" + }, + "y": { + "valType": "number", + "role": "style", + "dflt": 0.5, + "min": -2, + "max": 3, + "description": "Sets the y position of the color bar (in plot fraction).", + "editType": "colorbars" + }, + "yanchor": { + "valType": "enumerated", + "values": [ + "top", + "middle", + "bottom" + ], + "role": "style", + "dflt": "middle", + "description": "Sets this color bar's vertical position anchor This anchor binds the `y` position to the *top*, *middle* or *bottom* of the color bar.", + "editType": "colorbars" + }, + "ypad": { + "valType": "number", + "role": "style", + "min": 0, + "dflt": 10, + "description": "Sets the amount of padding (in px) along the y direction.", + "editType": "colorbars" + }, + "outlinecolor": { + "valType": "color", + "dflt": "#444", + "role": "style", + "editType": "colorbars", + "description": "Sets the axis line color." + }, + "outlinewidth": { + "valType": "number", + "min": 0, + "dflt": 1, + "role": "style", + "editType": "colorbars", + "description": "Sets the width (in px) of the axis line." + }, + "bordercolor": { + "valType": "color", + "dflt": "#444", + "role": "style", + "editType": "colorbars", + "description": "Sets the axis line color." + }, + "borderwidth": { + "valType": "number", + "role": "style", + "min": 0, + "dflt": 0, + "description": "Sets the width (in px) or the border enclosing this color bar.", + "editType": "colorbars" + }, + "bgcolor": { + "valType": "color", + "role": "style", + "dflt": "rgba(0,0,0,0)", + "description": "Sets the color of padded area.", + "editType": "colorbars" + }, + "tickmode": { + "valType": "enumerated", + "values": [ + "auto", + "linear", + "array" + ], + "role": "info", + "editType": "colorbars", + "impliedEdits": {}, + "description": "Sets the tick mode for this axis. If *auto*, the number of ticks is set via `nticks`. If *linear*, the placement of the ticks is determined by a starting position `tick0` and a tick step `dtick` (*linear* is the default value if `tick0` and `dtick` are provided). If *array*, the placement of the ticks is set via `tickvals` and the tick text is `ticktext`. (*array* is the default value if `tickvals` is provided)." + }, + "nticks": { + "valType": "integer", + "min": 0, + "dflt": 0, + "role": "style", + "editType": "colorbars", + "description": "Specifies the maximum number of ticks for the particular axis. The actual number of ticks will be chosen automatically to be less than or equal to `nticks`. Has an effect only if `tickmode` is set to *auto*." + }, + "tick0": { + "valType": "any", + "role": "style", + "editType": "colorbars", + "impliedEdits": { + "tickmode": "linear" + }, + "description": "Sets the placement of the first tick on this axis. Use with `dtick`. If the axis `type` is *log*, then you must take the log of your starting tick (e.g. to set the starting tick to 100, set the `tick0` to 2) except when `dtick`=*L* (see `dtick` for more info). If the axis `type` is *date*, it should be a date string, like date data. If the axis `type` is *category*, it should be a number, using the scale where each category is assigned a serial number from zero in the order it appears." + }, + "dtick": { + "valType": "any", + "role": "style", + "editType": "colorbars", + "impliedEdits": { + "tickmode": "linear" + }, + "description": "Sets the step in-between ticks on this axis. Use with `tick0`. Must be a positive number, or special strings available to *log* and *date* axes. If the axis `type` is *log*, then ticks are set every 10^(n*dtick) where n is the tick number. For example, to set a tick mark at 1, 10, 100, 1000, ... set dtick to 1. To set tick marks at 1, 100, 10000, ... set dtick to 2. To set tick marks at 1, 5, 25, 125, 625, 3125, ... set dtick to log_10(5), or 0.69897000433. *log* has several special values; *L*, where `f` is a positive number, gives ticks linearly spaced in value (but not position). For example `tick0` = 0.1, `dtick` = *L0.5* will put ticks at 0.1, 0.6, 1.1, 1.6 etc. To show powers of 10 plus small digits between, use *D1* (all digits) or *D2* (only 2 and 5). `tick0` is ignored for *D1* and *D2*. If the axis `type` is *date*, then you must convert the time to milliseconds. For example, to set the interval between ticks to one day, set `dtick` to 86400000.0. *date* also has special values *M* gives ticks spaced by a number of months. `n` must be a positive integer. To set ticks on the 15th of every third month, set `tick0` to *2000-01-15* and `dtick` to *M3*. To set ticks every 4 years, set `dtick` to *M48*" + }, + "tickvals": { + "valType": "data_array", + "editType": "colorbars", + "description": "Sets the values at which ticks on this axis appear. Only has an effect if `tickmode` is set to *array*. Used with `ticktext`.", + "role": "data" + }, + "ticktext": { + "valType": "data_array", + "editType": "colorbars", + "description": "Sets the text displayed at the ticks position via `tickvals`. Only has an effect if `tickmode` is set to *array*. Used with `tickvals`.", + "role": "data" + }, + "ticks": { + "valType": "enumerated", + "values": [ + "outside", + "inside", + "" + ], + "role": "style", + "editType": "colorbars", + "description": "Determines whether ticks are drawn or not. If **, this axis' ticks are not drawn. If *outside* (*inside*), this axis' are drawn outside (inside) the axis lines.", + "dflt": "" + }, + "ticklen": { + "valType": "number", + "min": 0, + "dflt": 5, + "role": "style", + "editType": "colorbars", + "description": "Sets the tick length (in px)." + }, + "tickwidth": { + "valType": "number", + "min": 0, + "dflt": 1, + "role": "style", + "editType": "colorbars", + "description": "Sets the tick width (in px)." + }, + "tickcolor": { + "valType": "color", + "dflt": "#444", + "role": "style", + "editType": "colorbars", + "description": "Sets the tick color." + }, + "showticklabels": { + "valType": "boolean", + "dflt": true, + "role": "style", + "editType": "colorbars", + "description": "Determines whether or not the tick labels are drawn." + }, + "tickfont": { + "family": { + "valType": "string", + "role": "style", + "noBlank": true, + "strict": true, + "description": "HTML font family - the typeface that will be applied by the web browser. The web browser will only be able to apply a font if it is available on the system which it operates. Provide multiple font families, separated by commas, to indicate the preference in which to apply fonts if they aren't available on the system. The plotly service (at https://plot.ly or on-premise) generates images on a server, where only a select number of fonts are installed and supported. These include *Arial*, *Balto*, *Courier New*, *Droid Sans*,, *Droid Serif*, *Droid Sans Mono*, *Gravitas One*, *Old Standard TT*, *Open Sans*, *Overpass*, *PT Sans Narrow*, *Raleway*, *Times New Roman*.", + "editType": "colorbars" + }, + "size": { + "valType": "number", + "role": "style", + "min": 1, + "editType": "colorbars" + }, + "color": { + "valType": "color", + "role": "style", + "editType": "colorbars" + }, + "description": "Sets the color bar's tick label font", + "editType": "colorbars", + "role": "object" + }, + "tickangle": { + "valType": "angle", + "dflt": "auto", + "role": "style", + "editType": "colorbars", + "description": "Sets the angle of the tick labels with respect to the horizontal. For example, a `tickangle` of -90 draws the tick labels vertically." + }, + "tickformat": { + "valType": "string", + "dflt": "", + "role": "style", + "editType": "colorbars", + "description": "Sets the tick label formatting rule using d3 formatting mini-languages which are very similar to those in Python. For numbers, see: https://github.com/d3/d3-format/blob/master/README.md#locale_format And for dates see: https://github.com/d3/d3-time-format/blob/master/README.md#locale_format We add one item to d3's date formatter: *%{n}f* for fractional seconds with n digits. For example, *2016-10-13 09:15:23.456* with tickformat *%H~%M~%S.%2f* would display *09~15~23.46*" + }, + "tickformatstops": { + "items": { + "tickformatstop": { + "dtickrange": { + "valType": "info_array", + "role": "info", + "items": [ + { + "valType": "any", + "editType": "colorbars" + }, + { + "valType": "any", + "editType": "colorbars" + } + ], + "editType": "colorbars", + "description": "range [*min*, *max*], where *min*, *max* - dtick values which describe some zoom level, it is possible to omit *min* or *max* value by passing *null*" + }, + "value": { + "valType": "string", + "dflt": "", + "role": "style", + "editType": "colorbars", + "description": "string - dtickformat for described zoom level, the same as *tickformat*" + }, + "editType": "colorbars", + "role": "object" + } + }, + "role": "object" + }, + "tickprefix": { + "valType": "string", + "dflt": "", + "role": "style", + "editType": "colorbars", + "description": "Sets a tick label prefix." + }, + "showtickprefix": { + "valType": "enumerated", + "values": [ + "all", + "first", + "last", + "none" + ], + "dflt": "all", + "role": "style", + "editType": "colorbars", + "description": "If *all*, all tick labels are displayed with a prefix. If *first*, only the first tick is displayed with a prefix. If *last*, only the last tick is displayed with a suffix. If *none*, tick prefixes are hidden." + }, + "ticksuffix": { + "valType": "string", + "dflt": "", + "role": "style", + "editType": "colorbars", + "description": "Sets a tick label suffix." + }, + "showticksuffix": { + "valType": "enumerated", + "values": [ + "all", + "first", + "last", + "none" + ], + "dflt": "all", + "role": "style", + "editType": "colorbars", + "description": "Same as `showtickprefix` but for tick suffixes." + }, + "separatethousands": { + "valType": "boolean", + "dflt": false, + "role": "style", + "editType": "colorbars", + "description": "If \"true\", even 4-digit integers are separated" + }, + "exponentformat": { + "valType": "enumerated", + "values": [ + "none", + "e", + "E", + "power", + "SI", + "B" + ], + "dflt": "B", + "role": "style", + "editType": "colorbars", + "description": "Determines a formatting rule for the tick exponents. For example, consider the number 1,000,000,000. If *none*, it appears as 1,000,000,000. If *e*, 1e+9. If *E*, 1E+9. If *power*, 1x10^9 (with 9 in a super script). If *SI*, 1G. If *B*, 1B." + }, + "showexponent": { + "valType": "enumerated", + "values": [ + "all", + "first", + "last", + "none" + ], + "dflt": "all", + "role": "style", + "editType": "colorbars", + "description": "If *all*, all exponents are shown besides their significands. If *first*, only the exponent of the first tick is shown. If *last*, only the exponent of the last tick is shown. If *none*, no exponents appear." + }, + "title": { + "valType": "string", + "role": "info", + "dflt": "Click to enter colorscale title", + "description": "Sets the title of the color bar.", + "editType": "colorbars" + }, + "titlefont": { + "family": { + "valType": "string", + "role": "style", + "noBlank": true, + "strict": true, + "description": "HTML font family - the typeface that will be applied by the web browser. The web browser will only be able to apply a font if it is available on the system which it operates. Provide multiple font families, separated by commas, to indicate the preference in which to apply fonts if they aren't available on the system. The plotly service (at https://plot.ly or on-premise) generates images on a server, where only a select number of fonts are installed and supported. These include *Arial*, *Balto*, *Courier New*, *Droid Sans*,, *Droid Serif*, *Droid Sans Mono*, *Gravitas One*, *Old Standard TT*, *Open Sans*, *Overpass*, *PT Sans Narrow*, *Raleway*, *Times New Roman*.", + "editType": "colorbars" + }, + "size": { + "valType": "number", + "role": "style", + "min": 1, + "editType": "colorbars" + }, + "color": { + "valType": "color", + "role": "style", + "editType": "colorbars" + }, + "description": "Sets this color bar's title font.", + "editType": "colorbars", + "role": "object" + }, + "titleside": { + "valType": "enumerated", + "values": [ + "right", + "top", + "bottom" + ], + "role": "style", + "dflt": "top", + "description": "Determines the location of the colorbar title with respect to the color bar.", + "editType": "colorbars" + }, + "editType": "colorbars", + "role": "object", + "tickvalssrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for tickvals .", + "editType": "none" + }, + "ticktextsrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for ticktext .", + "editType": "none" + } + }, + "role": "object", + "symbolsrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for symbol .", + "editType": "none" + }, + "opacitysrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for opacity .", + "editType": "none" + }, + "sizesrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for size .", + "editType": "none" + }, + "colorsrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for color .", + "editType": "none" + } + }, + "textfont": { + "family": { + "valType": "string", + "role": "style", + "noBlank": true, + "strict": true, + "editType": "calc", + "description": "HTML font family - the typeface that will be applied by the web browser. The web browser will only be able to apply a font if it is available on the system which it operates. Provide multiple font families, separated by commas, to indicate the preference in which to apply fonts if they aren't available on the system. The plotly service (at https://plot.ly or on-premise) generates images on a server, where only a select number of fonts are installed and supported. These include *Arial*, *Balto*, *Courier New*, *Droid Sans*,, *Droid Serif*, *Droid Sans Mono*, *Gravitas One*, *Old Standard TT*, *Open Sans*, *Overpass*, *PT Sans Narrow*, *Raleway*, *Times New Roman*.", + "arrayOk": true + }, + "size": { + "valType": "number", + "role": "style", + "min": 1, + "editType": "calc", + "arrayOk": true + }, + "color": { + "valType": "color", + "role": "style", + "editType": "style", + "arrayOk": true + }, + "editType": "calc", + "description": "Sets the text font.", + "role": "object", + "familysrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for family .", + "editType": "none" + }, + "sizesrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for size .", + "editType": "none" + }, + "colorsrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for color .", + "editType": "none" + } + }, + "textposition": { + "valType": "enumerated", + "values": [ + "top left", + "top center", + "top right", + "middle left", + "middle center", + "middle right", + "bottom left", + "bottom center", + "bottom right" + ], + "dflt": "middle center", + "arrayOk": true, + "role": "style", + "editType": "calc", + "description": "Sets the positions of the `text` elements with respects to the (x,y) coordinates." + }, + "selected": { + "marker": { + "opacity": { + "valType": "number", + "min": 0, + "max": 1, + "role": "style", + "editType": "style", + "description": "Sets the marker opacity of selected points." + }, + "color": { + "valType": "color", + "role": "style", + "editType": "style", + "description": "Sets the marker color of selected points." + }, + "size": { + "valType": "number", + "min": 0, + "role": "style", + "editType": "style", + "description": "Sets the marker size of selected points." + }, + "editType": "style", + "role": "object" + }, + "textfont": { + "color": { + "valType": "color", + "role": "style", + "editType": "style", + "description": "Sets the text font color of selected points." + }, + "editType": "style", + "role": "object" + }, + "editType": "style", + "role": "object" + }, + "unselected": { + "marker": { + "opacity": { + "valType": "number", + "min": 0, + "max": 1, + "role": "style", + "editType": "style", + "description": "Sets the marker opacity of unselected points, applied only when a selection exists." + }, + "color": { + "valType": "color", + "role": "style", + "editType": "style", + "description": "Sets the marker color of unselected points, applied only when a selection exists." + }, + "size": { + "valType": "number", + "min": 0, + "role": "style", + "editType": "style", + "description": "Sets the marker size of unselected points, applied only when a selection exists." + }, + "editType": "style", + "role": "object" + }, + "textfont": { + "color": { + "valType": "color", + "role": "style", + "editType": "style", + "description": "Sets the text font color of unselected points, applied only when a selection exists." + }, + "editType": "style", + "role": "object" + }, + "editType": "style", + "role": "object" + }, + "hoveron": { + "valType": "flaglist", + "flags": [ + "points", + "fills" + ], + "role": "info", + "editType": "style", + "description": "Do the hover effects highlight individual points (markers or line points) or do they highlight filled regions? If the fill is *toself* or *tonext* and there are no markers or text, then the default is *fills*, otherwise it is *points*." + }, + "xaxis": { + "valType": "subplotid", + "role": "info", + "dflt": "x", + "editType": "calc+clearAxisTypes", + "description": "Sets a reference between this trace's x coordinates and a 2D cartesian x axis. If *x* (the default value), the x coordinates refer to `layout.xaxis`. If *x2*, the x coordinates refer to `layout.xaxis2`, and so on." + }, + "yaxis": { + "valType": "subplotid", + "role": "info", + "dflt": "y", + "editType": "calc+clearAxisTypes", + "description": "Sets a reference between this trace's y coordinates and a 2D cartesian y axis. If *y* (the default value), the y coordinates refer to `layout.yaxis`. If *y2*, the y coordinates refer to `layout.xaxis2`, and so on." + }, + "idssrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for ids .", + "editType": "none" + }, + "customdatasrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for customdata .", + "editType": "none" + }, + "hoverinfosrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for hoverinfo .", + "editType": "none" + }, + "asrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for a .", + "editType": "none" + }, + "bsrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for b .", + "editType": "none" + }, + "textsrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for text .", + "editType": "none" + }, + "textpositionsrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for textposition .", + "editType": "none" + } + } + }, + "contourcarpet": { + "meta": { + "hrName": "contour_carpet", + "description": "Plots contours on either the first carpet axis or the carpet axis with a matching `carpet` attribute. Data `z` is interpreted as matching that of the corresponding carpet axis." + }, + "attributes": { + "type": "contourcarpet", + "visible": { + "valType": "enumerated", + "values": [ + true, + false, + "legendonly" + ], + "role": "info", + "dflt": true, + "editType": "calc", + "description": "Determines whether or not this trace is visible. If *legendonly*, the trace is not drawn, but can appear as a legend item (provided that the legend itself is visible)." + }, + "showlegend": { + "valType": "boolean", + "role": "info", + "dflt": true, + "editType": "style", + "description": "Determines whether or not an item corresponding to this trace is shown in the legend." + }, + "legendgroup": { + "valType": "string", + "role": "info", + "dflt": "", + "editType": "style", + "description": "Sets the legend group for this trace. Traces part of the same legend group hide/show at the same time when toggling legend items." + }, + "opacity": { + "valType": "number", + "role": "style", + "min": 0, + "max": 1, + "dflt": 1, + "editType": "style", + "description": "Sets the opacity of the trace." + }, + "name": { + "valType": "string", + "role": "info", + "editType": "style", + "description": "Sets the trace name. The trace name appear as the legend item and on hover." + }, + "uid": { + "valType": "string", + "role": "info", + "dflt": "", + "editType": "calc" + }, + "ids": { + "valType": "data_array", + "editType": "calc", + "description": "Assigns id labels to each datum. These ids for object constancy of data points during animation.", + "role": "data" + }, + "customdata": { + "valType": "data_array", + "editType": "calc", + "description": "Assigns extra data each datum. This may be useful when listening to hover, click and selection events. Note that, *scatter* traces also appends customdata items in the markers DOM elements", + "role": "data" + }, + "selectedpoints": { + "valType": "any", + "role": "info", + "editType": "calc", + "description": "Array containing integer indices of selected points. Has an effect only for traces that support selections. Note that an empty array means an empty selection where the `unselected` are turned on for all points, whereas, any other non-array values means no selection all where the `selected` and `unselected` styles have no effect." + }, + "hoverinfo": { + "valType": "flaglist", + "role": "info", + "flags": [ + "x", + "y", + "z", + "text", + "name" + ], + "extras": [ + "all", + "none", + "skip" + ], + "arrayOk": true, + "dflt": "all", + "editType": "none", + "description": "Determines which trace information appear on hover. If `none` or `skip` are set, no information is displayed upon hovering. But, if `none` is set, click and hover events are still fired." + }, + "hoverlabel": { + "bgcolor": { + "valType": "color", + "role": "style", + "arrayOk": true, + "editType": "none", + "description": "Sets the background color of the hover labels for this trace" + }, + "bordercolor": { + "valType": "color", + "role": "style", + "arrayOk": true, + "editType": "none", + "description": "Sets the border color of the hover labels for this trace." + }, + "font": { + "family": { + "valType": "string", + "role": "style", + "noBlank": true, + "strict": true, + "editType": "none", + "description": "HTML font family - the typeface that will be applied by the web browser. The web browser will only be able to apply a font if it is available on the system which it operates. Provide multiple font families, separated by commas, to indicate the preference in which to apply fonts if they aren't available on the system. The plotly service (at https://plot.ly or on-premise) generates images on a server, where only a select number of fonts are installed and supported. These include *Arial*, *Balto*, *Courier New*, *Droid Sans*,, *Droid Serif*, *Droid Sans Mono*, *Gravitas One*, *Old Standard TT*, *Open Sans*, *Overpass*, *PT Sans Narrow*, *Raleway*, *Times New Roman*.", + "arrayOk": true + }, + "size": { + "valType": "number", + "role": "style", + "min": 1, + "editType": "none", + "arrayOk": true + }, + "color": { + "valType": "color", + "role": "style", + "editType": "none", + "arrayOk": true + }, + "editType": "none", + "description": "Sets the font used in hover labels.", + "role": "object", + "familysrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for family .", + "editType": "none" + }, + "sizesrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for size .", + "editType": "none" + }, + "colorsrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for color .", + "editType": "none" + } + }, + "namelength": { + "valType": "integer", + "min": -1, + "arrayOk": true, + "role": "style", + "editType": "none", + "description": "Sets the length (in number of characters) of the trace name in the hover labels for this trace. -1 shows the whole name regardless of length. 0-3 shows the first 0-3 characters, and an integer >3 will show the whole name if it is less than that many characters, but if it is longer, will truncate to `namelength - 3` characters and add an ellipsis." + }, + "editType": "calc", + "role": "object", + "bgcolorsrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for bgcolor .", + "editType": "none" + }, + "bordercolorsrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for bordercolor .", + "editType": "none" + }, + "namelengthsrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for namelength .", + "editType": "none" + } + }, + "stream": { + "token": { + "valType": "string", + "noBlank": true, + "strict": true, + "role": "info", + "editType": "calc", + "description": "The stream id number links a data trace on a plot with a stream. See https://plot.ly/settings for more details." + }, + "maxpoints": { + "valType": "number", + "min": 0, + "max": 10000, + "dflt": 500, + "role": "info", + "editType": "calc", + "description": "Sets the maximum number of points to keep on the plots from an incoming stream. If `maxpoints` is set to *50*, only the newest 50 points will be displayed on the plot." + }, + "editType": "calc", + "role": "object" + }, + "carpet": { + "valType": "string", + "role": "info", + "editType": "calc", + "description": "The `carpet` of the carpet axes on which this contour trace lies" + }, + "z": { + "valType": "data_array", + "editType": "calc", + "description": "Sets the z data.", + "role": "data" + }, + "a": { + "valType": "data_array", + "editType": "calc+clearAxisTypes", + "description": "Sets the x coordinates.", + "impliedEdits": { + "xtype": "array" + }, + "role": "data" + }, + "a0": { + "valType": "any", + "dflt": 0, + "role": "info", + "editType": "calc+clearAxisTypes", + "description": "Alternate to `x`. Builds a linear space of x coordinates. Use with `dx` where `x0` is the starting coordinate and `dx` the step.", + "impliedEdits": { + "xtype": "scaled" + } + }, + "da": { + "valType": "number", + "dflt": 1, + "role": "info", + "editType": "calc", + "description": "Sets the x coordinate step. See `x0` for more info.", + "impliedEdits": { + "xtype": "scaled" + } + }, + "b": { + "valType": "data_array", + "editType": "calc+clearAxisTypes", + "description": "Sets the y coordinates.", + "impliedEdits": { + "ytype": "array" + }, + "role": "data" + }, + "b0": { + "valType": "any", + "dflt": 0, + "role": "info", + "editType": "calc+clearAxisTypes", + "description": "Alternate to `y`. Builds a linear space of y coordinates. Use with `dy` where `y0` is the starting coordinate and `dy` the step.", + "impliedEdits": { + "ytype": "scaled" + } + }, + "db": { + "valType": "number", + "dflt": 1, + "role": "info", + "editType": "calc", + "description": "Sets the y coordinate step. See `y0` for more info.", + "impliedEdits": { + "ytype": "scaled" + } + }, + "text": { + "valType": "data_array", + "editType": "calc", + "description": "Sets the text elements associated with each z value.", + "role": "data" + }, + "transpose": { + "valType": "boolean", + "dflt": false, + "role": "info", + "editType": "calc", + "description": "Transposes the z data." + }, + "atype": { + "valType": "enumerated", + "values": [ + "array", + "scaled" + ], + "role": "info", + "editType": "calc+clearAxisTypes", + "description": "If *array*, the heatmap's x coordinates are given by *x* (the default behavior when `x` is provided). If *scaled*, the heatmap's x coordinates are given by *x0* and *dx* (the default behavior when `x` is not provided)." + }, + "btype": { + "valType": "enumerated", + "values": [ + "array", + "scaled" + ], + "role": "info", + "editType": "calc+clearAxisTypes", + "description": "If *array*, the heatmap's y coordinates are given by *y* (the default behavior when `y` is provided) If *scaled*, the heatmap's y coordinates are given by *y0* and *dy* (the default behavior when `y` is not provided)" + }, + "mode": { + "valType": "flaglist", + "flags": [ + "lines", + "fill" + ], + "extras": [ + "none" + ], + "role": "info", + "editType": "calc", + "description": "The mode." + }, + "connectgaps": { + "valType": "boolean", + "dflt": false, + "role": "info", + "editType": "calc", + "description": "Determines whether or not gaps (i.e. {nan} or missing values) in the `z` data are filled in." + }, + "fillcolor": { + "valType": "color", + "role": "style", + "editType": "calc", + "description": "Sets the fill color. Defaults to a half-transparent variant of the line color, marker color, or marker line color, whichever is available." + }, + "autocontour": { + "valType": "boolean", + "dflt": true, + "role": "style", + "editType": "calc", + "impliedEdits": {}, + "description": "Determines whether or not the contour level attributes are picked by an algorithm. If *true*, the number of contour levels can be set in `ncontours`. If *false*, set the contour level attributes in `contours`." + }, + "ncontours": { + "valType": "integer", + "dflt": 15, + "min": 1, + "role": "style", + "editType": "calc", + "description": "Sets the maximum number of contour levels. The actual number of contours will be chosen automatically to be less than or equal to the value of `ncontours`. Has an effect only if `autocontour` is *true* or if `contours.size` is missing." + }, + "contours": { + "type": { + "valType": "enumerated", + "values": [ + "levels", + "constraint" + ], + "dflt": "levels", + "role": "info", + "editType": "calc", + "description": "If `levels`, the data is represented as a contour plot with multiple levels displayed. If `constraint`, the data is represented as constraints with the invalid region shaded as specified by the `operation` and `value` parameters." + }, + "start": { + "valType": "number", + "dflt": null, + "role": "style", + "editType": "plot", + "impliedEdits": { + "^autocontour": false + }, + "description": "Sets the starting contour level value. Must be less than `contours.end`" + }, + "end": { + "valType": "number", + "dflt": null, + "role": "style", + "editType": "plot", + "impliedEdits": { + "^autocontour": false + }, + "description": "Sets the end contour level value. Must be more than `contours.start`" + }, + "size": { + "valType": "number", + "dflt": null, + "min": 0, + "role": "style", + "editType": "plot", + "impliedEdits": { + "^autocontour": false + }, + "description": "Sets the step between each contour level. Must be positive." + }, + "coloring": { + "valType": "enumerated", + "values": [ + "fill", + "lines", + "none" + ], + "dflt": "fill", + "role": "style", + "editType": "calc", + "description": "Determines the coloring method showing the contour values. If *fill*, coloring is done evenly between each contour level If *lines*, coloring is done on the contour lines. If *none*, no coloring is applied on this trace." + }, + "showlines": { + "valType": "boolean", + "dflt": true, + "role": "style", + "editType": "plot", + "description": "Determines whether or not the contour lines are drawn. Has an effect only if `contours.coloring` is set to *fill*." + }, + "showlabels": { + "valType": "boolean", + "dflt": false, + "role": "style", + "editType": "plot", + "description": "Determines whether to label the contour lines with their values." + }, + "labelfont": { + "family": { + "valType": "string", + "role": "style", + "noBlank": true, + "strict": true, + "editType": "plot", + "description": "HTML font family - the typeface that will be applied by the web browser. The web browser will only be able to apply a font if it is available on the system which it operates. Provide multiple font families, separated by commas, to indicate the preference in which to apply fonts if they aren't available on the system. The plotly service (at https://plot.ly or on-premise) generates images on a server, where only a select number of fonts are installed and supported. These include *Arial*, *Balto*, *Courier New*, *Droid Sans*,, *Droid Serif*, *Droid Sans Mono*, *Gravitas One*, *Old Standard TT*, *Open Sans*, *Overpass*, *PT Sans Narrow*, *Raleway*, *Times New Roman*." + }, + "size": { + "valType": "number", + "role": "style", + "min": 1, + "editType": "plot" + }, + "color": { + "valType": "color", + "role": "style", + "editType": "style" + }, + "editType": "plot", + "description": "Sets the font used for labeling the contour levels. The default color comes from the lines, if shown. The default family and size come from `layout.font`.", + "role": "object" + }, + "labelformat": { + "valType": "string", + "dflt": "", + "role": "style", + "editType": "plot", + "description": "Sets the contour label formatting rule using d3 formatting mini-language which is very similar to Python, see: https://github.com/d3/d3-format/blob/master/README.md#locale_format." + }, + "operation": { + "valType": "enumerated", + "values": [ + "=", + "<", + ">=", + ">", + "<=", + "[]", + "()", + "[)", + "(]", + "][", + ")(", + "](", + ")[", + "{}", + "}{" + ], + "role": "info", + "dflt": "=", + "editType": "calc", + "description": "Sets the filter operation. *=* keeps items equal to `value` *<* keeps items less than `value` *<=* keeps items less than or equal to `value` *>* keeps items greater than `value` *>=* keeps items greater than or equal to `value` *[]* keeps items inside `value[0]` to value[1]` including both bounds` *()* keeps items inside `value[0]` to value[1]` excluding both bounds` *[)* keeps items inside `value[0]` to value[1]` including `value[0]` but excluding `value[1] *(]* keeps items inside `value[0]` to value[1]` excluding `value[0]` but including `value[1] *][* keeps items outside `value[0]` to value[1]` and equal to both bounds` *)(* keeps items outside `value[0]` to value[1]` *](* keeps items outside `value[0]` to value[1]` and equal to `value[0]` *)[* keeps items outside `value[0]` to value[1]` and equal to `value[1]`" + }, + "value": { + "valType": "any", + "dflt": 0, + "role": "info", + "editType": "calc", + "description": "Sets the value or values by which to filter by. Values are expected to be in the same type as the data linked to *target*. When `operation` is set to one of the inequality values (=,<,>=,>,<=) *value* is expected to be a number or a string. When `operation` is set to one of the interval value ([],(),[),(],][,)(,](,)[) *value* is expected to be 2-item array where the first item is the lower bound and the second item is the upper bound. When `operation`, is set to one of the set value ({},}{) *value* is expected to be an array with as many items as the desired set elements." + }, + "editType": "calc", + "role": "object" + }, + "line": { + "color": { + "valType": "color", + "role": "style", + "editType": "style", + "description": "Sets the color of the contour level. Has no if `contours.coloring` is set to *lines*." + }, + "width": { + "valType": "number", + "min": 0, + "dflt": 2, + "role": "style", + "editType": "style", + "description": "Sets the line width (in px)." + }, + "dash": { + "valType": "string", + "values": [ + "solid", + "dot", + "dash", + "longdash", + "dashdot", + "longdashdot" + ], + "dflt": "solid", + "role": "style", + "editType": "style", + "description": "Sets the dash style of lines. Set to a dash type string (*solid*, *dot*, *dash*, *longdash*, *dashdot*, or *longdashdot*) or a dash length list in px (eg *5px,10px,2px,2px*)." + }, + "smoothing": { + "valType": "number", + "min": 0, + "max": 1.3, + "dflt": 1, + "role": "style", + "editType": "plot", + "description": "Sets the amount of smoothing for the contour lines, where *0* corresponds to no smoothing." + }, + "editType": "plot", + "role": "object" + }, + "zauto": { + "valType": "boolean", + "role": "info", + "dflt": true, + "editType": "calc", + "impliedEdits": {}, + "description": "Determines the whether or not the color domain is computed with respect to the input data." + }, + "zmin": { + "valType": "number", + "role": "info", + "dflt": null, + "editType": "plot", + "impliedEdits": { + "zauto": false + }, + "description": "Sets the lower bound of color domain." + }, + "zmax": { + "valType": "number", + "role": "info", + "dflt": null, + "editType": "plot", + "impliedEdits": { + "zauto": false + }, + "description": "Sets the upper bound of color domain." + }, + "colorscale": { + "valType": "colorscale", + "role": "style", + "editType": "calc", + "impliedEdits": { + "autocolorscale": false + }, + "description": "Sets the colorscale. The colorscale must be an array containing arrays mapping a normalized value to an rgb, rgba, hex, hsl, hsv, or named color string. At minimum, a mapping for the lowest (0) and highest (1) values are required. For example, `[[0, 'rgb(0,0,255)', [1, 'rgb(255,0,0)']]`. To control the bounds of the colorscale in z space, use zmin and zmax" + }, + "autocolorscale": { + "valType": "boolean", + "role": "style", + "dflt": false, + "editType": "calc", + "impliedEdits": {}, + "description": "Determines whether or not the colorscale is picked using the sign of the input z values." + }, + "reversescale": { + "valType": "boolean", + "role": "style", + "dflt": false, + "editType": "calc", + "description": "Reverses the colorscale." + }, + "showscale": { + "valType": "boolean", + "role": "info", + "dflt": true, + "editType": "calc", + "description": "Determines whether or not a colorbar is displayed for this trace." + }, + "colorbar": { + "thicknessmode": { + "valType": "enumerated", + "values": [ + "fraction", + "pixels" + ], + "role": "style", + "dflt": "pixels", + "description": "Determines whether this color bar's thickness (i.e. the measure in the constant color direction) is set in units of plot *fraction* or in *pixels*. Use `thickness` to set the value.", + "editType": "colorbars" + }, + "thickness": { + "valType": "number", + "role": "style", + "min": 0, + "dflt": 30, + "description": "Sets the thickness of the color bar This measure excludes the size of the padding, ticks and labels.", + "editType": "colorbars" + }, + "lenmode": { + "valType": "enumerated", + "values": [ + "fraction", + "pixels" + ], + "role": "info", + "dflt": "fraction", + "description": "Determines whether this color bar's length (i.e. the measure in the color variation direction) is set in units of plot *fraction* or in *pixels. Use `len` to set the value.", + "editType": "colorbars" + }, + "len": { + "valType": "number", + "min": 0, + "dflt": 1, + "role": "style", + "description": "Sets the length of the color bar This measure excludes the padding of both ends. That is, the color bar length is this length minus the padding on both ends.", + "editType": "colorbars" + }, + "x": { + "valType": "number", + "dflt": 1.02, + "min": -2, + "max": 3, + "role": "style", + "description": "Sets the x position of the color bar (in plot fraction).", + "editType": "colorbars" + }, + "xanchor": { + "valType": "enumerated", + "values": [ + "left", + "center", + "right" + ], + "dflt": "left", + "role": "style", + "description": "Sets this color bar's horizontal position anchor. This anchor binds the `x` position to the *left*, *center* or *right* of the color bar.", + "editType": "colorbars" + }, + "xpad": { + "valType": "number", + "role": "style", + "min": 0, + "dflt": 10, + "description": "Sets the amount of padding (in px) along the x direction.", + "editType": "colorbars" + }, + "y": { + "valType": "number", + "role": "style", + "dflt": 0.5, + "min": -2, + "max": 3, + "description": "Sets the y position of the color bar (in plot fraction).", + "editType": "colorbars" + }, + "yanchor": { + "valType": "enumerated", + "values": [ + "top", + "middle", + "bottom" + ], + "role": "style", + "dflt": "middle", + "description": "Sets this color bar's vertical position anchor This anchor binds the `y` position to the *top*, *middle* or *bottom* of the color bar.", + "editType": "colorbars" + }, + "ypad": { + "valType": "number", + "role": "style", + "min": 0, + "dflt": 10, + "description": "Sets the amount of padding (in px) along the y direction.", + "editType": "colorbars" + }, + "outlinecolor": { + "valType": "color", + "dflt": "#444", + "role": "style", + "editType": "colorbars", + "description": "Sets the axis line color." + }, + "outlinewidth": { + "valType": "number", + "min": 0, + "dflt": 1, + "role": "style", + "editType": "colorbars", + "description": "Sets the width (in px) of the axis line." + }, + "bordercolor": { + "valType": "color", + "dflt": "#444", + "role": "style", + "editType": "colorbars", + "description": "Sets the axis line color." + }, + "borderwidth": { + "valType": "number", + "role": "style", + "min": 0, + "dflt": 0, + "description": "Sets the width (in px) or the border enclosing this color bar.", + "editType": "colorbars" + }, + "bgcolor": { + "valType": "color", + "role": "style", + "dflt": "rgba(0,0,0,0)", + "description": "Sets the color of padded area.", + "editType": "colorbars" + }, + "tickmode": { + "valType": "enumerated", + "values": [ + "auto", + "linear", + "array" + ], + "role": "info", + "editType": "colorbars", + "impliedEdits": {}, + "description": "Sets the tick mode for this axis. If *auto*, the number of ticks is set via `nticks`. If *linear*, the placement of the ticks is determined by a starting position `tick0` and a tick step `dtick` (*linear* is the default value if `tick0` and `dtick` are provided). If *array*, the placement of the ticks is set via `tickvals` and the tick text is `ticktext`. (*array* is the default value if `tickvals` is provided)." + }, + "nticks": { + "valType": "integer", + "min": 0, + "dflt": 0, + "role": "style", + "editType": "colorbars", + "description": "Specifies the maximum number of ticks for the particular axis. The actual number of ticks will be chosen automatically to be less than or equal to `nticks`. Has an effect only if `tickmode` is set to *auto*." + }, + "tick0": { + "valType": "any", + "role": "style", + "editType": "colorbars", + "impliedEdits": { + "tickmode": "linear" + }, + "description": "Sets the placement of the first tick on this axis. Use with `dtick`. If the axis `type` is *log*, then you must take the log of your starting tick (e.g. to set the starting tick to 100, set the `tick0` to 2) except when `dtick`=*L* (see `dtick` for more info). If the axis `type` is *date*, it should be a date string, like date data. If the axis `type` is *category*, it should be a number, using the scale where each category is assigned a serial number from zero in the order it appears." + }, + "dtick": { + "valType": "any", + "role": "style", + "editType": "colorbars", + "impliedEdits": { + "tickmode": "linear" + }, + "description": "Sets the step in-between ticks on this axis. Use with `tick0`. Must be a positive number, or special strings available to *log* and *date* axes. If the axis `type` is *log*, then ticks are set every 10^(n*dtick) where n is the tick number. For example, to set a tick mark at 1, 10, 100, 1000, ... set dtick to 1. To set tick marks at 1, 100, 10000, ... set dtick to 2. To set tick marks at 1, 5, 25, 125, 625, 3125, ... set dtick to log_10(5), or 0.69897000433. *log* has several special values; *L*, where `f` is a positive number, gives ticks linearly spaced in value (but not position). For example `tick0` = 0.1, `dtick` = *L0.5* will put ticks at 0.1, 0.6, 1.1, 1.6 etc. To show powers of 10 plus small digits between, use *D1* (all digits) or *D2* (only 2 and 5). `tick0` is ignored for *D1* and *D2*. If the axis `type` is *date*, then you must convert the time to milliseconds. For example, to set the interval between ticks to one day, set `dtick` to 86400000.0. *date* also has special values *M* gives ticks spaced by a number of months. `n` must be a positive integer. To set ticks on the 15th of every third month, set `tick0` to *2000-01-15* and `dtick` to *M3*. To set ticks every 4 years, set `dtick` to *M48*" + }, + "tickvals": { + "valType": "data_array", + "editType": "colorbars", + "description": "Sets the values at which ticks on this axis appear. Only has an effect if `tickmode` is set to *array*. Used with `ticktext`.", + "role": "data" + }, + "ticktext": { + "valType": "data_array", + "editType": "colorbars", + "description": "Sets the text displayed at the ticks position via `tickvals`. Only has an effect if `tickmode` is set to *array*. Used with `tickvals`.", + "role": "data" + }, + "ticks": { + "valType": "enumerated", + "values": [ + "outside", + "inside", + "" + ], + "role": "style", + "editType": "colorbars", + "description": "Determines whether ticks are drawn or not. If **, this axis' ticks are not drawn. If *outside* (*inside*), this axis' are drawn outside (inside) the axis lines.", + "dflt": "" + }, + "ticklen": { + "valType": "number", + "min": 0, + "dflt": 5, + "role": "style", + "editType": "colorbars", + "description": "Sets the tick length (in px)." + }, + "tickwidth": { + "valType": "number", + "min": 0, + "dflt": 1, + "role": "style", + "editType": "colorbars", + "description": "Sets the tick width (in px)." + }, + "tickcolor": { + "valType": "color", + "dflt": "#444", + "role": "style", + "editType": "colorbars", + "description": "Sets the tick color." + }, + "showticklabels": { + "valType": "boolean", + "dflt": true, + "role": "style", + "editType": "colorbars", + "description": "Determines whether or not the tick labels are drawn." + }, + "tickfont": { + "family": { + "valType": "string", + "role": "style", + "noBlank": true, + "strict": true, + "description": "HTML font family - the typeface that will be applied by the web browser. The web browser will only be able to apply a font if it is available on the system which it operates. Provide multiple font families, separated by commas, to indicate the preference in which to apply fonts if they aren't available on the system. The plotly service (at https://plot.ly or on-premise) generates images on a server, where only a select number of fonts are installed and supported. These include *Arial*, *Balto*, *Courier New*, *Droid Sans*,, *Droid Serif*, *Droid Sans Mono*, *Gravitas One*, *Old Standard TT*, *Open Sans*, *Overpass*, *PT Sans Narrow*, *Raleway*, *Times New Roman*.", + "editType": "colorbars" + }, + "size": { + "valType": "number", + "role": "style", + "min": 1, + "editType": "colorbars" + }, + "color": { + "valType": "color", + "role": "style", + "editType": "colorbars" + }, + "description": "Sets the color bar's tick label font", + "editType": "colorbars", + "role": "object" + }, + "tickangle": { + "valType": "angle", + "dflt": "auto", + "role": "style", + "editType": "colorbars", + "description": "Sets the angle of the tick labels with respect to the horizontal. For example, a `tickangle` of -90 draws the tick labels vertically." + }, + "tickformat": { + "valType": "string", + "dflt": "", + "role": "style", + "editType": "colorbars", + "description": "Sets the tick label formatting rule using d3 formatting mini-languages which are very similar to those in Python. For numbers, see: https://github.com/d3/d3-format/blob/master/README.md#locale_format And for dates see: https://github.com/d3/d3-time-format/blob/master/README.md#locale_format We add one item to d3's date formatter: *%{n}f* for fractional seconds with n digits. For example, *2016-10-13 09:15:23.456* with tickformat *%H~%M~%S.%2f* would display *09~15~23.46*" + }, + "tickformatstops": { + "items": { + "tickformatstop": { + "dtickrange": { + "valType": "info_array", + "role": "info", + "items": [ + { + "valType": "any", + "editType": "colorbars" + }, + { + "valType": "any", + "editType": "colorbars" + } + ], + "editType": "colorbars", + "description": "range [*min*, *max*], where *min*, *max* - dtick values which describe some zoom level, it is possible to omit *min* or *max* value by passing *null*" + }, + "value": { + "valType": "string", + "dflt": "", + "role": "style", + "editType": "colorbars", + "description": "string - dtickformat for described zoom level, the same as *tickformat*" + }, + "editType": "colorbars", + "role": "object" + } + }, + "role": "object" + }, + "tickprefix": { + "valType": "string", + "dflt": "", + "role": "style", + "editType": "colorbars", + "description": "Sets a tick label prefix." + }, + "showtickprefix": { + "valType": "enumerated", + "values": [ + "all", + "first", + "last", + "none" + ], + "dflt": "all", + "role": "style", + "editType": "colorbars", + "description": "If *all*, all tick labels are displayed with a prefix. If *first*, only the first tick is displayed with a prefix. If *last*, only the last tick is displayed with a suffix. If *none*, tick prefixes are hidden." + }, + "ticksuffix": { + "valType": "string", + "dflt": "", + "role": "style", + "editType": "colorbars", + "description": "Sets a tick label suffix." + }, + "showticksuffix": { + "valType": "enumerated", + "values": [ + "all", + "first", + "last", + "none" + ], + "dflt": "all", + "role": "style", + "editType": "colorbars", + "description": "Same as `showtickprefix` but for tick suffixes." + }, + "separatethousands": { + "valType": "boolean", + "dflt": false, + "role": "style", + "editType": "colorbars", + "description": "If \"true\", even 4-digit integers are separated" + }, + "exponentformat": { + "valType": "enumerated", + "values": [ + "none", + "e", + "E", + "power", + "SI", + "B" + ], + "dflt": "B", + "role": "style", + "editType": "colorbars", + "description": "Determines a formatting rule for the tick exponents. For example, consider the number 1,000,000,000. If *none*, it appears as 1,000,000,000. If *e*, 1e+9. If *E*, 1E+9. If *power*, 1x10^9 (with 9 in a super script). If *SI*, 1G. If *B*, 1B." + }, + "showexponent": { + "valType": "enumerated", + "values": [ + "all", + "first", + "last", + "none" + ], + "dflt": "all", + "role": "style", + "editType": "colorbars", + "description": "If *all*, all exponents are shown besides their significands. If *first*, only the exponent of the first tick is shown. If *last*, only the exponent of the last tick is shown. If *none*, no exponents appear." + }, + "title": { + "valType": "string", + "role": "info", + "dflt": "Click to enter colorscale title", + "description": "Sets the title of the color bar.", + "editType": "colorbars" + }, + "titlefont": { + "family": { + "valType": "string", + "role": "style", + "noBlank": true, + "strict": true, + "description": "HTML font family - the typeface that will be applied by the web browser. The web browser will only be able to apply a font if it is available on the system which it operates. Provide multiple font families, separated by commas, to indicate the preference in which to apply fonts if they aren't available on the system. The plotly service (at https://plot.ly or on-premise) generates images on a server, where only a select number of fonts are installed and supported. These include *Arial*, *Balto*, *Courier New*, *Droid Sans*,, *Droid Serif*, *Droid Sans Mono*, *Gravitas One*, *Old Standard TT*, *Open Sans*, *Overpass*, *PT Sans Narrow*, *Raleway*, *Times New Roman*.", + "editType": "colorbars" + }, + "size": { + "valType": "number", + "role": "style", + "min": 1, + "editType": "colorbars" + }, + "color": { + "valType": "color", + "role": "style", + "editType": "colorbars" + }, + "description": "Sets this color bar's title font.", + "editType": "colorbars", + "role": "object" + }, + "titleside": { + "valType": "enumerated", + "values": [ + "right", + "top", + "bottom" + ], + "role": "style", + "dflt": "top", + "description": "Determines the location of the colorbar title with respect to the color bar.", + "editType": "colorbars" + }, + "editType": "colorbars", + "role": "object", + "tickvalssrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for tickvals .", + "editType": "none" + }, + "ticktextsrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for ticktext .", + "editType": "none" + } + }, + "xaxis": { + "valType": "subplotid", + "role": "info", + "dflt": "x", + "editType": "calc+clearAxisTypes", + "description": "Sets a reference between this trace's x coordinates and a 2D cartesian x axis. If *x* (the default value), the x coordinates refer to `layout.xaxis`. If *x2*, the x coordinates refer to `layout.xaxis2`, and so on." + }, + "yaxis": { + "valType": "subplotid", + "role": "info", + "dflt": "y", + "editType": "calc+clearAxisTypes", + "description": "Sets a reference between this trace's y coordinates and a 2D cartesian y axis. If *y* (the default value), the y coordinates refer to `layout.yaxis`. If *y2*, the y coordinates refer to `layout.xaxis2`, and so on." + }, + "idssrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for ids .", + "editType": "none" + }, + "customdatasrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for customdata .", + "editType": "none" + }, + "hoverinfosrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for hoverinfo .", + "editType": "none" + }, + "zsrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for z .", + "editType": "none" + }, + "asrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for a .", + "editType": "none" + }, + "bsrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for b .", + "editType": "none" + }, + "textsrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for text .", + "editType": "none" + } + } + }, + "ohlc": { + "meta": { + "description": "The ohlc (short for Open-High-Low-Close) is a style of financial chart describing open, high, low and close for a given `x` coordinate (most likely time). The tip of the lines represent the `low` and `high` values and the horizontal segments represent the `open` and `close` values. Sample points where the close value is higher (lower) then the open value are called increasing (decreasing). By default, increasing candles are drawn in green whereas decreasing are drawn in red." + }, + "attributes": { + "type": "ohlc", + "visible": { + "valType": "enumerated", + "values": [ + true, + false, + "legendonly" + ], + "role": "info", + "dflt": true, + "editType": "calc", + "description": "Determines whether or not this trace is visible. If *legendonly*, the trace is not drawn, but can appear as a legend item (provided that the legend itself is visible)." + }, + "showlegend": { + "valType": "boolean", + "role": "info", + "dflt": true, + "editType": "style", + "description": "Determines whether or not an item corresponding to this trace is shown in the legend." + }, + "legendgroup": { + "valType": "string", + "role": "info", + "dflt": "", + "editType": "style", + "description": "Sets the legend group for this trace. Traces part of the same legend group hide/show at the same time when toggling legend items." + }, + "opacity": { + "valType": "number", + "role": "style", + "min": 0, + "max": 1, + "dflt": 1, + "editType": "style", + "description": "Sets the opacity of the trace." + }, + "name": { + "valType": "string", + "role": "info", + "editType": "style", + "description": "Sets the trace name. The trace name appear as the legend item and on hover." + }, + "uid": { + "valType": "string", + "role": "info", + "dflt": "", + "editType": "calc" + }, + "ids": { + "valType": "data_array", + "editType": "calc", + "description": "Assigns id labels to each datum. These ids for object constancy of data points during animation.", + "role": "data" + }, + "customdata": { + "valType": "data_array", + "editType": "calc", + "description": "Assigns extra data each datum. This may be useful when listening to hover, click and selection events. Note that, *scatter* traces also appends customdata items in the markers DOM elements", + "role": "data" + }, + "selectedpoints": { + "valType": "any", + "role": "info", + "editType": "calc", + "description": "Array containing integer indices of selected points. Has an effect only for traces that support selections. Note that an empty array means an empty selection where the `unselected` are turned on for all points, whereas, any other non-array values means no selection all where the `selected` and `unselected` styles have no effect." + }, + "hoverinfo": { + "valType": "flaglist", + "role": "info", + "flags": [ + "x", + "y", + "z", + "text", + "name" + ], + "extras": [ + "all", + "none", + "skip" + ], + "arrayOk": true, + "dflt": "all", + "editType": "none", + "description": "Determines which trace information appear on hover. If `none` or `skip` are set, no information is displayed upon hovering. But, if `none` is set, click and hover events are still fired." + }, + "hoverlabel": { + "bgcolor": { + "valType": "color", + "role": "style", + "arrayOk": true, + "editType": "none", + "description": "Sets the background color of the hover labels for this trace" + }, + "bordercolor": { + "valType": "color", + "role": "style", + "arrayOk": true, + "editType": "none", + "description": "Sets the border color of the hover labels for this trace." + }, + "font": { + "family": { + "valType": "string", + "role": "style", + "noBlank": true, + "strict": true, + "editType": "none", + "description": "HTML font family - the typeface that will be applied by the web browser. The web browser will only be able to apply a font if it is available on the system which it operates. Provide multiple font families, separated by commas, to indicate the preference in which to apply fonts if they aren't available on the system. The plotly service (at https://plot.ly or on-premise) generates images on a server, where only a select number of fonts are installed and supported. These include *Arial*, *Balto*, *Courier New*, *Droid Sans*,, *Droid Serif*, *Droid Sans Mono*, *Gravitas One*, *Old Standard TT*, *Open Sans*, *Overpass*, *PT Sans Narrow*, *Raleway*, *Times New Roman*.", + "arrayOk": true + }, + "size": { + "valType": "number", + "role": "style", + "min": 1, + "editType": "none", + "arrayOk": true + }, + "color": { + "valType": "color", + "role": "style", + "editType": "none", + "arrayOk": true + }, + "editType": "none", + "description": "Sets the font used in hover labels.", + "role": "object", + "familysrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for family .", + "editType": "none" + }, + "sizesrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for size .", + "editType": "none" + }, + "colorsrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for color .", + "editType": "none" + } + }, + "namelength": { + "valType": "integer", + "min": -1, + "arrayOk": true, + "role": "style", + "editType": "none", + "description": "Sets the length (in number of characters) of the trace name in the hover labels for this trace. -1 shows the whole name regardless of length. 0-3 shows the first 0-3 characters, and an integer >3 will show the whole name if it is less than that many characters, but if it is longer, will truncate to `namelength - 3` characters and add an ellipsis." + }, + "editType": "calc", + "role": "object", + "bgcolorsrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for bgcolor .", + "editType": "none" + }, + "bordercolorsrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for bordercolor .", + "editType": "none" + }, + "namelengthsrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for namelength .", + "editType": "none" + } + }, + "stream": { + "token": { + "valType": "string", + "noBlank": true, + "strict": true, + "role": "info", + "editType": "calc", + "description": "The stream id number links a data trace on a plot with a stream. See https://plot.ly/settings for more details." + }, + "maxpoints": { + "valType": "number", + "min": 0, + "max": 10000, + "dflt": 500, + "role": "info", + "editType": "calc", + "description": "Sets the maximum number of points to keep on the plots from an incoming stream. If `maxpoints` is set to *50*, only the newest 50 points will be displayed on the plot." + }, + "editType": "calc", + "role": "object" + }, + "x": { + "valType": "data_array", + "editType": "calc+clearAxisTypes", + "description": "Sets the x coordinates. If absent, linear coordinate will be generated.", + "role": "data" + }, + "open": { + "valType": "data_array", + "dflt": [], + "editType": "calc", + "description": "Sets the open values.", + "role": "data" + }, + "high": { + "valType": "data_array", + "dflt": [], + "editType": "calc", + "description": "Sets the high values.", + "role": "data" + }, + "low": { + "valType": "data_array", + "dflt": [], + "editType": "calc", + "description": "Sets the low values.", + "role": "data" + }, + "close": { + "valType": "data_array", + "dflt": [], + "editType": "calc", + "description": "Sets the close values.", + "role": "data" + }, + "line": { + "width": { + "valType": "number", + "min": 0, + "dflt": 2, + "role": "style", + "editType": "style", + "description": "[object Object] Note that this style setting can also be set per direction via `increasing.line.width` and `decreasing.line.width`." + }, + "dash": { + "valType": "string", + "values": [ + "solid", + "dot", + "dash", + "longdash", + "dashdot", + "longdashdot" + ], + "dflt": "solid", + "role": "style", + "editType": "style", + "description": "Sets the dash style of lines. Set to a dash type string (*solid*, *dot*, *dash*, *longdash*, *dashdot*, or *longdashdot*) or a dash length list in px (eg *5px,10px,2px,2px*). Note that this style setting can also be set per direction via `increasing.line.dash` and `decreasing.line.dash`." + }, + "editType": "style", + "role": "object" + }, + "increasing": { + "name": { + "valType": "string", + "role": "info", + "editType": "style", + "description": "Sets the segment name. The segment name appear as the legend item and on hover." + }, + "showlegend": { + "valType": "boolean", + "role": "info", + "dflt": true, + "editType": "style", + "description": "Determines whether or not an item corresponding to this segment is shown in the legend." + }, + "line": { + "color": { + "valType": "color", + "role": "style", + "editType": "style", + "description": "Sets the line color.", + "dflt": "#3D9970" + }, + "width": { + "valType": "number", + "min": 0, + "dflt": 2, + "role": "style", + "editType": "style", + "description": "Sets the line width (in px)." + }, + "dash": { + "valType": "string", + "values": [ + "solid", + "dot", + "dash", + "longdash", + "dashdot", + "longdashdot" + ], + "dflt": "solid", + "role": "style", + "editType": "style", + "description": "Sets the dash style of lines. Set to a dash type string (*solid*, *dot*, *dash*, *longdash*, *dashdot*, or *longdashdot*) or a dash length list in px (eg *5px,10px,2px,2px*)." + }, + "editType": "style", + "role": "object" + }, + "editType": "style", + "role": "object" + }, + "decreasing": { + "name": { + "valType": "string", + "role": "info", + "editType": "style", + "description": "Sets the segment name. The segment name appear as the legend item and on hover." + }, + "showlegend": { + "valType": "boolean", + "role": "info", + "dflt": true, + "editType": "style", + "description": "Determines whether or not an item corresponding to this segment is shown in the legend." + }, + "line": { + "color": { + "valType": "color", + "role": "style", + "editType": "style", + "description": "Sets the line color.", + "dflt": "#FF4136" + }, + "width": { + "valType": "number", + "min": 0, + "dflt": 2, + "role": "style", + "editType": "style", + "description": "Sets the line width (in px)." + }, + "dash": { + "valType": "string", + "values": [ + "solid", + "dot", + "dash", + "longdash", + "dashdot", + "longdashdot" + ], + "dflt": "solid", + "role": "style", + "editType": "style", + "description": "Sets the dash style of lines. Set to a dash type string (*solid*, *dot*, *dash*, *longdash*, *dashdot*, or *longdashdot*) or a dash length list in px (eg *5px,10px,2px,2px*)." + }, + "editType": "style", + "role": "object" + }, + "editType": "style", + "role": "object" + }, + "text": { + "valType": "string", + "role": "info", + "dflt": "", + "arrayOk": true, + "editType": "calc", + "description": "Sets hover text elements associated with each sample point. If a single string, the same string appears over all the data points. If an array of string, the items are mapped in order to this trace's sample points." + }, + "tickwidth": { + "valType": "number", + "min": 0, + "max": 0.5, + "dflt": 0.3, + "role": "style", + "editType": "calcIfAutorange", + "description": "Sets the width of the open/close tick marks relative to the *x* minimal interval." + }, + "xcalendar": { + "valType": "enumerated", + "values": [ + "gregorian", + "chinese", + "coptic", + "discworld", + "ethiopian", + "hebrew", + "islamic", + "julian", + "mayan", + "nanakshahi", + "nepali", + "persian", + "jalali", + "taiwan", + "thai", + "ummalqura" + ], + "role": "info", + "editType": "calc", + "dflt": "gregorian", + "description": "Sets the calendar system to use with `x` date data." + }, + "xaxis": { + "valType": "subplotid", + "role": "info", + "dflt": "x", + "editType": "calc+clearAxisTypes", + "description": "Sets a reference between this trace's x coordinates and a 2D cartesian x axis. If *x* (the default value), the x coordinates refer to `layout.xaxis`. If *x2*, the x coordinates refer to `layout.xaxis2`, and so on." + }, + "yaxis": { + "valType": "subplotid", + "role": "info", + "dflt": "y", + "editType": "calc+clearAxisTypes", + "description": "Sets a reference between this trace's y coordinates and a 2D cartesian y axis. If *y* (the default value), the y coordinates refer to `layout.yaxis`. If *y2*, the y coordinates refer to `layout.xaxis2`, and so on." + }, + "idssrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for ids .", + "editType": "none" + }, + "customdatasrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for customdata .", + "editType": "none" + }, + "hoverinfosrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for hoverinfo .", + "editType": "none" + }, + "xsrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for x .", + "editType": "none" + }, + "opensrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for open .", + "editType": "none" + }, + "highsrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for high .", + "editType": "none" + }, + "lowsrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for low .", + "editType": "none" + }, + "closesrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for close .", + "editType": "none" + }, + "textsrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for text .", + "editType": "none" + } + } + }, + "candlestick": { + "meta": { + "description": "The candlestick is a style of financial chart describing open, high, low and close for a given `x` coordinate (most likely time). The boxes represent the spread between the `open` and `close` values and the lines represent the spread between the `low` and `high` values Sample points where the close value is higher (lower) then the open value are called increasing (decreasing). By default, increasing candles are drawn in green whereas decreasing are drawn in red." + }, + "attributes": { + "type": "candlestick", + "visible": { + "valType": "enumerated", + "values": [ + true, + false, + "legendonly" + ], + "role": "info", + "dflt": true, + "editType": "calc", + "description": "Determines whether or not this trace is visible. If *legendonly*, the trace is not drawn, but can appear as a legend item (provided that the legend itself is visible)." + }, + "showlegend": { + "valType": "boolean", + "role": "info", + "dflt": true, + "editType": "style", + "description": "Determines whether or not an item corresponding to this trace is shown in the legend." + }, + "legendgroup": { + "valType": "string", + "role": "info", + "dflt": "", + "editType": "style", + "description": "Sets the legend group for this trace. Traces part of the same legend group hide/show at the same time when toggling legend items." + }, + "opacity": { + "valType": "number", + "role": "style", + "min": 0, + "max": 1, + "dflt": 1, + "editType": "style", + "description": "Sets the opacity of the trace." + }, + "name": { + "valType": "string", + "role": "info", + "editType": "style", + "description": "Sets the trace name. The trace name appear as the legend item and on hover." + }, + "uid": { + "valType": "string", + "role": "info", + "dflt": "", + "editType": "calc" + }, + "ids": { + "valType": "data_array", + "editType": "calc", + "description": "Assigns id labels to each datum. These ids for object constancy of data points during animation.", + "role": "data" + }, + "customdata": { + "valType": "data_array", + "editType": "calc", + "description": "Assigns extra data each datum. This may be useful when listening to hover, click and selection events. Note that, *scatter* traces also appends customdata items in the markers DOM elements", + "role": "data" + }, + "selectedpoints": { + "valType": "any", + "role": "info", + "editType": "calc", + "description": "Array containing integer indices of selected points. Has an effect only for traces that support selections. Note that an empty array means an empty selection where the `unselected` are turned on for all points, whereas, any other non-array values means no selection all where the `selected` and `unselected` styles have no effect." + }, + "hoverinfo": { + "valType": "flaglist", + "role": "info", + "flags": [ + "x", + "y", + "z", + "text", + "name" + ], + "extras": [ + "all", + "none", + "skip" + ], + "arrayOk": true, + "dflt": "all", + "editType": "none", + "description": "Determines which trace information appear on hover. If `none` or `skip` are set, no information is displayed upon hovering. But, if `none` is set, click and hover events are still fired." + }, + "hoverlabel": { + "bgcolor": { + "valType": "color", + "role": "style", + "arrayOk": true, + "editType": "none", + "description": "Sets the background color of the hover labels for this trace" + }, + "bordercolor": { + "valType": "color", + "role": "style", + "arrayOk": true, + "editType": "none", + "description": "Sets the border color of the hover labels for this trace." + }, + "font": { + "family": { + "valType": "string", + "role": "style", + "noBlank": true, + "strict": true, + "editType": "none", + "description": "HTML font family - the typeface that will be applied by the web browser. The web browser will only be able to apply a font if it is available on the system which it operates. Provide multiple font families, separated by commas, to indicate the preference in which to apply fonts if they aren't available on the system. The plotly service (at https://plot.ly or on-premise) generates images on a server, where only a select number of fonts are installed and supported. These include *Arial*, *Balto*, *Courier New*, *Droid Sans*,, *Droid Serif*, *Droid Sans Mono*, *Gravitas One*, *Old Standard TT*, *Open Sans*, *Overpass*, *PT Sans Narrow*, *Raleway*, *Times New Roman*.", + "arrayOk": true + }, + "size": { + "valType": "number", + "role": "style", + "min": 1, + "editType": "none", + "arrayOk": true + }, + "color": { + "valType": "color", + "role": "style", + "editType": "none", + "arrayOk": true + }, + "editType": "none", + "description": "Sets the font used in hover labels.", + "role": "object", + "familysrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for family .", + "editType": "none" + }, + "sizesrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for size .", + "editType": "none" + }, + "colorsrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for color .", + "editType": "none" + } + }, + "namelength": { + "valType": "integer", + "min": -1, + "arrayOk": true, + "role": "style", + "editType": "none", + "description": "Sets the length (in number of characters) of the trace name in the hover labels for this trace. -1 shows the whole name regardless of length. 0-3 shows the first 0-3 characters, and an integer >3 will show the whole name if it is less than that many characters, but if it is longer, will truncate to `namelength - 3` characters and add an ellipsis." + }, + "editType": "calc", + "role": "object", + "bgcolorsrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for bgcolor .", + "editType": "none" + }, + "bordercolorsrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for bordercolor .", + "editType": "none" + }, + "namelengthsrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for namelength .", + "editType": "none" + } + }, + "stream": { + "token": { + "valType": "string", + "noBlank": true, + "strict": true, + "role": "info", + "editType": "calc", + "description": "The stream id number links a data trace on a plot with a stream. See https://plot.ly/settings for more details." + }, + "maxpoints": { + "valType": "number", + "min": 0, + "max": 10000, + "dflt": 500, + "role": "info", + "editType": "calc", + "description": "Sets the maximum number of points to keep on the plots from an incoming stream. If `maxpoints` is set to *50*, only the newest 50 points will be displayed on the plot." + }, + "editType": "calc", + "role": "object" + }, + "x": { + "valType": "data_array", + "editType": "calc+clearAxisTypes", + "description": "Sets the x coordinates. If absent, linear coordinate will be generated.", + "role": "data" + }, + "open": { + "valType": "data_array", + "dflt": [], + "editType": "calc", + "description": "Sets the open values.", + "role": "data" + }, + "high": { + "valType": "data_array", + "dflt": [], + "editType": "calc", + "description": "Sets the high values.", + "role": "data" + }, + "low": { + "valType": "data_array", + "dflt": [], + "editType": "calc", + "description": "Sets the low values.", + "role": "data" + }, + "close": { + "valType": "data_array", + "dflt": [], + "editType": "calc", + "description": "Sets the close values.", + "role": "data" + }, + "line": { + "width": { + "valType": "number", + "role": "style", + "min": 0, + "dflt": 2, + "editType": "style", + "description": "Sets the width (in px) of line bounding the box(es). Note that this style setting can also be set per direction via `increasing.line.width` and `decreasing.line.width`." + }, + "editType": "style", + "role": "object" + }, + "increasing": { + "name": { + "valType": "string", + "role": "info", + "editType": "style", + "description": "Sets the segment name. The segment name appear as the legend item and on hover." + }, + "showlegend": { + "valType": "boolean", + "role": "info", + "dflt": true, + "editType": "style", + "description": "Determines whether or not an item corresponding to this segment is shown in the legend." + }, + "line": { + "color": { + "valType": "color", + "role": "style", + "editType": "style", + "description": "Sets the color of line bounding the box(es).", + "dflt": "#3D9970" + }, + "width": { + "valType": "number", + "role": "style", + "min": 0, + "dflt": 2, + "editType": "style", + "description": "Sets the width (in px) of line bounding the box(es)." + }, + "editType": "style", + "role": "object" + }, + "fillcolor": { + "valType": "color", + "role": "style", + "editType": "style", + "description": "Sets the fill color. Defaults to a half-transparent variant of the line color, marker color, or marker line color, whichever is available." + }, + "editType": "style", + "role": "object" + }, + "decreasing": { + "name": { + "valType": "string", + "role": "info", + "editType": "style", + "description": "Sets the segment name. The segment name appear as the legend item and on hover." + }, + "showlegend": { + "valType": "boolean", + "role": "info", + "dflt": true, + "editType": "style", + "description": "Determines whether or not an item corresponding to this segment is shown in the legend." + }, + "line": { + "color": { + "valType": "color", + "role": "style", + "editType": "style", + "description": "Sets the color of line bounding the box(es).", + "dflt": "#FF4136" + }, + "width": { + "valType": "number", + "role": "style", + "min": 0, + "dflt": 2, + "editType": "style", + "description": "Sets the width (in px) of line bounding the box(es)." + }, + "editType": "style", + "role": "object" + }, + "fillcolor": { + "valType": "color", + "role": "style", + "editType": "style", + "description": "Sets the fill color. Defaults to a half-transparent variant of the line color, marker color, or marker line color, whichever is available." + }, + "editType": "style", + "role": "object" + }, + "text": { + "valType": "string", + "role": "info", + "dflt": "", + "arrayOk": true, + "editType": "calc", + "description": "Sets hover text elements associated with each sample point. If a single string, the same string appears over all the data points. If an array of string, the items are mapped in order to this trace's sample points." + }, + "whiskerwidth": { + "valType": "number", + "min": 0, + "max": 1, + "dflt": 0, + "role": "style", + "editType": "calcIfAutorange", + "description": "Sets the width of the whiskers relative to the box' width. For example, with 1, the whiskers are as wide as the box(es)." + }, + "xcalendar": { + "valType": "enumerated", + "values": [ + "gregorian", + "chinese", + "coptic", + "discworld", + "ethiopian", + "hebrew", + "islamic", + "julian", + "mayan", + "nanakshahi", + "nepali", + "persian", + "jalali", + "taiwan", + "thai", + "ummalqura" + ], + "role": "info", + "editType": "calc", + "dflt": "gregorian", + "description": "Sets the calendar system to use with `x` date data." + }, + "xaxis": { + "valType": "subplotid", + "role": "info", + "dflt": "x", + "editType": "calc+clearAxisTypes", + "description": "Sets a reference between this trace's x coordinates and a 2D cartesian x axis. If *x* (the default value), the x coordinates refer to `layout.xaxis`. If *x2*, the x coordinates refer to `layout.xaxis2`, and so on." + }, + "yaxis": { + "valType": "subplotid", + "role": "info", + "dflt": "y", + "editType": "calc+clearAxisTypes", + "description": "Sets a reference between this trace's y coordinates and a 2D cartesian y axis. If *y* (the default value), the y coordinates refer to `layout.yaxis`. If *y2*, the y coordinates refer to `layout.xaxis2`, and so on." + }, + "idssrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for ids .", + "editType": "none" + }, + "customdatasrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for customdata .", + "editType": "none" + }, + "hoverinfosrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for hoverinfo .", + "editType": "none" + }, + "xsrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for x .", + "editType": "none" + }, + "opensrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for open .", + "editType": "none" + }, + "highsrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for high .", + "editType": "none" + }, + "lowsrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for low .", + "editType": "none" + }, + "closesrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for close .", + "editType": "none" + }, + "textsrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for text .", + "editType": "none" + } + } + }, + "area": { + "meta": {}, + "attributes": { + "type": "area", + "visible": { + "valType": "enumerated", + "values": [ + true, + false, + "legendonly" + ], + "role": "info", + "dflt": true, + "editType": "calc", + "description": "Determines whether or not this trace is visible. If *legendonly*, the trace is not drawn, but can appear as a legend item (provided that the legend itself is visible)." + }, + "showlegend": { + "valType": "boolean", + "role": "info", + "dflt": true, + "editType": "style", + "description": "Determines whether or not an item corresponding to this trace is shown in the legend." + }, + "legendgroup": { + "valType": "string", + "role": "info", + "dflt": "", + "editType": "style", + "description": "Sets the legend group for this trace. Traces part of the same legend group hide/show at the same time when toggling legend items." + }, + "opacity": { + "valType": "number", + "role": "style", + "min": 0, + "max": 1, + "dflt": 1, + "editType": "style", + "description": "Sets the opacity of the trace." + }, + "name": { + "valType": "string", + "role": "info", + "editType": "style", + "description": "Sets the trace name. The trace name appear as the legend item and on hover." + }, + "uid": { + "valType": "string", + "role": "info", + "dflt": "", + "editType": "calc" + }, + "ids": { + "valType": "data_array", + "editType": "calc", + "description": "Assigns id labels to each datum. These ids for object constancy of data points during animation.", + "role": "data" + }, + "customdata": { + "valType": "data_array", + "editType": "calc", + "description": "Assigns extra data each datum. This may be useful when listening to hover, click and selection events. Note that, *scatter* traces also appends customdata items in the markers DOM elements", + "role": "data" + }, + "selectedpoints": { + "valType": "any", + "role": "info", + "editType": "calc", + "description": "Array containing integer indices of selected points. Has an effect only for traces that support selections. Note that an empty array means an empty selection where the `unselected` are turned on for all points, whereas, any other non-array values means no selection all where the `selected` and `unselected` styles have no effect." + }, + "hoverinfo": { + "valType": "flaglist", + "role": "info", + "flags": [ + "x", + "y", + "z", + "text", + "name" + ], + "extras": [ + "all", + "none", + "skip" + ], + "arrayOk": true, + "dflt": "all", + "editType": "none", + "description": "Determines which trace information appear on hover. If `none` or `skip` are set, no information is displayed upon hovering. But, if `none` is set, click and hover events are still fired." + }, + "hoverlabel": { + "bgcolor": { + "valType": "color", + "role": "style", + "arrayOk": true, + "editType": "none", + "description": "Sets the background color of the hover labels for this trace" + }, + "bordercolor": { + "valType": "color", + "role": "style", + "arrayOk": true, + "editType": "none", + "description": "Sets the border color of the hover labels for this trace." + }, + "font": { + "family": { + "valType": "string", + "role": "style", + "noBlank": true, + "strict": true, + "editType": "none", + "description": "HTML font family - the typeface that will be applied by the web browser. The web browser will only be able to apply a font if it is available on the system which it operates. Provide multiple font families, separated by commas, to indicate the preference in which to apply fonts if they aren't available on the system. The plotly service (at https://plot.ly or on-premise) generates images on a server, where only a select number of fonts are installed and supported. These include *Arial*, *Balto*, *Courier New*, *Droid Sans*,, *Droid Serif*, *Droid Sans Mono*, *Gravitas One*, *Old Standard TT*, *Open Sans*, *Overpass*, *PT Sans Narrow*, *Raleway*, *Times New Roman*.", + "arrayOk": true + }, + "size": { + "valType": "number", + "role": "style", + "min": 1, + "editType": "none", + "arrayOk": true + }, + "color": { + "valType": "color", + "role": "style", + "editType": "none", + "arrayOk": true + }, + "editType": "none", + "description": "Sets the font used in hover labels.", + "role": "object", + "familysrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for family .", + "editType": "none" + }, + "sizesrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for size .", + "editType": "none" + }, + "colorsrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for color .", + "editType": "none" + } + }, + "namelength": { + "valType": "integer", + "min": -1, + "arrayOk": true, + "role": "style", + "editType": "none", + "description": "Sets the length (in number of characters) of the trace name in the hover labels for this trace. -1 shows the whole name regardless of length. 0-3 shows the first 0-3 characters, and an integer >3 will show the whole name if it is less than that many characters, but if it is longer, will truncate to `namelength - 3` characters and add an ellipsis." + }, + "editType": "calc", + "role": "object", + "bgcolorsrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for bgcolor .", + "editType": "none" + }, + "bordercolorsrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for bordercolor .", + "editType": "none" + }, + "namelengthsrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for namelength .", + "editType": "none" + } + }, + "stream": { + "token": { + "valType": "string", + "noBlank": true, + "strict": true, + "role": "info", + "editType": "calc", + "description": "The stream id number links a data trace on a plot with a stream. See https://plot.ly/settings for more details." + }, + "maxpoints": { + "valType": "number", + "min": 0, + "max": 10000, + "dflt": 500, + "role": "info", + "editType": "calc", + "description": "Sets the maximum number of points to keep on the plots from an incoming stream. If `maxpoints` is set to *50*, only the newest 50 points will be displayed on the plot." + }, + "editType": "calc", + "role": "object" + }, + "r": { + "valType": "data_array", + "editType": "calc", + "description": "For polar chart only.Sets the radial coordinates.", + "role": "data" + }, + "t": { + "valType": "data_array", + "editType": "calc", + "description": "For polar chart only.Sets the angular coordinates.", + "role": "data" + }, + "marker": { + "color": { + "valType": "color", + "arrayOk": true, + "role": "style", + "editType": "style", + "description": "Sets the marker color. It accepts either a specific color or an array of numbers that are mapped to the colorscale relative to the max and min values of the array or relative to `cmin` and `cmax` if set." + }, + "size": { + "valType": "number", + "min": 0, + "dflt": 6, + "arrayOk": true, + "role": "style", + "editType": "calcIfAutorange", + "description": "Sets the marker size (in px)." + }, + "symbol": { + "valType": "enumerated", + "values": [ + 0, + "circle", + 100, + "circle-open", + 200, + "circle-dot", + 300, + "circle-open-dot", + 1, + "square", + 101, + "square-open", + 201, + "square-dot", + 301, + "square-open-dot", + 2, + "diamond", + 102, + "diamond-open", + 202, + "diamond-dot", + 302, + "diamond-open-dot", + 3, + "cross", + 103, + "cross-open", + 203, + "cross-dot", + 303, + "cross-open-dot", + 4, + "x", + 104, + "x-open", + 204, + "x-dot", + 304, + "x-open-dot", + 5, + "triangle-up", + 105, + "triangle-up-open", + 205, + "triangle-up-dot", + 305, + "triangle-up-open-dot", + 6, + "triangle-down", + 106, + "triangle-down-open", + 206, + "triangle-down-dot", + 306, + "triangle-down-open-dot", + 7, + "triangle-left", + 107, + "triangle-left-open", + 207, + "triangle-left-dot", + 307, + "triangle-left-open-dot", + 8, + "triangle-right", + 108, + "triangle-right-open", + 208, + "triangle-right-dot", + 308, + "triangle-right-open-dot", + 9, + "triangle-ne", + 109, + "triangle-ne-open", + 209, + "triangle-ne-dot", + 309, + "triangle-ne-open-dot", + 10, + "triangle-se", + 110, + "triangle-se-open", + 210, + "triangle-se-dot", + 310, + "triangle-se-open-dot", + 11, + "triangle-sw", + 111, + "triangle-sw-open", + 211, + "triangle-sw-dot", + 311, + "triangle-sw-open-dot", + 12, + "triangle-nw", + 112, + "triangle-nw-open", + 212, + "triangle-nw-dot", + 312, + "triangle-nw-open-dot", + 13, + "pentagon", + 113, + "pentagon-open", + 213, + "pentagon-dot", + 313, + "pentagon-open-dot", + 14, + "hexagon", + 114, + "hexagon-open", + 214, + "hexagon-dot", + 314, + "hexagon-open-dot", + 15, + "hexagon2", + 115, + "hexagon2-open", + 215, + "hexagon2-dot", + 315, + "hexagon2-open-dot", + 16, + "octagon", + 116, + "octagon-open", + 216, + "octagon-dot", + 316, + "octagon-open-dot", + 17, + "star", + 117, + "star-open", + 217, + "star-dot", + 317, + "star-open-dot", + 18, + "hexagram", + 118, + "hexagram-open", + 218, + "hexagram-dot", + 318, + "hexagram-open-dot", + 19, + "star-triangle-up", + 119, + "star-triangle-up-open", + 219, + "star-triangle-up-dot", + 319, + "star-triangle-up-open-dot", + 20, + "star-triangle-down", + 120, + "star-triangle-down-open", + 220, + "star-triangle-down-dot", + 320, + "star-triangle-down-open-dot", + 21, + "star-square", + 121, + "star-square-open", + 221, + "star-square-dot", + 321, + "star-square-open-dot", + 22, + "star-diamond", + 122, + "star-diamond-open", + 222, + "star-diamond-dot", + 322, + "star-diamond-open-dot", + 23, + "diamond-tall", + 123, + "diamond-tall-open", + 223, + "diamond-tall-dot", + 323, + "diamond-tall-open-dot", + 24, + "diamond-wide", + 124, + "diamond-wide-open", + 224, + "diamond-wide-dot", + 324, + "diamond-wide-open-dot", + 25, + "hourglass", + 125, + "hourglass-open", + 26, + "bowtie", + 126, + "bowtie-open", + 27, + "circle-cross", + 127, + "circle-cross-open", + 28, + "circle-x", + 128, + "circle-x-open", + 29, + "square-cross", + 129, + "square-cross-open", + 30, + "square-x", + 130, + "square-x-open", + 31, + "diamond-cross", + 131, + "diamond-cross-open", + 32, + "diamond-x", + 132, + "diamond-x-open", + 33, + "cross-thin", + 133, + "cross-thin-open", + 34, + "x-thin", + 134, + "x-thin-open", + 35, + "asterisk", + 135, + "asterisk-open", + 36, + "hash", + 136, + "hash-open", + 236, + "hash-dot", + 336, + "hash-open-dot", + 37, + "y-up", + 137, + "y-up-open", + 38, + "y-down", + 138, + "y-down-open", + 39, + "y-left", + 139, + "y-left-open", + 40, + "y-right", + 140, + "y-right-open", + 41, + "line-ew", + 141, + "line-ew-open", + 42, + "line-ns", + 142, + "line-ns-open", + 43, + "line-ne", + 143, + "line-ne-open", + 44, + "line-nw", + 144, + "line-nw-open" + ], + "dflt": "circle", + "arrayOk": true, + "role": "style", + "editType": "style", + "description": "Sets the marker symbol type. Adding 100 is equivalent to appending *-open* to a symbol name. Adding 200 is equivalent to appending *-dot* to a symbol name. Adding 300 is equivalent to appending *-open-dot* or *dot-open* to a symbol name." + }, + "opacity": { + "valType": "number", + "min": 0, + "max": 1, + "arrayOk": true, + "role": "style", + "editType": "style", + "description": "Sets the marker opacity." + }, + "editType": "calc", + "role": "object", + "colorsrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for color .", + "editType": "none" + }, + "sizesrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for size .", + "editType": "none" + }, + "symbolsrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for symbol .", + "editType": "none" + }, + "opacitysrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for opacity .", + "editType": "none" + } + }, + "idssrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for ids .", + "editType": "none" + }, + "customdatasrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for customdata .", + "editType": "none" + }, + "hoverinfosrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for hoverinfo .", + "editType": "none" + }, + "rsrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for r .", + "editType": "none" + }, + "tsrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for t .", + "editType": "none" + } + } + } + }, + "layout": { + "layoutAttributes": { + "font": { + "family": { + "valType": "string", + "role": "style", + "noBlank": true, + "strict": true, + "editType": "calc", + "description": "HTML font family - the typeface that will be applied by the web browser. The web browser will only be able to apply a font if it is available on the system which it operates. Provide multiple font families, separated by commas, to indicate the preference in which to apply fonts if they aren't available on the system. The plotly service (at https://plot.ly or on-premise) generates images on a server, where only a select number of fonts are installed and supported. These include *Arial*, *Balto*, *Courier New*, *Droid Sans*,, *Droid Serif*, *Droid Sans Mono*, *Gravitas One*, *Old Standard TT*, *Open Sans*, *Overpass*, *PT Sans Narrow*, *Raleway*, *Times New Roman*.", + "dflt": "\"Open Sans\", verdana, arial, sans-serif" + }, + "size": { + "valType": "number", + "role": "style", + "min": 1, + "editType": "calc", + "dflt": 12 + }, + "color": { + "valType": "color", + "role": "style", + "editType": "calc", + "dflt": "#444" + }, + "editType": "calc", + "description": "Sets the global font. Note that fonts used in traces and other layout components inherit from the global font.", + "role": "object" + }, + "title": { + "valType": "string", + "role": "info", + "dflt": "Click to enter Plot title", + "editType": "layoutstyle", + "description": "Sets the plot's title." + }, + "titlefont": { + "family": { + "valType": "string", + "role": "style", + "noBlank": true, + "strict": true, + "editType": "layoutstyle", + "description": "HTML font family - the typeface that will be applied by the web browser. The web browser will only be able to apply a font if it is available on the system which it operates. Provide multiple font families, separated by commas, to indicate the preference in which to apply fonts if they aren't available on the system. The plotly service (at https://plot.ly or on-premise) generates images on a server, where only a select number of fonts are installed and supported. These include *Arial*, *Balto*, *Courier New*, *Droid Sans*,, *Droid Serif*, *Droid Sans Mono*, *Gravitas One*, *Old Standard TT*, *Open Sans*, *Overpass*, *PT Sans Narrow*, *Raleway*, *Times New Roman*." + }, + "size": { + "valType": "number", + "role": "style", + "min": 1, + "editType": "layoutstyle" + }, + "color": { + "valType": "color", + "role": "style", + "editType": "layoutstyle" + }, + "editType": "layoutstyle", + "description": "Sets the title font.", + "role": "object" + }, + "autosize": { + "valType": "boolean", + "role": "info", + "dflt": false, + "editType": "none", + "description": "Determines whether or not a layout width or height that has been left undefined by the user is initialized on each relayout. Note that, regardless of this attribute, an undefined layout width or height is always initialized on the first call to plot." + }, + "width": { + "valType": "number", + "role": "info", + "min": 10, + "dflt": 700, + "editType": "none", + "description": "Sets the plot's width (in px)." + }, + "height": { + "valType": "number", + "role": "info", + "min": 10, + "dflt": 450, + "editType": "none", + "description": "Sets the plot's height (in px)." + }, + "margin": { + "l": { + "valType": "number", + "role": "info", + "min": 0, + "dflt": 80, + "editType": "calc", + "description": "Sets the left margin (in px)." + }, + "r": { + "valType": "number", + "role": "info", + "min": 0, + "dflt": 80, + "editType": "calc", + "description": "Sets the right margin (in px)." + }, + "t": { + "valType": "number", + "role": "info", + "min": 0, + "dflt": 100, + "editType": "calc", + "description": "Sets the top margin (in px)." + }, + "b": { + "valType": "number", + "role": "info", + "min": 0, + "dflt": 80, + "editType": "calc", + "description": "Sets the bottom margin (in px)." + }, + "pad": { + "valType": "number", + "role": "info", + "min": 0, + "dflt": 0, + "editType": "calc", + "description": "Sets the amount of padding (in px) between the plotting area and the axis lines" + }, + "autoexpand": { + "valType": "boolean", + "role": "info", + "dflt": true, + "editType": "calc" + }, + "editType": "calc", + "role": "object" + }, + "paper_bgcolor": { + "valType": "color", + "role": "style", + "dflt": "#fff", + "editType": "plot", + "description": "Sets the color of paper where the graph is drawn." + }, + "plot_bgcolor": { + "valType": "color", + "role": "style", + "dflt": "#fff", + "editType": "layoutstyle", + "description": "Sets the color of plotting area in-between x and y axes." + }, + "separators": { + "valType": "string", + "role": "style", + "dflt": ".,", + "editType": "plot", + "description": "Sets the decimal and thousand separators. For example, *. * puts a '.' before decimals and a space between thousands." + }, + "hidesources": { + "valType": "boolean", + "role": "info", + "dflt": false, + "editType": "plot", + "description": "Determines whether or not a text link citing the data source is placed at the bottom-right cored of the figure. Has only an effect only on graphs that have been generated via forked graphs from the plotly service (at https://plot.ly or on-premise)." + }, + "showlegend": { + "valType": "boolean", + "role": "info", + "editType": "legend", + "description": "Determines whether or not a legend is drawn." + }, + "colorway": { + "valType": "colorlist", + "dflt": [ + "#1f77b4", + "#ff7f0e", + "#2ca02c", + "#d62728", + "#9467bd", + "#8c564b", + "#e377c2", + "#7f7f7f", + "#bcbd22", + "#17becf" + ], + "role": "style", + "editType": "calc", + "description": "Sets the default trace colors." + }, + "dragmode": { + "valType": "enumerated", + "role": "info", + "values": [ + "zoom", + "pan", + "select", + "lasso", + "orbit", + "turntable" + ], + "dflt": "zoom", + "editType": "modebar", + "description": "Determines the mode of drag interactions. *select* and *lasso* apply only to scatter traces with markers or text. *orbit* and *turntable* apply only to 3D scenes." + }, + "hovermode": { + "valType": "enumerated", + "role": "info", + "values": [ + "x", + "y", + "closest", + false + ], + "editType": "modebar", + "description": "Determines the mode of hover interactions." + }, + "hoverlabel": { + "bgcolor": { + "valType": "color", + "role": "style", + "editType": "none", + "description": "Sets the background color of all hover labels on graph" + }, + "bordercolor": { + "valType": "color", + "role": "style", + "editType": "none", + "description": "Sets the border color of all hover labels on graph." + }, + "font": { + "family": { + "valType": "string", + "role": "style", + "noBlank": true, + "strict": true, + "editType": "none", + "description": "HTML font family - the typeface that will be applied by the web browser. The web browser will only be able to apply a font if it is available on the system which it operates. Provide multiple font families, separated by commas, to indicate the preference in which to apply fonts if they aren't available on the system. The plotly service (at https://plot.ly or on-premise) generates images on a server, where only a select number of fonts are installed and supported. These include *Arial*, *Balto*, *Courier New*, *Droid Sans*,, *Droid Serif*, *Droid Sans Mono*, *Gravitas One*, *Old Standard TT*, *Open Sans*, *Overpass*, *PT Sans Narrow*, *Raleway*, *Times New Roman*.", + "dflt": "Arial, sans-serif" + }, + "size": { + "valType": "number", + "role": "style", + "min": 1, + "editType": "none", + "dflt": 13 + }, + "color": { + "valType": "color", + "role": "style", + "editType": "none" + }, + "editType": "none", + "description": "Sets the default hover label font used by all traces on the graph.", + "role": "object" + }, + "namelength": { + "valType": "integer", + "min": -1, + "dflt": 15, + "role": "style", + "editType": "none", + "description": "Sets the default length (in number of characters) of the trace name in the hover labels for all traces. -1 shows the whole name regardless of length. 0-3 shows the first 0-3 characters, and an integer >3 will show the whole name if it is less than that many characters, but if it is longer, will truncate to `namelength - 3` characters and add an ellipsis." + }, + "editType": "none", + "role": "object" + }, + "calendar": { + "valType": "enumerated", + "values": [ + "gregorian", + "chinese", + "coptic", + "discworld", + "ethiopian", + "hebrew", + "islamic", + "julian", + "mayan", + "nanakshahi", + "nepali", + "persian", + "jalali", + "taiwan", + "thai", + "ummalqura" + ], + "role": "info", + "editType": "calc", + "dflt": "gregorian", + "description": "Sets the default calendar system to use for interpreting and displaying dates throughout the plot." + }, + "xaxis": { + "visible": { + "valType": "boolean", + "role": "info", + "editType": "plot", + "description": "A single toggle to hide the axis while preserving interaction like dragging. Default is true when a cheater plot is present on the axis, otherwise false" + }, + "color": { + "valType": "color", + "dflt": "#444", + "role": "style", + "editType": "ticks", + "description": "Sets default for all colors associated with this axis all at once: line, font, tick, and grid colors. Grid color is lightened by blending this with the plot background Individual pieces can override this." + }, + "title": { + "valType": "string", + "role": "info", + "editType": "ticks", + "description": "Sets the title of this axis." + }, + "titlefont": { + "family": { + "valType": "string", + "role": "style", + "noBlank": true, + "strict": true, + "editType": "ticks", + "description": "HTML font family - the typeface that will be applied by the web browser. The web browser will only be able to apply a font if it is available on the system which it operates. Provide multiple font families, separated by commas, to indicate the preference in which to apply fonts if they aren't available on the system. The plotly service (at https://plot.ly or on-premise) generates images on a server, where only a select number of fonts are installed and supported. These include *Arial*, *Balto*, *Courier New*, *Droid Sans*,, *Droid Serif*, *Droid Sans Mono*, *Gravitas One*, *Old Standard TT*, *Open Sans*, *Overpass*, *PT Sans Narrow*, *Raleway*, *Times New Roman*." + }, + "size": { + "valType": "number", + "role": "style", + "min": 1, + "editType": "ticks" + }, + "color": { + "valType": "color", + "role": "style", + "editType": "ticks" + }, + "editType": "ticks", + "description": "Sets this axis' title font.", + "role": "object" + }, + "type": { + "valType": "enumerated", + "values": [ + "-", + "linear", + "log", + "date", + "category" + ], + "dflt": "-", + "role": "info", + "editType": "calc", + "description": "Sets the axis type. By default, plotly attempts to determined the axis type by looking into the data of the traces that referenced the axis in question." + }, + "autorange": { + "valType": "enumerated", + "values": [ + true, + false, + "reversed" + ], + "dflt": true, + "role": "style", + "editType": "calc", + "impliedEdits": {}, + "description": "Determines whether or not the range of this axis is computed in relation to the input data. See `rangemode` for more info. If `range` is provided, then `autorange` is set to *false*." + }, + "rangemode": { + "valType": "enumerated", + "values": [ + "normal", + "tozero", + "nonnegative" + ], + "dflt": "normal", + "role": "style", + "editType": "calc", + "description": "If *normal*, the range is computed in relation to the extrema of the input data. If *tozero*`, the range extends to 0, regardless of the input data If *nonnegative*, the range is non-negative, regardless of the input data." + }, + "range": { + "valType": "info_array", + "role": "info", + "items": [ + { + "valType": "any", + "editType": "plot", + "impliedEdits": { + "^autorange": false + } + }, + { + "valType": "any", + "editType": "plot", + "impliedEdits": { + "^autorange": false + } + } + ], + "editType": "plot", + "impliedEdits": { + "autorange": false + }, + "description": "Sets the range of this axis. If the axis `type` is *log*, then you must take the log of your desired range (e.g. to set the range from 1 to 100, set the range from 0 to 2). If the axis `type` is *date*, it should be date strings, like date data, though Date objects and unix milliseconds will be accepted and converted to strings. If the axis `type` is *category*, it should be numbers, using the scale where each category is assigned a serial number from zero in the order it appears." + }, + "fixedrange": { + "valType": "boolean", + "dflt": false, + "role": "info", + "editType": "calc", + "description": "Determines whether or not this axis is zoom-able. If true, then zoom is disabled." + }, + "scaleanchor": { + "valType": "enumerated", + "values": [ + "/^x([2-9]|[1-9][0-9]+)?$/", + "/^y([2-9]|[1-9][0-9]+)?$/" + ], + "role": "info", + "editType": "calc", + "description": "If set to another axis id (e.g. `x2`, `y`), the range of this axis changes together with the range of the corresponding axis such that the scale of pixels per unit is in a constant ratio. Both axes are still zoomable, but when you zoom one, the other will zoom the same amount, keeping a fixed midpoint. `constrain` and `constraintoward` determine how we enforce the constraint. You can chain these, ie `yaxis: {scaleanchor: *x*}, xaxis2: {scaleanchor: *y*}` but you can only link axes of the same `type`. The linked axis can have the opposite letter (to constrain the aspect ratio) or the same letter (to match scales across subplots). Loops (`yaxis: {scaleanchor: *x*}, xaxis: {scaleanchor: *y*}` or longer) are redundant and the last constraint encountered will be ignored to avoid possible inconsistent constraints via `scaleratio`." + }, + "scaleratio": { + "valType": "number", + "min": 0, + "dflt": 1, + "role": "info", + "editType": "calc", + "description": "If this axis is linked to another by `scaleanchor`, this determines the pixel to unit scale ratio. For example, if this value is 10, then every unit on this axis spans 10 times the number of pixels as a unit on the linked axis. Use this for example to create an elevation profile where the vertical scale is exaggerated a fixed amount with respect to the horizontal." + }, + "constrain": { + "valType": "enumerated", + "values": [ + "range", + "domain" + ], + "dflt": "range", + "role": "info", + "editType": "calc", + "description": "If this axis needs to be compressed (either due to its own `scaleanchor` and `scaleratio` or those of the other axis), determines how that happens: by increasing the *range* (default), or by decreasing the *domain*." + }, + "constraintoward": { + "valType": "enumerated", + "values": [ + "left", + "center", + "right", + "top", + "middle", + "bottom" + ], + "role": "info", + "editType": "calc", + "description": "If this axis needs to be compressed (either due to its own `scaleanchor` and `scaleratio` or those of the other axis), determines which direction we push the originally specified plot area. Options are *left*, *center* (default), and *right* for x axes, and *top*, *middle* (default), and *bottom* for y axes." + }, + "tickmode": { + "valType": "enumerated", + "values": [ + "auto", + "linear", + "array" + ], + "role": "info", + "editType": "ticks", + "impliedEdits": {}, + "description": "Sets the tick mode for this axis. If *auto*, the number of ticks is set via `nticks`. If *linear*, the placement of the ticks is determined by a starting position `tick0` and a tick step `dtick` (*linear* is the default value if `tick0` and `dtick` are provided). If *array*, the placement of the ticks is set via `tickvals` and the tick text is `ticktext`. (*array* is the default value if `tickvals` is provided)." + }, + "nticks": { + "valType": "integer", + "min": 0, + "dflt": 0, + "role": "style", + "editType": "ticks", + "description": "Specifies the maximum number of ticks for the particular axis. The actual number of ticks will be chosen automatically to be less than or equal to `nticks`. Has an effect only if `tickmode` is set to *auto*." + }, + "tick0": { + "valType": "any", + "role": "style", + "editType": "ticks", + "impliedEdits": { + "tickmode": "linear" + }, + "description": "Sets the placement of the first tick on this axis. Use with `dtick`. If the axis `type` is *log*, then you must take the log of your starting tick (e.g. to set the starting tick to 100, set the `tick0` to 2) except when `dtick`=*L* (see `dtick` for more info). If the axis `type` is *date*, it should be a date string, like date data. If the axis `type` is *category*, it should be a number, using the scale where each category is assigned a serial number from zero in the order it appears." + }, + "dtick": { + "valType": "any", + "role": "style", + "editType": "ticks", + "impliedEdits": { + "tickmode": "linear" + }, + "description": "Sets the step in-between ticks on this axis. Use with `tick0`. Must be a positive number, or special strings available to *log* and *date* axes. If the axis `type` is *log*, then ticks are set every 10^(n*dtick) where n is the tick number. For example, to set a tick mark at 1, 10, 100, 1000, ... set dtick to 1. To set tick marks at 1, 100, 10000, ... set dtick to 2. To set tick marks at 1, 5, 25, 125, 625, 3125, ... set dtick to log_10(5), or 0.69897000433. *log* has several special values; *L*, where `f` is a positive number, gives ticks linearly spaced in value (but not position). For example `tick0` = 0.1, `dtick` = *L0.5* will put ticks at 0.1, 0.6, 1.1, 1.6 etc. To show powers of 10 plus small digits between, use *D1* (all digits) or *D2* (only 2 and 5). `tick0` is ignored for *D1* and *D2*. If the axis `type` is *date*, then you must convert the time to milliseconds. For example, to set the interval between ticks to one day, set `dtick` to 86400000.0. *date* also has special values *M* gives ticks spaced by a number of months. `n` must be a positive integer. To set ticks on the 15th of every third month, set `tick0` to *2000-01-15* and `dtick` to *M3*. To set ticks every 4 years, set `dtick` to *M48*" + }, + "tickvals": { + "valType": "data_array", + "editType": "ticks", + "description": "Sets the values at which ticks on this axis appear. Only has an effect if `tickmode` is set to *array*. Used with `ticktext`.", + "role": "data" + }, + "ticktext": { + "valType": "data_array", + "editType": "ticks", + "description": "Sets the text displayed at the ticks position via `tickvals`. Only has an effect if `tickmode` is set to *array*. Used with `tickvals`.", + "role": "data" + }, + "ticks": { + "valType": "enumerated", + "values": [ + "outside", + "inside", + "" + ], + "role": "style", + "editType": "ticks", + "description": "Determines whether ticks are drawn or not. If **, this axis' ticks are not drawn. If *outside* (*inside*), this axis' are drawn outside (inside) the axis lines." + }, + "mirror": { + "valType": "enumerated", + "values": [ + true, + "ticks", + false, + "all", + "allticks" + ], + "dflt": false, + "role": "style", + "editType": "ticks+layoutstyle", + "description": "Determines if the axis lines or/and ticks are mirrored to the opposite side of the plotting area. If *true*, the axis lines are mirrored. If *ticks*, the axis lines and ticks are mirrored. If *false*, mirroring is disable. If *all*, axis lines are mirrored on all shared-axes subplots. If *allticks*, axis lines and ticks are mirrored on all shared-axes subplots." + }, + "ticklen": { + "valType": "number", + "min": 0, + "dflt": 5, + "role": "style", + "editType": "ticks", + "description": "Sets the tick length (in px)." + }, + "tickwidth": { + "valType": "number", + "min": 0, + "dflt": 1, + "role": "style", + "editType": "ticks", + "description": "Sets the tick width (in px)." + }, + "tickcolor": { + "valType": "color", + "dflt": "#444", + "role": "style", + "editType": "ticks", + "description": "Sets the tick color." + }, + "showticklabels": { + "valType": "boolean", + "dflt": true, + "role": "style", + "editType": "ticks", + "description": "Determines whether or not the tick labels are drawn." + }, + "showspikes": { + "valType": "boolean", + "dflt": false, + "role": "style", + "editType": "modebar", + "description": "Determines whether or not spikes (aka droplines) are drawn for this axis. Note: This only takes affect when hovermode = closest" + }, + "spikecolor": { + "valType": "color", + "dflt": null, + "role": "style", + "editType": "none", + "description": "Sets the spike color. If undefined, will use the series color" + }, + "spikethickness": { + "valType": "number", + "dflt": 3, + "role": "style", + "editType": "none", + "description": "Sets the width (in px) of the zero line." + }, + "spikedash": { + "valType": "string", + "values": [ + "solid", + "dot", + "dash", + "longdash", + "dashdot", + "longdashdot" + ], + "dflt": "dash", + "role": "style", + "editType": "none", + "description": "Sets the dash style of lines. Set to a dash type string (*solid*, *dot*, *dash*, *longdash*, *dashdot*, or *longdashdot*) or a dash length list in px (eg *5px,10px,2px,2px*)." + }, + "spikemode": { + "valType": "flaglist", + "flags": [ + "toaxis", + "across", + "marker" + ], + "role": "style", + "dflt": "toaxis", + "editType": "none", + "description": "Determines the drawing mode for the spike line If *toaxis*, the line is drawn from the data point to the axis the series is plotted on. If *across*, the line is drawn across the entire plot area, and supercedes *toaxis*. If *marker*, then a marker dot is drawn on the axis the series is plotted on" + }, + "tickfont": { + "family": { + "valType": "string", + "role": "style", + "noBlank": true, + "strict": true, + "editType": "ticks", + "description": "HTML font family - the typeface that will be applied by the web browser. The web browser will only be able to apply a font if it is available on the system which it operates. Provide multiple font families, separated by commas, to indicate the preference in which to apply fonts if they aren't available on the system. The plotly service (at https://plot.ly or on-premise) generates images on a server, where only a select number of fonts are installed and supported. These include *Arial*, *Balto*, *Courier New*, *Droid Sans*,, *Droid Serif*, *Droid Sans Mono*, *Gravitas One*, *Old Standard TT*, *Open Sans*, *Overpass*, *PT Sans Narrow*, *Raleway*, *Times New Roman*." + }, + "size": { + "valType": "number", + "role": "style", + "min": 1, + "editType": "ticks" + }, + "color": { + "valType": "color", + "role": "style", + "editType": "ticks" + }, + "editType": "ticks", + "description": "Sets the tick font.", + "role": "object" + }, + "tickangle": { + "valType": "angle", + "dflt": "auto", + "role": "style", + "editType": "ticks", + "description": "Sets the angle of the tick labels with respect to the horizontal. For example, a `tickangle` of -90 draws the tick labels vertically." + }, + "tickprefix": { + "valType": "string", + "dflt": "", + "role": "style", + "editType": "ticks", + "description": "Sets a tick label prefix." + }, + "showtickprefix": { + "valType": "enumerated", + "values": [ + "all", + "first", + "last", + "none" + ], + "dflt": "all", + "role": "style", + "editType": "ticks", + "description": "If *all*, all tick labels are displayed with a prefix. If *first*, only the first tick is displayed with a prefix. If *last*, only the last tick is displayed with a suffix. If *none*, tick prefixes are hidden." + }, + "ticksuffix": { + "valType": "string", + "dflt": "", + "role": "style", + "editType": "ticks", + "description": "Sets a tick label suffix." + }, + "showticksuffix": { + "valType": "enumerated", + "values": [ + "all", + "first", + "last", + "none" + ], + "dflt": "all", + "role": "style", + "editType": "ticks", + "description": "Same as `showtickprefix` but for tick suffixes." + }, + "showexponent": { + "valType": "enumerated", + "values": [ + "all", + "first", + "last", + "none" + ], + "dflt": "all", + "role": "style", + "editType": "ticks", + "description": "If *all*, all exponents are shown besides their significands. If *first*, only the exponent of the first tick is shown. If *last*, only the exponent of the last tick is shown. If *none*, no exponents appear." + }, + "exponentformat": { + "valType": "enumerated", + "values": [ + "none", + "e", + "E", + "power", + "SI", + "B" + ], + "dflt": "B", + "role": "style", + "editType": "ticks", + "description": "Determines a formatting rule for the tick exponents. For example, consider the number 1,000,000,000. If *none*, it appears as 1,000,000,000. If *e*, 1e+9. If *E*, 1E+9. If *power*, 1x10^9 (with 9 in a super script). If *SI*, 1G. If *B*, 1B." + }, + "separatethousands": { + "valType": "boolean", + "dflt": false, + "role": "style", + "editType": "ticks", + "description": "If \"true\", even 4-digit integers are separated" + }, + "tickformat": { + "valType": "string", + "dflt": "", + "role": "style", + "editType": "ticks", + "description": "Sets the tick label formatting rule using d3 formatting mini-languages which are very similar to those in Python. For numbers, see: https://github.com/d3/d3-format/blob/master/README.md#locale_format And for dates see: https://github.com/d3/d3-time-format/blob/master/README.md#locale_format We add one item to d3's date formatter: *%{n}f* for fractional seconds with n digits. For example, *2016-10-13 09:15:23.456* with tickformat *%H~%M~%S.%2f* would display *09~15~23.46*" + }, + "tickformatstops": { + "items": { + "tickformatstop": { + "dtickrange": { + "valType": "info_array", + "role": "info", + "items": [ + { + "valType": "any", + "editType": "ticks" + }, + { + "valType": "any", + "editType": "ticks" + } + ], + "editType": "ticks", + "description": "range [*min*, *max*], where *min*, *max* - dtick values which describe some zoom level, it is possible to omit *min* or *max* value by passing *null*" + }, + "value": { + "valType": "string", + "dflt": "", + "role": "style", + "editType": "ticks", + "description": "string - dtickformat for described zoom level, the same as *tickformat*" + }, + "editType": "ticks", + "role": "object" + } + }, + "role": "object" + }, + "hoverformat": { + "valType": "string", + "dflt": "", + "role": "style", + "editType": "none", + "description": "Sets the hover text formatting rule using d3 formatting mini-languages which are very similar to those in Python. For numbers, see: https://github.com/d3/d3-format/blob/master/README.md#locale_format And for dates see: https://github.com/d3/d3-time-format/blob/master/README.md#locale_format We add one item to d3's date formatter: *%{n}f* for fractional seconds with n digits. For example, *2016-10-13 09:15:23.456* with tickformat *%H~%M~%S.%2f* would display *09~15~23.46*" + }, + "showline": { + "valType": "boolean", + "dflt": false, + "role": "style", + "editType": "layoutstyle", + "description": "Determines whether or not a line bounding this axis is drawn." + }, + "linecolor": { + "valType": "color", + "dflt": "#444", + "role": "style", + "editType": "layoutstyle", + "description": "Sets the axis line color." + }, + "linewidth": { + "valType": "number", + "min": 0, + "dflt": 1, + "role": "style", + "editType": "ticks+layoutstyle", + "description": "Sets the width (in px) of the axis line." + }, + "showgrid": { + "valType": "boolean", + "role": "style", + "editType": "ticks", + "description": "Determines whether or not grid lines are drawn. If *true*, the grid lines are drawn at every tick mark." + }, + "gridcolor": { + "valType": "color", + "dflt": "#eee", + "role": "style", + "editType": "ticks", + "description": "Sets the color of the grid lines." + }, + "gridwidth": { + "valType": "number", + "min": 0, + "dflt": 1, + "role": "style", + "editType": "ticks", + "description": "Sets the width (in px) of the grid lines." + }, + "zeroline": { + "valType": "boolean", + "role": "style", + "editType": "ticks", + "description": "Determines whether or not a line is drawn at along the 0 value of this axis. If *true*, the zero line is drawn on top of the grid lines." + }, + "zerolinecolor": { + "valType": "color", + "dflt": "#444", + "role": "style", + "editType": "ticks", + "description": "Sets the line color of the zero line." + }, + "zerolinewidth": { + "valType": "number", + "dflt": 1, + "role": "style", + "editType": "ticks", + "description": "Sets the width (in px) of the zero line." + }, + "anchor": { + "valType": "enumerated", + "values": [ + "free", + "/^x([2-9]|[1-9][0-9]+)?$/", + "/^y([2-9]|[1-9][0-9]+)?$/" + ], + "role": "info", + "editType": "plot", + "description": "If set to an opposite-letter axis id (e.g. `x2`, `y`), this axis is bound to the corresponding opposite-letter axis. If set to *free*, this axis' position is determined by `position`." + }, + "side": { + "valType": "enumerated", + "values": [ + "top", + "bottom", + "left", + "right" + ], + "role": "info", + "editType": "plot", + "description": "Determines whether a x (y) axis is positioned at the *bottom* (*left*) or *top* (*right*) of the plotting area." + }, + "overlaying": { + "valType": "enumerated", + "values": [ + "free", + "/^x([2-9]|[1-9][0-9]+)?$/", + "/^y([2-9]|[1-9][0-9]+)?$/" + ], + "role": "info", + "editType": "calc", + "description": "If set a same-letter axis id, this axis is overlaid on top of the corresponding same-letter axis. If *false*, this axis does not overlay any same-letter axes." + }, + "layer": { + "valType": "enumerated", + "values": [ + "above traces", + "below traces" + ], + "dflt": "above traces", + "role": "info", + "editType": "plot", + "description": "Sets the layer on which this axis is displayed. If *above traces*, this axis is displayed above all the subplot's traces If *below traces*, this axis is displayed below all the subplot's traces, but above the grid lines. Useful when used together with scatter-like traces with `cliponaxis` set to *false* to show markers and/or text nodes above this axis." + }, + "domain": { + "valType": "info_array", + "role": "info", + "items": [ + { + "valType": "number", + "min": 0, + "max": 1, + "editType": "calc" + }, + { + "valType": "number", + "min": 0, + "max": 1, + "editType": "calc" + } + ], + "dflt": [ + 0, + 1 + ], + "editType": "calc", + "description": "Sets the domain of this axis (in plot fraction)." + }, + "position": { + "valType": "number", + "min": 0, + "max": 1, + "dflt": 0, + "role": "style", + "editType": "plot", + "description": "Sets the position of this axis in the plotting space (in normalized coordinates). Only has an effect if `anchor` is set to *free*." + }, + "categoryorder": { + "valType": "enumerated", + "values": [ + "trace", + "category ascending", + "category descending", + "array" + ], + "dflt": "trace", + "role": "info", + "editType": "calc", + "description": "Specifies the ordering logic for the case of categorical variables. By default, plotly uses *trace*, which specifies the order that is present in the data supplied. Set `categoryorder` to *category ascending* or *category descending* if order should be determined by the alphanumerical order of the category names. Set `categoryorder` to *array* to derive the ordering from the attribute `categoryarray`. If a category is not found in the `categoryarray` array, the sorting behavior for that attribute will be identical to the *trace* mode. The unspecified categories will follow the categories in `categoryarray`." + }, + "categoryarray": { + "valType": "data_array", + "role": "data", + "editType": "calc", + "description": "Sets the order in which categories on this axis appear. Only has an effect if `categoryorder` is set to *array*. Used with `categoryorder`." + }, + "editType": "calc", + "_deprecated": { + "autotick": { + "valType": "boolean", + "role": "info", + "editType": "ticks", + "description": "Obsolete. Set `tickmode` to *auto* for old `autotick` *true* behavior. Set `tickmode` to *linear* for `autotick` *false*." + } + }, + "rangeslider": { + "bgcolor": { + "valType": "color", + "dflt": "#fff", + "role": "style", + "editType": "calc", + "description": "Sets the background color of the range slider." + }, + "bordercolor": { + "valType": "color", + "dflt": "#444", + "role": "style", + "editType": "calc", + "description": "Sets the border color of the range slider." + }, + "borderwidth": { + "valType": "integer", + "dflt": 0, + "min": 0, + "role": "style", + "editType": "calc", + "description": "Sets the border color of the range slider." + }, + "autorange": { + "valType": "boolean", + "dflt": true, + "role": "style", + "editType": "calc", + "description": "Determines whether or not the range slider range is computed in relation to the input data. If `range` is provided, then `autorange` is set to *false*." + }, + "range": { + "valType": "info_array", + "role": "info", + "items": [ + { + "valType": "any", + "editType": "calc" + }, + { + "valType": "any", + "editType": "calc" + } + ], + "editType": "calc", + "description": "Sets the range of the range slider. If not set, defaults to the full xaxis range. If the axis `type` is *log*, then you must take the log of your desired range. If the axis `type` is *date*, it should be date strings, like date data, though Date objects and unix milliseconds will be accepted and converted to strings. If the axis `type` is *category*, it should be numbers, using the scale where each category is assigned a serial number from zero in the order it appears." + }, + "thickness": { + "valType": "number", + "dflt": 0.15, + "min": 0, + "max": 1, + "role": "style", + "editType": "calc", + "description": "The height of the range slider as a fraction of the total plot area height." + }, + "visible": { + "valType": "boolean", + "dflt": true, + "role": "info", + "editType": "calc", + "description": "Determines whether or not the range slider will be visible. If visible, perpendicular axes will be set to `fixedrange`" + }, + "editType": "calc", + "role": "object" + }, + "rangeselector": { + "visible": { + "valType": "boolean", + "role": "info", + "editType": "plot", + "description": "Determines whether or not this range selector is visible. Note that range selectors are only available for x axes of `type` set to or auto-typed to *date*." + }, + "buttons": { + "items": { + "button": { + "step": { + "valType": "enumerated", + "role": "info", + "values": [ + "month", + "year", + "day", + "hour", + "minute", + "second", + "all" + ], + "dflt": "month", + "editType": "plot", + "description": "The unit of measurement that the `count` value will set the range by." + }, + "stepmode": { + "valType": "enumerated", + "role": "info", + "values": [ + "backward", + "todate" + ], + "dflt": "backward", + "editType": "plot", + "description": "Sets the range update mode. If *backward*, the range update shifts the start of range back *count* times *step* milliseconds. If *todate*, the range update shifts the start of range back to the first timestamp from *count* times *step* milliseconds back. For example, with `step` set to *year* and `count` set to *1* the range update shifts the start of the range back to January 01 of the current year. Month and year *todate* are currently available only for the built-in (Gregorian) calendar." + }, + "count": { + "valType": "number", + "role": "info", + "min": 0, + "dflt": 1, + "editType": "plot", + "description": "Sets the number of steps to take to update the range. Use with `step` to specify the update interval." + }, + "label": { + "valType": "string", + "role": "info", + "editType": "plot", + "description": "Sets the text label to appear on the button." + }, + "editType": "plot", + "description": "Sets the specifications for each buttons. By default, a range selector comes with no buttons.", + "role": "object" + } + }, + "role": "object" + }, + "x": { + "valType": "number", + "min": -2, + "max": 3, + "role": "style", + "editType": "plot", + "description": "Sets the x position (in normalized coordinates) of the range selector." + }, + "xanchor": { + "valType": "enumerated", + "values": [ + "auto", + "left", + "center", + "right" + ], + "dflt": "left", + "role": "info", + "editType": "plot", + "description": "Sets the range selector's horizontal position anchor. This anchor binds the `x` position to the *left*, *center* or *right* of the range selector." + }, + "y": { + "valType": "number", + "min": -2, + "max": 3, + "role": "style", + "editType": "plot", + "description": "Sets the y position (in normalized coordinates) of the range selector." + }, + "yanchor": { + "valType": "enumerated", + "values": [ + "auto", + "top", + "middle", + "bottom" + ], + "dflt": "bottom", + "role": "info", + "editType": "plot", + "description": "Sets the range selector's vertical position anchor This anchor binds the `y` position to the *top*, *middle* or *bottom* of the range selector." + }, + "font": { + "family": { + "valType": "string", + "role": "style", + "noBlank": true, + "strict": true, + "editType": "plot", + "description": "HTML font family - the typeface that will be applied by the web browser. The web browser will only be able to apply a font if it is available on the system which it operates. Provide multiple font families, separated by commas, to indicate the preference in which to apply fonts if they aren't available on the system. The plotly service (at https://plot.ly or on-premise) generates images on a server, where only a select number of fonts are installed and supported. These include *Arial*, *Balto*, *Courier New*, *Droid Sans*,, *Droid Serif*, *Droid Sans Mono*, *Gravitas One*, *Old Standard TT*, *Open Sans*, *Overpass*, *PT Sans Narrow*, *Raleway*, *Times New Roman*." + }, + "size": { + "valType": "number", + "role": "style", + "min": 1, + "editType": "plot" + }, + "color": { + "valType": "color", + "role": "style", + "editType": "plot" + }, + "editType": "plot", + "description": "Sets the font of the range selector button text.", + "role": "object" + }, + "bgcolor": { + "valType": "color", + "dflt": "#eee", + "role": "style", + "editType": "plot", + "description": "Sets the background color of the range selector buttons." + }, + "activecolor": { + "valType": "color", + "role": "style", + "editType": "plot", + "description": "Sets the background color of the active range selector button." + }, + "bordercolor": { + "valType": "color", + "dflt": "#444", + "role": "style", + "editType": "plot", + "description": "Sets the color of the border enclosing the range selector." + }, + "borderwidth": { + "valType": "number", + "min": 0, + "dflt": 0, + "role": "style", + "editType": "plot", + "description": "Sets the width (in px) of the border enclosing the range selector." + }, + "editType": "plot", + "role": "object" + }, + "calendar": { + "valType": "enumerated", + "values": [ + "gregorian", + "chinese", + "coptic", + "discworld", + "ethiopian", + "hebrew", + "islamic", + "julian", + "mayan", + "nanakshahi", + "nepali", + "persian", + "jalali", + "taiwan", + "thai", + "ummalqura" + ], + "role": "info", + "editType": "calc", + "dflt": "gregorian", + "description": "Sets the calendar system to use for `range` and `tick0` if this is a date axis. This does not set the calendar for interpreting data on this axis, that's specified in the trace or via the global `layout.calendar`" + }, + "_isSubplotObj": true, + "role": "object", + "tickvalssrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for tickvals .", + "editType": "none" + }, + "ticktextsrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for ticktext .", + "editType": "none" + }, + "categoryarraysrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for categoryarray .", + "editType": "none" + } + }, + "yaxis": { + "visible": { + "valType": "boolean", + "role": "info", + "editType": "plot", + "description": "A single toggle to hide the axis while preserving interaction like dragging. Default is true when a cheater plot is present on the axis, otherwise false" + }, + "color": { + "valType": "color", + "dflt": "#444", + "role": "style", + "editType": "ticks", + "description": "Sets default for all colors associated with this axis all at once: line, font, tick, and grid colors. Grid color is lightened by blending this with the plot background Individual pieces can override this." + }, + "title": { + "valType": "string", + "role": "info", + "editType": "ticks", + "description": "Sets the title of this axis." + }, + "titlefont": { + "family": { + "valType": "string", + "role": "style", + "noBlank": true, + "strict": true, + "editType": "ticks", + "description": "HTML font family - the typeface that will be applied by the web browser. The web browser will only be able to apply a font if it is available on the system which it operates. Provide multiple font families, separated by commas, to indicate the preference in which to apply fonts if they aren't available on the system. The plotly service (at https://plot.ly or on-premise) generates images on a server, where only a select number of fonts are installed and supported. These include *Arial*, *Balto*, *Courier New*, *Droid Sans*,, *Droid Serif*, *Droid Sans Mono*, *Gravitas One*, *Old Standard TT*, *Open Sans*, *Overpass*, *PT Sans Narrow*, *Raleway*, *Times New Roman*." + }, + "size": { + "valType": "number", + "role": "style", + "min": 1, + "editType": "ticks" + }, + "color": { + "valType": "color", + "role": "style", + "editType": "ticks" + }, + "editType": "ticks", + "description": "Sets this axis' title font.", + "role": "object" + }, + "type": { + "valType": "enumerated", + "values": [ + "-", + "linear", + "log", + "date", + "category" + ], + "dflt": "-", + "role": "info", + "editType": "calc", + "description": "Sets the axis type. By default, plotly attempts to determined the axis type by looking into the data of the traces that referenced the axis in question." + }, + "autorange": { + "valType": "enumerated", + "values": [ + true, + false, + "reversed" + ], + "dflt": true, + "role": "style", + "editType": "calc", + "impliedEdits": {}, + "description": "Determines whether or not the range of this axis is computed in relation to the input data. See `rangemode` for more info. If `range` is provided, then `autorange` is set to *false*." + }, + "rangemode": { + "valType": "enumerated", + "values": [ + "normal", + "tozero", + "nonnegative" + ], + "dflt": "normal", + "role": "style", + "editType": "calc", + "description": "If *normal*, the range is computed in relation to the extrema of the input data. If *tozero*`, the range extends to 0, regardless of the input data If *nonnegative*, the range is non-negative, regardless of the input data." + }, + "range": { + "valType": "info_array", + "role": "info", + "items": [ + { + "valType": "any", + "editType": "plot", + "impliedEdits": { + "^autorange": false + } + }, + { + "valType": "any", + "editType": "plot", + "impliedEdits": { + "^autorange": false + } + } + ], + "editType": "plot", + "impliedEdits": { + "autorange": false + }, + "description": "Sets the range of this axis. If the axis `type` is *log*, then you must take the log of your desired range (e.g. to set the range from 1 to 100, set the range from 0 to 2). If the axis `type` is *date*, it should be date strings, like date data, though Date objects and unix milliseconds will be accepted and converted to strings. If the axis `type` is *category*, it should be numbers, using the scale where each category is assigned a serial number from zero in the order it appears." + }, + "fixedrange": { + "valType": "boolean", + "dflt": false, + "role": "info", + "editType": "calc", + "description": "Determines whether or not this axis is zoom-able. If true, then zoom is disabled." + }, + "scaleanchor": { + "valType": "enumerated", + "values": [ + "/^x([2-9]|[1-9][0-9]+)?$/", + "/^y([2-9]|[1-9][0-9]+)?$/" + ], + "role": "info", + "editType": "calc", + "description": "If set to another axis id (e.g. `x2`, `y`), the range of this axis changes together with the range of the corresponding axis such that the scale of pixels per unit is in a constant ratio. Both axes are still zoomable, but when you zoom one, the other will zoom the same amount, keeping a fixed midpoint. `constrain` and `constraintoward` determine how we enforce the constraint. You can chain these, ie `yaxis: {scaleanchor: *x*}, xaxis2: {scaleanchor: *y*}` but you can only link axes of the same `type`. The linked axis can have the opposite letter (to constrain the aspect ratio) or the same letter (to match scales across subplots). Loops (`yaxis: {scaleanchor: *x*}, xaxis: {scaleanchor: *y*}` or longer) are redundant and the last constraint encountered will be ignored to avoid possible inconsistent constraints via `scaleratio`." + }, + "scaleratio": { + "valType": "number", + "min": 0, + "dflt": 1, + "role": "info", + "editType": "calc", + "description": "If this axis is linked to another by `scaleanchor`, this determines the pixel to unit scale ratio. For example, if this value is 10, then every unit on this axis spans 10 times the number of pixels as a unit on the linked axis. Use this for example to create an elevation profile where the vertical scale is exaggerated a fixed amount with respect to the horizontal." + }, + "constrain": { + "valType": "enumerated", + "values": [ + "range", + "domain" + ], + "dflt": "range", + "role": "info", + "editType": "calc", + "description": "If this axis needs to be compressed (either due to its own `scaleanchor` and `scaleratio` or those of the other axis), determines how that happens: by increasing the *range* (default), or by decreasing the *domain*." + }, + "constraintoward": { + "valType": "enumerated", + "values": [ + "left", + "center", + "right", + "top", + "middle", + "bottom" + ], + "role": "info", + "editType": "calc", + "description": "If this axis needs to be compressed (either due to its own `scaleanchor` and `scaleratio` or those of the other axis), determines which direction we push the originally specified plot area. Options are *left*, *center* (default), and *right* for x axes, and *top*, *middle* (default), and *bottom* for y axes." + }, + "tickmode": { + "valType": "enumerated", + "values": [ + "auto", + "linear", + "array" + ], + "role": "info", + "editType": "ticks", + "impliedEdits": {}, + "description": "Sets the tick mode for this axis. If *auto*, the number of ticks is set via `nticks`. If *linear*, the placement of the ticks is determined by a starting position `tick0` and a tick step `dtick` (*linear* is the default value if `tick0` and `dtick` are provided). If *array*, the placement of the ticks is set via `tickvals` and the tick text is `ticktext`. (*array* is the default value if `tickvals` is provided)." + }, + "nticks": { + "valType": "integer", + "min": 0, + "dflt": 0, + "role": "style", + "editType": "ticks", + "description": "Specifies the maximum number of ticks for the particular axis. The actual number of ticks will be chosen automatically to be less than or equal to `nticks`. Has an effect only if `tickmode` is set to *auto*." + }, + "tick0": { + "valType": "any", + "role": "style", + "editType": "ticks", + "impliedEdits": { + "tickmode": "linear" + }, + "description": "Sets the placement of the first tick on this axis. Use with `dtick`. If the axis `type` is *log*, then you must take the log of your starting tick (e.g. to set the starting tick to 100, set the `tick0` to 2) except when `dtick`=*L* (see `dtick` for more info). If the axis `type` is *date*, it should be a date string, like date data. If the axis `type` is *category*, it should be a number, using the scale where each category is assigned a serial number from zero in the order it appears." + }, + "dtick": { + "valType": "any", + "role": "style", + "editType": "ticks", + "impliedEdits": { + "tickmode": "linear" + }, + "description": "Sets the step in-between ticks on this axis. Use with `tick0`. Must be a positive number, or special strings available to *log* and *date* axes. If the axis `type` is *log*, then ticks are set every 10^(n*dtick) where n is the tick number. For example, to set a tick mark at 1, 10, 100, 1000, ... set dtick to 1. To set tick marks at 1, 100, 10000, ... set dtick to 2. To set tick marks at 1, 5, 25, 125, 625, 3125, ... set dtick to log_10(5), or 0.69897000433. *log* has several special values; *L*, where `f` is a positive number, gives ticks linearly spaced in value (but not position). For example `tick0` = 0.1, `dtick` = *L0.5* will put ticks at 0.1, 0.6, 1.1, 1.6 etc. To show powers of 10 plus small digits between, use *D1* (all digits) or *D2* (only 2 and 5). `tick0` is ignored for *D1* and *D2*. If the axis `type` is *date*, then you must convert the time to milliseconds. For example, to set the interval between ticks to one day, set `dtick` to 86400000.0. *date* also has special values *M* gives ticks spaced by a number of months. `n` must be a positive integer. To set ticks on the 15th of every third month, set `tick0` to *2000-01-15* and `dtick` to *M3*. To set ticks every 4 years, set `dtick` to *M48*" + }, + "tickvals": { + "valType": "data_array", + "editType": "ticks", + "description": "Sets the values at which ticks on this axis appear. Only has an effect if `tickmode` is set to *array*. Used with `ticktext`.", + "role": "data" + }, + "ticktext": { + "valType": "data_array", + "editType": "ticks", + "description": "Sets the text displayed at the ticks position via `tickvals`. Only has an effect if `tickmode` is set to *array*. Used with `tickvals`.", + "role": "data" + }, + "ticks": { + "valType": "enumerated", + "values": [ + "outside", + "inside", + "" + ], + "role": "style", + "editType": "ticks", + "description": "Determines whether ticks are drawn or not. If **, this axis' ticks are not drawn. If *outside* (*inside*), this axis' are drawn outside (inside) the axis lines." + }, + "mirror": { + "valType": "enumerated", + "values": [ + true, + "ticks", + false, + "all", + "allticks" + ], + "dflt": false, + "role": "style", + "editType": "ticks+layoutstyle", + "description": "Determines if the axis lines or/and ticks are mirrored to the opposite side of the plotting area. If *true*, the axis lines are mirrored. If *ticks*, the axis lines and ticks are mirrored. If *false*, mirroring is disable. If *all*, axis lines are mirrored on all shared-axes subplots. If *allticks*, axis lines and ticks are mirrored on all shared-axes subplots." + }, + "ticklen": { + "valType": "number", + "min": 0, + "dflt": 5, + "role": "style", + "editType": "ticks", + "description": "Sets the tick length (in px)." + }, + "tickwidth": { + "valType": "number", + "min": 0, + "dflt": 1, + "role": "style", + "editType": "ticks", + "description": "Sets the tick width (in px)." + }, + "tickcolor": { + "valType": "color", + "dflt": "#444", + "role": "style", + "editType": "ticks", + "description": "Sets the tick color." + }, + "showticklabels": { + "valType": "boolean", + "dflt": true, + "role": "style", + "editType": "ticks", + "description": "Determines whether or not the tick labels are drawn." + }, + "showspikes": { + "valType": "boolean", + "dflt": false, + "role": "style", + "editType": "modebar", + "description": "Determines whether or not spikes (aka droplines) are drawn for this axis. Note: This only takes affect when hovermode = closest" + }, + "spikecolor": { + "valType": "color", + "dflt": null, + "role": "style", + "editType": "none", + "description": "Sets the spike color. If undefined, will use the series color" + }, + "spikethickness": { + "valType": "number", + "dflt": 3, + "role": "style", + "editType": "none", + "description": "Sets the width (in px) of the zero line." + }, + "spikedash": { + "valType": "string", + "values": [ + "solid", + "dot", + "dash", + "longdash", + "dashdot", + "longdashdot" + ], + "dflt": "dash", + "role": "style", + "editType": "none", + "description": "Sets the dash style of lines. Set to a dash type string (*solid*, *dot*, *dash*, *longdash*, *dashdot*, or *longdashdot*) or a dash length list in px (eg *5px,10px,2px,2px*)." + }, + "spikemode": { + "valType": "flaglist", + "flags": [ + "toaxis", + "across", + "marker" + ], + "role": "style", + "dflt": "toaxis", + "editType": "none", + "description": "Determines the drawing mode for the spike line If *toaxis*, the line is drawn from the data point to the axis the series is plotted on. If *across*, the line is drawn across the entire plot area, and supercedes *toaxis*. If *marker*, then a marker dot is drawn on the axis the series is plotted on" + }, + "tickfont": { + "family": { + "valType": "string", + "role": "style", + "noBlank": true, + "strict": true, + "editType": "ticks", + "description": "HTML font family - the typeface that will be applied by the web browser. The web browser will only be able to apply a font if it is available on the system which it operates. Provide multiple font families, separated by commas, to indicate the preference in which to apply fonts if they aren't available on the system. The plotly service (at https://plot.ly or on-premise) generates images on a server, where only a select number of fonts are installed and supported. These include *Arial*, *Balto*, *Courier New*, *Droid Sans*,, *Droid Serif*, *Droid Sans Mono*, *Gravitas One*, *Old Standard TT*, *Open Sans*, *Overpass*, *PT Sans Narrow*, *Raleway*, *Times New Roman*." + }, + "size": { + "valType": "number", + "role": "style", + "min": 1, + "editType": "ticks" + }, + "color": { + "valType": "color", + "role": "style", + "editType": "ticks" + }, + "editType": "ticks", + "description": "Sets the tick font.", + "role": "object" + }, + "tickangle": { + "valType": "angle", + "dflt": "auto", + "role": "style", + "editType": "ticks", + "description": "Sets the angle of the tick labels with respect to the horizontal. For example, a `tickangle` of -90 draws the tick labels vertically." + }, + "tickprefix": { + "valType": "string", + "dflt": "", + "role": "style", + "editType": "ticks", + "description": "Sets a tick label prefix." + }, + "showtickprefix": { + "valType": "enumerated", + "values": [ + "all", + "first", + "last", + "none" + ], + "dflt": "all", + "role": "style", + "editType": "ticks", + "description": "If *all*, all tick labels are displayed with a prefix. If *first*, only the first tick is displayed with a prefix. If *last*, only the last tick is displayed with a suffix. If *none*, tick prefixes are hidden." + }, + "ticksuffix": { + "valType": "string", + "dflt": "", + "role": "style", + "editType": "ticks", + "description": "Sets a tick label suffix." + }, + "showticksuffix": { + "valType": "enumerated", + "values": [ + "all", + "first", + "last", + "none" + ], + "dflt": "all", + "role": "style", + "editType": "ticks", + "description": "Same as `showtickprefix` but for tick suffixes." + }, + "showexponent": { + "valType": "enumerated", + "values": [ + "all", + "first", + "last", + "none" + ], + "dflt": "all", + "role": "style", + "editType": "ticks", + "description": "If *all*, all exponents are shown besides their significands. If *first*, only the exponent of the first tick is shown. If *last*, only the exponent of the last tick is shown. If *none*, no exponents appear." + }, + "exponentformat": { + "valType": "enumerated", + "values": [ + "none", + "e", + "E", + "power", + "SI", + "B" + ], + "dflt": "B", + "role": "style", + "editType": "ticks", + "description": "Determines a formatting rule for the tick exponents. For example, consider the number 1,000,000,000. If *none*, it appears as 1,000,000,000. If *e*, 1e+9. If *E*, 1E+9. If *power*, 1x10^9 (with 9 in a super script). If *SI*, 1G. If *B*, 1B." + }, + "separatethousands": { + "valType": "boolean", + "dflt": false, + "role": "style", + "editType": "ticks", + "description": "If \"true\", even 4-digit integers are separated" + }, + "tickformat": { + "valType": "string", + "dflt": "", + "role": "style", + "editType": "ticks", + "description": "Sets the tick label formatting rule using d3 formatting mini-languages which are very similar to those in Python. For numbers, see: https://github.com/d3/d3-format/blob/master/README.md#locale_format And for dates see: https://github.com/d3/d3-time-format/blob/master/README.md#locale_format We add one item to d3's date formatter: *%{n}f* for fractional seconds with n digits. For example, *2016-10-13 09:15:23.456* with tickformat *%H~%M~%S.%2f* would display *09~15~23.46*" + }, + "tickformatstops": { + "items": { + "tickformatstop": { + "dtickrange": { + "valType": "info_array", + "role": "info", + "items": [ + { + "valType": "any", + "editType": "ticks" + }, + { + "valType": "any", + "editType": "ticks" + } + ], + "editType": "ticks", + "description": "range [*min*, *max*], where *min*, *max* - dtick values which describe some zoom level, it is possible to omit *min* or *max* value by passing *null*" + }, + "value": { + "valType": "string", + "dflt": "", + "role": "style", + "editType": "ticks", + "description": "string - dtickformat for described zoom level, the same as *tickformat*" + }, + "editType": "ticks", + "role": "object" + } + }, + "role": "object" + }, + "hoverformat": { + "valType": "string", + "dflt": "", + "role": "style", + "editType": "none", + "description": "Sets the hover text formatting rule using d3 formatting mini-languages which are very similar to those in Python. For numbers, see: https://github.com/d3/d3-format/blob/master/README.md#locale_format And for dates see: https://github.com/d3/d3-time-format/blob/master/README.md#locale_format We add one item to d3's date formatter: *%{n}f* for fractional seconds with n digits. For example, *2016-10-13 09:15:23.456* with tickformat *%H~%M~%S.%2f* would display *09~15~23.46*" + }, + "showline": { + "valType": "boolean", + "dflt": false, + "role": "style", + "editType": "layoutstyle", + "description": "Determines whether or not a line bounding this axis is drawn." + }, + "linecolor": { + "valType": "color", + "dflt": "#444", + "role": "style", + "editType": "layoutstyle", + "description": "Sets the axis line color." + }, + "linewidth": { + "valType": "number", + "min": 0, + "dflt": 1, + "role": "style", + "editType": "ticks+layoutstyle", + "description": "Sets the width (in px) of the axis line." + }, + "showgrid": { + "valType": "boolean", + "role": "style", + "editType": "ticks", + "description": "Determines whether or not grid lines are drawn. If *true*, the grid lines are drawn at every tick mark." + }, + "gridcolor": { + "valType": "color", + "dflt": "#eee", + "role": "style", + "editType": "ticks", + "description": "Sets the color of the grid lines." + }, + "gridwidth": { + "valType": "number", + "min": 0, + "dflt": 1, + "role": "style", + "editType": "ticks", + "description": "Sets the width (in px) of the grid lines." + }, + "zeroline": { + "valType": "boolean", + "role": "style", + "editType": "ticks", + "description": "Determines whether or not a line is drawn at along the 0 value of this axis. If *true*, the zero line is drawn on top of the grid lines." + }, + "zerolinecolor": { + "valType": "color", + "dflt": "#444", + "role": "style", + "editType": "ticks", + "description": "Sets the line color of the zero line." + }, + "zerolinewidth": { + "valType": "number", + "dflt": 1, + "role": "style", + "editType": "ticks", + "description": "Sets the width (in px) of the zero line." + }, + "anchor": { + "valType": "enumerated", + "values": [ + "free", + "/^x([2-9]|[1-9][0-9]+)?$/", + "/^y([2-9]|[1-9][0-9]+)?$/" + ], + "role": "info", + "editType": "plot", + "description": "If set to an opposite-letter axis id (e.g. `x2`, `y`), this axis is bound to the corresponding opposite-letter axis. If set to *free*, this axis' position is determined by `position`." + }, + "side": { + "valType": "enumerated", + "values": [ + "top", + "bottom", + "left", + "right" + ], + "role": "info", + "editType": "plot", + "description": "Determines whether a x (y) axis is positioned at the *bottom* (*left*) or *top* (*right*) of the plotting area." + }, + "overlaying": { + "valType": "enumerated", + "values": [ + "free", + "/^x([2-9]|[1-9][0-9]+)?$/", + "/^y([2-9]|[1-9][0-9]+)?$/" + ], + "role": "info", + "editType": "calc", + "description": "If set a same-letter axis id, this axis is overlaid on top of the corresponding same-letter axis. If *false*, this axis does not overlay any same-letter axes." + }, + "layer": { + "valType": "enumerated", + "values": [ + "above traces", + "below traces" + ], + "dflt": "above traces", + "role": "info", + "editType": "plot", + "description": "Sets the layer on which this axis is displayed. If *above traces*, this axis is displayed above all the subplot's traces If *below traces*, this axis is displayed below all the subplot's traces, but above the grid lines. Useful when used together with scatter-like traces with `cliponaxis` set to *false* to show markers and/or text nodes above this axis." + }, + "domain": { + "valType": "info_array", + "role": "info", + "items": [ + { + "valType": "number", + "min": 0, + "max": 1, + "editType": "calc" + }, + { + "valType": "number", + "min": 0, + "max": 1, + "editType": "calc" + } + ], + "dflt": [ + 0, + 1 + ], + "editType": "calc", + "description": "Sets the domain of this axis (in plot fraction)." + }, + "position": { + "valType": "number", + "min": 0, + "max": 1, + "dflt": 0, + "role": "style", + "editType": "plot", + "description": "Sets the position of this axis in the plotting space (in normalized coordinates). Only has an effect if `anchor` is set to *free*." + }, + "categoryorder": { + "valType": "enumerated", + "values": [ + "trace", + "category ascending", + "category descending", + "array" + ], + "dflt": "trace", + "role": "info", + "editType": "calc", + "description": "Specifies the ordering logic for the case of categorical variables. By default, plotly uses *trace*, which specifies the order that is present in the data supplied. Set `categoryorder` to *category ascending* or *category descending* if order should be determined by the alphanumerical order of the category names. Set `categoryorder` to *array* to derive the ordering from the attribute `categoryarray`. If a category is not found in the `categoryarray` array, the sorting behavior for that attribute will be identical to the *trace* mode. The unspecified categories will follow the categories in `categoryarray`." + }, + "categoryarray": { + "valType": "data_array", + "role": "data", + "editType": "calc", + "description": "Sets the order in which categories on this axis appear. Only has an effect if `categoryorder` is set to *array*. Used with `categoryorder`." + }, + "editType": "calc", + "_deprecated": { + "autotick": { + "valType": "boolean", + "role": "info", + "editType": "ticks", + "description": "Obsolete. Set `tickmode` to *auto* for old `autotick` *true* behavior. Set `tickmode` to *linear* for `autotick` *false*." + } + }, + "calendar": { + "valType": "enumerated", + "values": [ + "gregorian", + "chinese", + "coptic", + "discworld", + "ethiopian", + "hebrew", + "islamic", + "julian", + "mayan", + "nanakshahi", + "nepali", + "persian", + "jalali", + "taiwan", + "thai", + "ummalqura" + ], + "role": "info", + "editType": "calc", + "dflt": "gregorian", + "description": "Sets the calendar system to use for `range` and `tick0` if this is a date axis. This does not set the calendar for interpreting data on this axis, that's specified in the trace or via the global `layout.calendar`" + }, + "_isSubplotObj": true, + "role": "object", + "tickvalssrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for tickvals .", + "editType": "none" + }, + "ticktextsrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for ticktext .", + "editType": "none" + }, + "categoryarraysrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for categoryarray .", + "editType": "none" + } + }, + "ternary": { + "domain": { + "x": { + "valType": "info_array", + "role": "info", + "items": [ + { + "valType": "number", + "min": 0, + "max": 1, + "editType": "plot" + }, + { + "valType": "number", + "min": 0, + "max": 1, + "editType": "plot" + } + ], + "dflt": [ + 0, + 1 + ], + "description": "Sets the horizontal domain of this subplot (in plot fraction).", + "editType": "plot" + }, + "y": { + "valType": "info_array", + "role": "info", + "items": [ + { + "valType": "number", + "min": 0, + "max": 1, + "editType": "plot" + }, + { + "valType": "number", + "min": 0, + "max": 1, + "editType": "plot" + } + ], + "dflt": [ + 0, + 1 + ], + "description": "Sets the vertical domain of this subplot (in plot fraction).", + "editType": "plot" + }, + "editType": "plot", + "role": "object" + }, + "bgcolor": { + "valType": "color", + "role": "style", + "dflt": "#fff", + "description": "Set the background color of the subplot", + "editType": "plot" + }, + "sum": { + "valType": "number", + "role": "info", + "dflt": 1, + "min": 0, + "description": "The number each triplet should sum to, and the maximum range of each axis", + "editType": "plot" + }, + "aaxis": { + "title": { + "valType": "string", + "role": "info", + "editType": "plot", + "description": "Sets the title of this axis." + }, + "titlefont": { + "family": { + "valType": "string", + "role": "style", + "noBlank": true, + "strict": true, + "editType": "plot", + "description": "HTML font family - the typeface that will be applied by the web browser. The web browser will only be able to apply a font if it is available on the system which it operates. Provide multiple font families, separated by commas, to indicate the preference in which to apply fonts if they aren't available on the system. The plotly service (at https://plot.ly or on-premise) generates images on a server, where only a select number of fonts are installed and supported. These include *Arial*, *Balto*, *Courier New*, *Droid Sans*,, *Droid Serif*, *Droid Sans Mono*, *Gravitas One*, *Old Standard TT*, *Open Sans*, *Overpass*, *PT Sans Narrow*, *Raleway*, *Times New Roman*." + }, + "size": { + "valType": "number", + "role": "style", + "min": 1, + "editType": "plot" + }, + "color": { + "valType": "color", + "role": "style", + "editType": "plot" + }, + "editType": "plot", + "description": "Sets this axis' title font.", + "role": "object" + }, + "color": { + "valType": "color", + "dflt": "#444", + "role": "style", + "editType": "plot", + "description": "Sets default for all colors associated with this axis all at once: line, font, tick, and grid colors. Grid color is lightened by blending this with the plot background Individual pieces can override this." + }, + "tickmode": { + "valType": "enumerated", + "values": [ + "auto", + "linear", + "array" + ], + "role": "info", + "editType": "plot", + "impliedEdits": {}, + "description": "Sets the tick mode for this axis. If *auto*, the number of ticks is set via `nticks`. If *linear*, the placement of the ticks is determined by a starting position `tick0` and a tick step `dtick` (*linear* is the default value if `tick0` and `dtick` are provided). If *array*, the placement of the ticks is set via `tickvals` and the tick text is `ticktext`. (*array* is the default value if `tickvals` is provided)." + }, + "nticks": { + "valType": "integer", + "min": 1, + "dflt": 6, + "role": "style", + "editType": "plot", + "description": "Specifies the maximum number of ticks for the particular axis. The actual number of ticks will be chosen automatically to be less than or equal to `nticks`. Has an effect only if `tickmode` is set to *auto*." + }, + "tick0": { + "valType": "any", + "role": "style", + "editType": "plot", + "impliedEdits": { + "tickmode": "linear" + }, + "description": "Sets the placement of the first tick on this axis. Use with `dtick`. If the axis `type` is *log*, then you must take the log of your starting tick (e.g. to set the starting tick to 100, set the `tick0` to 2) except when `dtick`=*L* (see `dtick` for more info). If the axis `type` is *date*, it should be a date string, like date data. If the axis `type` is *category*, it should be a number, using the scale where each category is assigned a serial number from zero in the order it appears." + }, + "dtick": { + "valType": "any", + "role": "style", + "editType": "plot", + "impliedEdits": { + "tickmode": "linear" + }, + "description": "Sets the step in-between ticks on this axis. Use with `tick0`. Must be a positive number, or special strings available to *log* and *date* axes. If the axis `type` is *log*, then ticks are set every 10^(n*dtick) where n is the tick number. For example, to set a tick mark at 1, 10, 100, 1000, ... set dtick to 1. To set tick marks at 1, 100, 10000, ... set dtick to 2. To set tick marks at 1, 5, 25, 125, 625, 3125, ... set dtick to log_10(5), or 0.69897000433. *log* has several special values; *L*, where `f` is a positive number, gives ticks linearly spaced in value (but not position). For example `tick0` = 0.1, `dtick` = *L0.5* will put ticks at 0.1, 0.6, 1.1, 1.6 etc. To show powers of 10 plus small digits between, use *D1* (all digits) or *D2* (only 2 and 5). `tick0` is ignored for *D1* and *D2*. If the axis `type` is *date*, then you must convert the time to milliseconds. For example, to set the interval between ticks to one day, set `dtick` to 86400000.0. *date* also has special values *M* gives ticks spaced by a number of months. `n` must be a positive integer. To set ticks on the 15th of every third month, set `tick0` to *2000-01-15* and `dtick` to *M3*. To set ticks every 4 years, set `dtick` to *M48*" + }, + "tickvals": { + "valType": "data_array", + "editType": "plot", + "description": "Sets the values at which ticks on this axis appear. Only has an effect if `tickmode` is set to *array*. Used with `ticktext`.", + "role": "data" + }, + "ticktext": { + "valType": "data_array", + "editType": "plot", + "description": "Sets the text displayed at the ticks position via `tickvals`. Only has an effect if `tickmode` is set to *array*. Used with `tickvals`.", + "role": "data" + }, + "ticks": { + "valType": "enumerated", + "values": [ + "outside", + "inside", + "" + ], + "role": "style", + "editType": "plot", + "description": "Determines whether ticks are drawn or not. If **, this axis' ticks are not drawn. If *outside* (*inside*), this axis' are drawn outside (inside) the axis lines." + }, + "ticklen": { + "valType": "number", + "min": 0, + "dflt": 5, + "role": "style", + "editType": "plot", + "description": "Sets the tick length (in px)." + }, + "tickwidth": { + "valType": "number", + "min": 0, + "dflt": 1, + "role": "style", + "editType": "plot", + "description": "Sets the tick width (in px)." + }, + "tickcolor": { + "valType": "color", + "dflt": "#444", + "role": "style", + "editType": "plot", + "description": "Sets the tick color." + }, + "showticklabels": { + "valType": "boolean", + "dflt": true, + "role": "style", + "editType": "plot", + "description": "Determines whether or not the tick labels are drawn." + }, + "showtickprefix": { + "valType": "enumerated", + "values": [ + "all", + "first", + "last", + "none" + ], + "dflt": "all", + "role": "style", + "editType": "plot", + "description": "If *all*, all tick labels are displayed with a prefix. If *first*, only the first tick is displayed with a prefix. If *last*, only the last tick is displayed with a suffix. If *none*, tick prefixes are hidden." + }, + "tickprefix": { + "valType": "string", + "dflt": "", + "role": "style", + "editType": "plot", + "description": "Sets a tick label prefix." + }, + "showticksuffix": { + "valType": "enumerated", + "values": [ + "all", + "first", + "last", + "none" + ], + "dflt": "all", + "role": "style", + "editType": "plot", + "description": "Same as `showtickprefix` but for tick suffixes." + }, + "ticksuffix": { + "valType": "string", + "dflt": "", + "role": "style", + "editType": "plot", + "description": "Sets a tick label suffix." + }, + "showexponent": { + "valType": "enumerated", + "values": [ + "all", + "first", + "last", + "none" + ], + "dflt": "all", + "role": "style", + "editType": "plot", + "description": "If *all*, all exponents are shown besides their significands. If *first*, only the exponent of the first tick is shown. If *last*, only the exponent of the last tick is shown. If *none*, no exponents appear." + }, + "exponentformat": { + "valType": "enumerated", + "values": [ + "none", + "e", + "E", + "power", + "SI", + "B" + ], + "dflt": "B", + "role": "style", + "editType": "plot", + "description": "Determines a formatting rule for the tick exponents. For example, consider the number 1,000,000,000. If *none*, it appears as 1,000,000,000. If *e*, 1e+9. If *E*, 1E+9. If *power*, 1x10^9 (with 9 in a super script). If *SI*, 1G. If *B*, 1B." + }, + "separatethousands": { + "valType": "boolean", + "dflt": false, + "role": "style", + "editType": "plot", + "description": "If \"true\", even 4-digit integers are separated" + }, + "tickfont": { + "family": { + "valType": "string", + "role": "style", + "noBlank": true, + "strict": true, + "editType": "plot", + "description": "HTML font family - the typeface that will be applied by the web browser. The web browser will only be able to apply a font if it is available on the system which it operates. Provide multiple font families, separated by commas, to indicate the preference in which to apply fonts if they aren't available on the system. The plotly service (at https://plot.ly or on-premise) generates images on a server, where only a select number of fonts are installed and supported. These include *Arial*, *Balto*, *Courier New*, *Droid Sans*,, *Droid Serif*, *Droid Sans Mono*, *Gravitas One*, *Old Standard TT*, *Open Sans*, *Overpass*, *PT Sans Narrow*, *Raleway*, *Times New Roman*." + }, + "size": { + "valType": "number", + "role": "style", + "min": 1, + "editType": "plot" + }, + "color": { + "valType": "color", + "role": "style", + "editType": "plot" + }, + "editType": "plot", + "description": "Sets the tick font.", + "role": "object" + }, + "tickangle": { + "valType": "angle", + "dflt": "auto", + "role": "style", + "editType": "plot", + "description": "Sets the angle of the tick labels with respect to the horizontal. For example, a `tickangle` of -90 draws the tick labels vertically." + }, + "tickformat": { + "valType": "string", + "dflt": "", + "role": "style", + "editType": "plot", + "description": "Sets the tick label formatting rule using d3 formatting mini-languages which are very similar to those in Python. For numbers, see: https://github.com/d3/d3-format/blob/master/README.md#locale_format And for dates see: https://github.com/d3/d3-time-format/blob/master/README.md#locale_format We add one item to d3's date formatter: *%{n}f* for fractional seconds with n digits. For example, *2016-10-13 09:15:23.456* with tickformat *%H~%M~%S.%2f* would display *09~15~23.46*" + }, + "tickformatstops": { + "items": { + "tickformatstop": { + "dtickrange": { + "valType": "info_array", + "role": "info", + "items": [ + { + "valType": "any", + "editType": "plot" + }, + { + "valType": "any", + "editType": "plot" + } + ], + "editType": "plot", + "description": "range [*min*, *max*], where *min*, *max* - dtick values which describe some zoom level, it is possible to omit *min* or *max* value by passing *null*" + }, + "value": { + "valType": "string", + "dflt": "", + "role": "style", + "editType": "plot", + "description": "string - dtickformat for described zoom level, the same as *tickformat*" + }, + "editType": "plot", + "role": "object" + } + }, + "role": "object" + }, + "hoverformat": { + "valType": "string", + "dflt": "", + "role": "style", + "editType": "plot", + "description": "Sets the hover text formatting rule using d3 formatting mini-languages which are very similar to those in Python. For numbers, see: https://github.com/d3/d3-format/blob/master/README.md#locale_format And for dates see: https://github.com/d3/d3-time-format/blob/master/README.md#locale_format We add one item to d3's date formatter: *%{n}f* for fractional seconds with n digits. For example, *2016-10-13 09:15:23.456* with tickformat *%H~%M~%S.%2f* would display *09~15~23.46*" + }, + "showline": { + "valType": "boolean", + "dflt": true, + "role": "style", + "editType": "plot", + "description": "Determines whether or not a line bounding this axis is drawn." + }, + "linecolor": { + "valType": "color", + "dflt": "#444", + "role": "style", + "editType": "plot", + "description": "Sets the axis line color." + }, + "linewidth": { + "valType": "number", + "min": 0, + "dflt": 1, + "role": "style", + "editType": "plot", + "description": "Sets the width (in px) of the axis line." + }, + "showgrid": { + "valType": "boolean", + "role": "style", + "editType": "plot", + "description": "Determines whether or not grid lines are drawn. If *true*, the grid lines are drawn at every tick mark.", + "dflt": true + }, + "gridcolor": { + "valType": "color", + "dflt": "#eee", + "role": "style", + "editType": "plot", + "description": "Sets the color of the grid lines." + }, + "gridwidth": { + "valType": "number", + "min": 0, + "dflt": 1, + "role": "style", + "editType": "plot", + "description": "Sets the width (in px) of the grid lines." + }, + "layer": { + "valType": "enumerated", + "values": [ + "above traces", + "below traces" + ], + "dflt": "above traces", + "role": "info", + "editType": "plot", + "description": "Sets the layer on which this axis is displayed. If *above traces*, this axis is displayed above all the subplot's traces If *below traces*, this axis is displayed below all the subplot's traces, but above the grid lines. Useful when used together with scatter-like traces with `cliponaxis` set to *false* to show markers and/or text nodes above this axis." + }, + "min": { + "valType": "number", + "dflt": 0, + "role": "info", + "min": 0, + "description": "The minimum value visible on this axis. The maximum is determined by the sum minus the minimum values of the other two axes. The full view corresponds to all the minima set to zero.", + "editType": "plot" + }, + "editType": "plot", + "role": "object", + "tickvalssrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for tickvals .", + "editType": "none" + }, + "ticktextsrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for ticktext .", + "editType": "none" + } + }, + "baxis": { + "title": { + "valType": "string", + "role": "info", + "editType": "plot", + "description": "Sets the title of this axis." + }, + "titlefont": { + "family": { + "valType": "string", + "role": "style", + "noBlank": true, + "strict": true, + "editType": "plot", + "description": "HTML font family - the typeface that will be applied by the web browser. The web browser will only be able to apply a font if it is available on the system which it operates. Provide multiple font families, separated by commas, to indicate the preference in which to apply fonts if they aren't available on the system. The plotly service (at https://plot.ly or on-premise) generates images on a server, where only a select number of fonts are installed and supported. These include *Arial*, *Balto*, *Courier New*, *Droid Sans*,, *Droid Serif*, *Droid Sans Mono*, *Gravitas One*, *Old Standard TT*, *Open Sans*, *Overpass*, *PT Sans Narrow*, *Raleway*, *Times New Roman*." + }, + "size": { + "valType": "number", + "role": "style", + "min": 1, + "editType": "plot" + }, + "color": { + "valType": "color", + "role": "style", + "editType": "plot" + }, + "editType": "plot", + "description": "Sets this axis' title font.", + "role": "object" + }, + "color": { + "valType": "color", + "dflt": "#444", + "role": "style", + "editType": "plot", + "description": "Sets default for all colors associated with this axis all at once: line, font, tick, and grid colors. Grid color is lightened by blending this with the plot background Individual pieces can override this." + }, + "tickmode": { + "valType": "enumerated", + "values": [ + "auto", + "linear", + "array" + ], + "role": "info", + "editType": "plot", + "impliedEdits": {}, + "description": "Sets the tick mode for this axis. If *auto*, the number of ticks is set via `nticks`. If *linear*, the placement of the ticks is determined by a starting position `tick0` and a tick step `dtick` (*linear* is the default value if `tick0` and `dtick` are provided). If *array*, the placement of the ticks is set via `tickvals` and the tick text is `ticktext`. (*array* is the default value if `tickvals` is provided)." + }, + "nticks": { + "valType": "integer", + "min": 1, + "dflt": 6, + "role": "style", + "editType": "plot", + "description": "Specifies the maximum number of ticks for the particular axis. The actual number of ticks will be chosen automatically to be less than or equal to `nticks`. Has an effect only if `tickmode` is set to *auto*." + }, + "tick0": { + "valType": "any", + "role": "style", + "editType": "plot", + "impliedEdits": { + "tickmode": "linear" + }, + "description": "Sets the placement of the first tick on this axis. Use with `dtick`. If the axis `type` is *log*, then you must take the log of your starting tick (e.g. to set the starting tick to 100, set the `tick0` to 2) except when `dtick`=*L* (see `dtick` for more info). If the axis `type` is *date*, it should be a date string, like date data. If the axis `type` is *category*, it should be a number, using the scale where each category is assigned a serial number from zero in the order it appears." + }, + "dtick": { + "valType": "any", + "role": "style", + "editType": "plot", + "impliedEdits": { + "tickmode": "linear" + }, + "description": "Sets the step in-between ticks on this axis. Use with `tick0`. Must be a positive number, or special strings available to *log* and *date* axes. If the axis `type` is *log*, then ticks are set every 10^(n*dtick) where n is the tick number. For example, to set a tick mark at 1, 10, 100, 1000, ... set dtick to 1. To set tick marks at 1, 100, 10000, ... set dtick to 2. To set tick marks at 1, 5, 25, 125, 625, 3125, ... set dtick to log_10(5), or 0.69897000433. *log* has several special values; *L*, where `f` is a positive number, gives ticks linearly spaced in value (but not position). For example `tick0` = 0.1, `dtick` = *L0.5* will put ticks at 0.1, 0.6, 1.1, 1.6 etc. To show powers of 10 plus small digits between, use *D1* (all digits) or *D2* (only 2 and 5). `tick0` is ignored for *D1* and *D2*. If the axis `type` is *date*, then you must convert the time to milliseconds. For example, to set the interval between ticks to one day, set `dtick` to 86400000.0. *date* also has special values *M* gives ticks spaced by a number of months. `n` must be a positive integer. To set ticks on the 15th of every third month, set `tick0` to *2000-01-15* and `dtick` to *M3*. To set ticks every 4 years, set `dtick` to *M48*" + }, + "tickvals": { + "valType": "data_array", + "editType": "plot", + "description": "Sets the values at which ticks on this axis appear. Only has an effect if `tickmode` is set to *array*. Used with `ticktext`.", + "role": "data" + }, + "ticktext": { + "valType": "data_array", + "editType": "plot", + "description": "Sets the text displayed at the ticks position via `tickvals`. Only has an effect if `tickmode` is set to *array*. Used with `tickvals`.", + "role": "data" + }, + "ticks": { + "valType": "enumerated", + "values": [ + "outside", + "inside", + "" + ], + "role": "style", + "editType": "plot", + "description": "Determines whether ticks are drawn or not. If **, this axis' ticks are not drawn. If *outside* (*inside*), this axis' are drawn outside (inside) the axis lines." + }, + "ticklen": { + "valType": "number", + "min": 0, + "dflt": 5, + "role": "style", + "editType": "plot", + "description": "Sets the tick length (in px)." + }, + "tickwidth": { + "valType": "number", + "min": 0, + "dflt": 1, + "role": "style", + "editType": "plot", + "description": "Sets the tick width (in px)." + }, + "tickcolor": { + "valType": "color", + "dflt": "#444", + "role": "style", + "editType": "plot", + "description": "Sets the tick color." + }, + "showticklabels": { + "valType": "boolean", + "dflt": true, + "role": "style", + "editType": "plot", + "description": "Determines whether or not the tick labels are drawn." + }, + "showtickprefix": { + "valType": "enumerated", + "values": [ + "all", + "first", + "last", + "none" + ], + "dflt": "all", + "role": "style", + "editType": "plot", + "description": "If *all*, all tick labels are displayed with a prefix. If *first*, only the first tick is displayed with a prefix. If *last*, only the last tick is displayed with a suffix. If *none*, tick prefixes are hidden." + }, + "tickprefix": { + "valType": "string", + "dflt": "", + "role": "style", + "editType": "plot", + "description": "Sets a tick label prefix." + }, + "showticksuffix": { + "valType": "enumerated", + "values": [ + "all", + "first", + "last", + "none" + ], + "dflt": "all", + "role": "style", + "editType": "plot", + "description": "Same as `showtickprefix` but for tick suffixes." + }, + "ticksuffix": { + "valType": "string", + "dflt": "", + "role": "style", + "editType": "plot", + "description": "Sets a tick label suffix." + }, + "showexponent": { + "valType": "enumerated", + "values": [ + "all", + "first", + "last", + "none" + ], + "dflt": "all", + "role": "style", + "editType": "plot", + "description": "If *all*, all exponents are shown besides their significands. If *first*, only the exponent of the first tick is shown. If *last*, only the exponent of the last tick is shown. If *none*, no exponents appear." + }, + "exponentformat": { + "valType": "enumerated", + "values": [ + "none", + "e", + "E", + "power", + "SI", + "B" + ], + "dflt": "B", + "role": "style", + "editType": "plot", + "description": "Determines a formatting rule for the tick exponents. For example, consider the number 1,000,000,000. If *none*, it appears as 1,000,000,000. If *e*, 1e+9. If *E*, 1E+9. If *power*, 1x10^9 (with 9 in a super script). If *SI*, 1G. If *B*, 1B." + }, + "separatethousands": { + "valType": "boolean", + "dflt": false, + "role": "style", + "editType": "plot", + "description": "If \"true\", even 4-digit integers are separated" + }, + "tickfont": { + "family": { + "valType": "string", + "role": "style", + "noBlank": true, + "strict": true, + "editType": "plot", + "description": "HTML font family - the typeface that will be applied by the web browser. The web browser will only be able to apply a font if it is available on the system which it operates. Provide multiple font families, separated by commas, to indicate the preference in which to apply fonts if they aren't available on the system. The plotly service (at https://plot.ly or on-premise) generates images on a server, where only a select number of fonts are installed and supported. These include *Arial*, *Balto*, *Courier New*, *Droid Sans*,, *Droid Serif*, *Droid Sans Mono*, *Gravitas One*, *Old Standard TT*, *Open Sans*, *Overpass*, *PT Sans Narrow*, *Raleway*, *Times New Roman*." + }, + "size": { + "valType": "number", + "role": "style", + "min": 1, + "editType": "plot" + }, + "color": { + "valType": "color", + "role": "style", + "editType": "plot" + }, + "editType": "plot", + "description": "Sets the tick font.", + "role": "object" + }, + "tickangle": { + "valType": "angle", + "dflt": "auto", + "role": "style", + "editType": "plot", + "description": "Sets the angle of the tick labels with respect to the horizontal. For example, a `tickangle` of -90 draws the tick labels vertically." + }, + "tickformat": { + "valType": "string", + "dflt": "", + "role": "style", + "editType": "plot", + "description": "Sets the tick label formatting rule using d3 formatting mini-languages which are very similar to those in Python. For numbers, see: https://github.com/d3/d3-format/blob/master/README.md#locale_format And for dates see: https://github.com/d3/d3-time-format/blob/master/README.md#locale_format We add one item to d3's date formatter: *%{n}f* for fractional seconds with n digits. For example, *2016-10-13 09:15:23.456* with tickformat *%H~%M~%S.%2f* would display *09~15~23.46*" + }, + "tickformatstops": { + "items": { + "tickformatstop": { + "dtickrange": { + "valType": "info_array", + "role": "info", + "items": [ + { + "valType": "any", + "editType": "plot" + }, + { + "valType": "any", + "editType": "plot" + } + ], + "editType": "plot", + "description": "range [*min*, *max*], where *min*, *max* - dtick values which describe some zoom level, it is possible to omit *min* or *max* value by passing *null*" + }, + "value": { + "valType": "string", + "dflt": "", + "role": "style", + "editType": "plot", + "description": "string - dtickformat for described zoom level, the same as *tickformat*" + }, + "editType": "plot", + "role": "object" + } + }, + "role": "object" + }, + "hoverformat": { + "valType": "string", + "dflt": "", + "role": "style", + "editType": "plot", + "description": "Sets the hover text formatting rule using d3 formatting mini-languages which are very similar to those in Python. For numbers, see: https://github.com/d3/d3-format/blob/master/README.md#locale_format And for dates see: https://github.com/d3/d3-time-format/blob/master/README.md#locale_format We add one item to d3's date formatter: *%{n}f* for fractional seconds with n digits. For example, *2016-10-13 09:15:23.456* with tickformat *%H~%M~%S.%2f* would display *09~15~23.46*" + }, + "showline": { + "valType": "boolean", + "dflt": true, + "role": "style", + "editType": "plot", + "description": "Determines whether or not a line bounding this axis is drawn." + }, + "linecolor": { + "valType": "color", + "dflt": "#444", + "role": "style", + "editType": "plot", + "description": "Sets the axis line color." + }, + "linewidth": { + "valType": "number", + "min": 0, + "dflt": 1, + "role": "style", + "editType": "plot", + "description": "Sets the width (in px) of the axis line." + }, + "showgrid": { + "valType": "boolean", + "role": "style", + "editType": "plot", + "description": "Determines whether or not grid lines are drawn. If *true*, the grid lines are drawn at every tick mark.", + "dflt": true + }, + "gridcolor": { + "valType": "color", + "dflt": "#eee", + "role": "style", + "editType": "plot", + "description": "Sets the color of the grid lines." + }, + "gridwidth": { + "valType": "number", + "min": 0, + "dflt": 1, + "role": "style", + "editType": "plot", + "description": "Sets the width (in px) of the grid lines." + }, + "layer": { + "valType": "enumerated", + "values": [ + "above traces", + "below traces" + ], + "dflt": "above traces", + "role": "info", + "editType": "plot", + "description": "Sets the layer on which this axis is displayed. If *above traces*, this axis is displayed above all the subplot's traces If *below traces*, this axis is displayed below all the subplot's traces, but above the grid lines. Useful when used together with scatter-like traces with `cliponaxis` set to *false* to show markers and/or text nodes above this axis." + }, + "min": { + "valType": "number", + "dflt": 0, + "role": "info", + "min": 0, + "description": "The minimum value visible on this axis. The maximum is determined by the sum minus the minimum values of the other two axes. The full view corresponds to all the minima set to zero.", + "editType": "plot" + }, + "editType": "plot", + "role": "object", + "tickvalssrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for tickvals .", + "editType": "none" + }, + "ticktextsrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for ticktext .", + "editType": "none" + } + }, + "caxis": { + "title": { + "valType": "string", + "role": "info", + "editType": "plot", + "description": "Sets the title of this axis." + }, + "titlefont": { + "family": { + "valType": "string", + "role": "style", + "noBlank": true, + "strict": true, + "editType": "plot", + "description": "HTML font family - the typeface that will be applied by the web browser. The web browser will only be able to apply a font if it is available on the system which it operates. Provide multiple font families, separated by commas, to indicate the preference in which to apply fonts if they aren't available on the system. The plotly service (at https://plot.ly or on-premise) generates images on a server, where only a select number of fonts are installed and supported. These include *Arial*, *Balto*, *Courier New*, *Droid Sans*,, *Droid Serif*, *Droid Sans Mono*, *Gravitas One*, *Old Standard TT*, *Open Sans*, *Overpass*, *PT Sans Narrow*, *Raleway*, *Times New Roman*." + }, + "size": { + "valType": "number", + "role": "style", + "min": 1, + "editType": "plot" + }, + "color": { + "valType": "color", + "role": "style", + "editType": "plot" + }, + "editType": "plot", + "description": "Sets this axis' title font.", + "role": "object" + }, + "color": { + "valType": "color", + "dflt": "#444", + "role": "style", + "editType": "plot", + "description": "Sets default for all colors associated with this axis all at once: line, font, tick, and grid colors. Grid color is lightened by blending this with the plot background Individual pieces can override this." + }, + "tickmode": { + "valType": "enumerated", + "values": [ + "auto", + "linear", + "array" + ], + "role": "info", + "editType": "plot", + "impliedEdits": {}, + "description": "Sets the tick mode for this axis. If *auto*, the number of ticks is set via `nticks`. If *linear*, the placement of the ticks is determined by a starting position `tick0` and a tick step `dtick` (*linear* is the default value if `tick0` and `dtick` are provided). If *array*, the placement of the ticks is set via `tickvals` and the tick text is `ticktext`. (*array* is the default value if `tickvals` is provided)." + }, + "nticks": { + "valType": "integer", + "min": 1, + "dflt": 6, + "role": "style", + "editType": "plot", + "description": "Specifies the maximum number of ticks for the particular axis. The actual number of ticks will be chosen automatically to be less than or equal to `nticks`. Has an effect only if `tickmode` is set to *auto*." + }, + "tick0": { + "valType": "any", + "role": "style", + "editType": "plot", + "impliedEdits": { + "tickmode": "linear" + }, + "description": "Sets the placement of the first tick on this axis. Use with `dtick`. If the axis `type` is *log*, then you must take the log of your starting tick (e.g. to set the starting tick to 100, set the `tick0` to 2) except when `dtick`=*L* (see `dtick` for more info). If the axis `type` is *date*, it should be a date string, like date data. If the axis `type` is *category*, it should be a number, using the scale where each category is assigned a serial number from zero in the order it appears." + }, + "dtick": { + "valType": "any", + "role": "style", + "editType": "plot", + "impliedEdits": { + "tickmode": "linear" + }, + "description": "Sets the step in-between ticks on this axis. Use with `tick0`. Must be a positive number, or special strings available to *log* and *date* axes. If the axis `type` is *log*, then ticks are set every 10^(n*dtick) where n is the tick number. For example, to set a tick mark at 1, 10, 100, 1000, ... set dtick to 1. To set tick marks at 1, 100, 10000, ... set dtick to 2. To set tick marks at 1, 5, 25, 125, 625, 3125, ... set dtick to log_10(5), or 0.69897000433. *log* has several special values; *L*, where `f` is a positive number, gives ticks linearly spaced in value (but not position). For example `tick0` = 0.1, `dtick` = *L0.5* will put ticks at 0.1, 0.6, 1.1, 1.6 etc. To show powers of 10 plus small digits between, use *D1* (all digits) or *D2* (only 2 and 5). `tick0` is ignored for *D1* and *D2*. If the axis `type` is *date*, then you must convert the time to milliseconds. For example, to set the interval between ticks to one day, set `dtick` to 86400000.0. *date* also has special values *M* gives ticks spaced by a number of months. `n` must be a positive integer. To set ticks on the 15th of every third month, set `tick0` to *2000-01-15* and `dtick` to *M3*. To set ticks every 4 years, set `dtick` to *M48*" + }, + "tickvals": { + "valType": "data_array", + "editType": "plot", + "description": "Sets the values at which ticks on this axis appear. Only has an effect if `tickmode` is set to *array*. Used with `ticktext`.", + "role": "data" + }, + "ticktext": { + "valType": "data_array", + "editType": "plot", + "description": "Sets the text displayed at the ticks position via `tickvals`. Only has an effect if `tickmode` is set to *array*. Used with `tickvals`.", + "role": "data" + }, + "ticks": { + "valType": "enumerated", + "values": [ + "outside", + "inside", + "" + ], + "role": "style", + "editType": "plot", + "description": "Determines whether ticks are drawn or not. If **, this axis' ticks are not drawn. If *outside* (*inside*), this axis' are drawn outside (inside) the axis lines." + }, + "ticklen": { + "valType": "number", + "min": 0, + "dflt": 5, + "role": "style", + "editType": "plot", + "description": "Sets the tick length (in px)." + }, + "tickwidth": { + "valType": "number", + "min": 0, + "dflt": 1, + "role": "style", + "editType": "plot", + "description": "Sets the tick width (in px)." + }, + "tickcolor": { + "valType": "color", + "dflt": "#444", + "role": "style", + "editType": "plot", + "description": "Sets the tick color." + }, + "showticklabels": { + "valType": "boolean", + "dflt": true, + "role": "style", + "editType": "plot", + "description": "Determines whether or not the tick labels are drawn." + }, + "showtickprefix": { + "valType": "enumerated", + "values": [ + "all", + "first", + "last", + "none" + ], + "dflt": "all", + "role": "style", + "editType": "plot", + "description": "If *all*, all tick labels are displayed with a prefix. If *first*, only the first tick is displayed with a prefix. If *last*, only the last tick is displayed with a suffix. If *none*, tick prefixes are hidden." + }, + "tickprefix": { + "valType": "string", + "dflt": "", + "role": "style", + "editType": "plot", + "description": "Sets a tick label prefix." + }, + "showticksuffix": { + "valType": "enumerated", + "values": [ + "all", + "first", + "last", + "none" + ], + "dflt": "all", + "role": "style", + "editType": "plot", + "description": "Same as `showtickprefix` but for tick suffixes." + }, + "ticksuffix": { + "valType": "string", + "dflt": "", + "role": "style", + "editType": "plot", + "description": "Sets a tick label suffix." + }, + "showexponent": { + "valType": "enumerated", + "values": [ + "all", + "first", + "last", + "none" + ], + "dflt": "all", + "role": "style", + "editType": "plot", + "description": "If *all*, all exponents are shown besides their significands. If *first*, only the exponent of the first tick is shown. If *last*, only the exponent of the last tick is shown. If *none*, no exponents appear." + }, + "exponentformat": { + "valType": "enumerated", + "values": [ + "none", + "e", + "E", + "power", + "SI", + "B" + ], + "dflt": "B", + "role": "style", + "editType": "plot", + "description": "Determines a formatting rule for the tick exponents. For example, consider the number 1,000,000,000. If *none*, it appears as 1,000,000,000. If *e*, 1e+9. If *E*, 1E+9. If *power*, 1x10^9 (with 9 in a super script). If *SI*, 1G. If *B*, 1B." + }, + "separatethousands": { + "valType": "boolean", + "dflt": false, + "role": "style", + "editType": "plot", + "description": "If \"true\", even 4-digit integers are separated" + }, + "tickfont": { + "family": { + "valType": "string", + "role": "style", + "noBlank": true, + "strict": true, + "editType": "plot", + "description": "HTML font family - the typeface that will be applied by the web browser. The web browser will only be able to apply a font if it is available on the system which it operates. Provide multiple font families, separated by commas, to indicate the preference in which to apply fonts if they aren't available on the system. The plotly service (at https://plot.ly or on-premise) generates images on a server, where only a select number of fonts are installed and supported. These include *Arial*, *Balto*, *Courier New*, *Droid Sans*,, *Droid Serif*, *Droid Sans Mono*, *Gravitas One*, *Old Standard TT*, *Open Sans*, *Overpass*, *PT Sans Narrow*, *Raleway*, *Times New Roman*." + }, + "size": { + "valType": "number", + "role": "style", + "min": 1, + "editType": "plot" + }, + "color": { + "valType": "color", + "role": "style", + "editType": "plot" + }, + "editType": "plot", + "description": "Sets the tick font.", + "role": "object" + }, + "tickangle": { + "valType": "angle", + "dflt": "auto", + "role": "style", + "editType": "plot", + "description": "Sets the angle of the tick labels with respect to the horizontal. For example, a `tickangle` of -90 draws the tick labels vertically." + }, + "tickformat": { + "valType": "string", + "dflt": "", + "role": "style", + "editType": "plot", + "description": "Sets the tick label formatting rule using d3 formatting mini-languages which are very similar to those in Python. For numbers, see: https://github.com/d3/d3-format/blob/master/README.md#locale_format And for dates see: https://github.com/d3/d3-time-format/blob/master/README.md#locale_format We add one item to d3's date formatter: *%{n}f* for fractional seconds with n digits. For example, *2016-10-13 09:15:23.456* with tickformat *%H~%M~%S.%2f* would display *09~15~23.46*" + }, + "tickformatstops": { + "items": { + "tickformatstop": { + "dtickrange": { + "valType": "info_array", + "role": "info", + "items": [ + { + "valType": "any", + "editType": "plot" + }, + { + "valType": "any", + "editType": "plot" + } + ], + "editType": "plot", + "description": "range [*min*, *max*], where *min*, *max* - dtick values which describe some zoom level, it is possible to omit *min* or *max* value by passing *null*" + }, + "value": { + "valType": "string", + "dflt": "", + "role": "style", + "editType": "plot", + "description": "string - dtickformat for described zoom level, the same as *tickformat*" + }, + "editType": "plot", + "role": "object" + } + }, + "role": "object" + }, + "hoverformat": { + "valType": "string", + "dflt": "", + "role": "style", + "editType": "plot", + "description": "Sets the hover text formatting rule using d3 formatting mini-languages which are very similar to those in Python. For numbers, see: https://github.com/d3/d3-format/blob/master/README.md#locale_format And for dates see: https://github.com/d3/d3-time-format/blob/master/README.md#locale_format We add one item to d3's date formatter: *%{n}f* for fractional seconds with n digits. For example, *2016-10-13 09:15:23.456* with tickformat *%H~%M~%S.%2f* would display *09~15~23.46*" + }, + "showline": { + "valType": "boolean", + "dflt": true, + "role": "style", + "editType": "plot", + "description": "Determines whether or not a line bounding this axis is drawn." + }, + "linecolor": { + "valType": "color", + "dflt": "#444", + "role": "style", + "editType": "plot", + "description": "Sets the axis line color." + }, + "linewidth": { + "valType": "number", + "min": 0, + "dflt": 1, + "role": "style", + "editType": "plot", + "description": "Sets the width (in px) of the axis line." + }, + "showgrid": { + "valType": "boolean", + "role": "style", + "editType": "plot", + "description": "Determines whether or not grid lines are drawn. If *true*, the grid lines are drawn at every tick mark.", + "dflt": true + }, + "gridcolor": { + "valType": "color", + "dflt": "#eee", + "role": "style", + "editType": "plot", + "description": "Sets the color of the grid lines." + }, + "gridwidth": { + "valType": "number", + "min": 0, + "dflt": 1, + "role": "style", + "editType": "plot", + "description": "Sets the width (in px) of the grid lines." + }, + "layer": { + "valType": "enumerated", + "values": [ + "above traces", + "below traces" + ], + "dflt": "above traces", + "role": "info", + "editType": "plot", + "description": "Sets the layer on which this axis is displayed. If *above traces*, this axis is displayed above all the subplot's traces If *below traces*, this axis is displayed below all the subplot's traces, but above the grid lines. Useful when used together with scatter-like traces with `cliponaxis` set to *false* to show markers and/or text nodes above this axis." + }, + "min": { + "valType": "number", + "dflt": 0, + "role": "info", + "min": 0, + "description": "The minimum value visible on this axis. The maximum is determined by the sum minus the minimum values of the other two axes. The full view corresponds to all the minima set to zero.", + "editType": "plot" + }, + "editType": "plot", + "role": "object", + "tickvalssrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for tickvals .", + "editType": "none" + }, + "ticktextsrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for ticktext .", + "editType": "none" + } + }, + "editType": "plot", + "_isSubplotObj": true, + "role": "object" + }, + "scene": { + "_arrayAttrRegexps": [ + {} + ], + "bgcolor": { + "valType": "color", + "role": "style", + "dflt": "rgba(0,0,0,0)", + "editType": "plot" + }, + "camera": { + "up": { + "x": { + "valType": "number", + "role": "info", + "dflt": 0, + "editType": "camera" + }, + "y": { + "valType": "number", + "role": "info", + "dflt": 0, + "editType": "camera" + }, + "z": { + "valType": "number", + "role": "info", + "dflt": 1, + "editType": "camera" + }, + "editType": "camera", + "description": "Sets the (x,y,z) components of the 'up' camera vector. This vector determines the up direction of this scene with respect to the page. The default is *{x: 0, y: 0, z: 1}* which means that the z axis points up.", + "role": "object" + }, + "center": { + "x": { + "valType": "number", + "role": "info", + "dflt": 0, + "editType": "camera" + }, + "y": { + "valType": "number", + "role": "info", + "dflt": 0, + "editType": "camera" + }, + "z": { + "valType": "number", + "role": "info", + "dflt": 0, + "editType": "camera" + }, + "editType": "camera", + "description": "Sets the (x,y,z) components of the 'center' camera vector This vector determines the translation (x,y,z) space about the center of this scene. By default, there is no such translation.", + "role": "object" + }, + "eye": { + "x": { + "valType": "number", + "role": "info", + "dflt": 1.25, + "editType": "camera" + }, + "y": { + "valType": "number", + "role": "info", + "dflt": 1.25, + "editType": "camera" + }, + "z": { + "valType": "number", + "role": "info", + "dflt": 1.25, + "editType": "camera" + }, + "editType": "camera", + "description": "Sets the (x,y,z) components of the 'eye' camera vector. This vector determines the view point about the origin of this scene.", + "role": "object" + }, + "editType": "camera", + "role": "object" + }, + "domain": { + "x": { + "valType": "info_array", + "role": "info", + "items": [ + { + "valType": "number", + "min": 0, + "max": 1, + "editType": "plot" + }, + { + "valType": "number", + "min": 0, + "max": 1, + "editType": "plot" + } + ], + "dflt": [ + 0, + 1 + ], + "editType": "plot", + "description": "Sets the horizontal domain of this scene (in plot fraction)." + }, + "y": { + "valType": "info_array", + "role": "info", + "items": [ + { + "valType": "number", + "min": 0, + "max": 1, + "editType": "plot" + }, + { + "valType": "number", + "min": 0, + "max": 1, + "editType": "plot" + } + ], + "dflt": [ + 0, + 1 + ], + "editType": "plot", + "description": "Sets the vertical domain of this scene (in plot fraction)." + }, + "editType": "plot", + "role": "object" + }, + "aspectmode": { + "valType": "enumerated", + "role": "info", + "values": [ + "auto", + "cube", + "data", + "manual" + ], + "dflt": "auto", + "editType": "plot", + "impliedEdits": {}, + "description": "If *cube*, this scene's axes are drawn as a cube, regardless of the axes' ranges. If *data*, this scene's axes are drawn in proportion with the axes' ranges. If *manual*, this scene's axes are drawn in proportion with the input of *aspectratio* (the default behavior if *aspectratio* is provided). If *auto*, this scene's axes are drawn using the results of *data* except when one axis is more than four times the size of the two others, where in that case the results of *cube* are used." + }, + "aspectratio": { + "x": { + "valType": "number", + "role": "info", + "min": 0, + "editType": "plot", + "impliedEdits": { + "^aspectmode": "manual" + } + }, + "y": { + "valType": "number", + "role": "info", + "min": 0, + "editType": "plot", + "impliedEdits": { + "^aspectmode": "manual" + } + }, + "z": { + "valType": "number", + "role": "info", + "min": 0, + "editType": "plot", + "impliedEdits": { + "^aspectmode": "manual" + } + }, + "editType": "plot", + "impliedEdits": { + "aspectmode": "manual", + "role": "object" + }, + "description": "Sets this scene's axis aspectratio.", + "role": "object" + }, + "xaxis": { + "visible": { + "valType": "boolean", + "role": "info", + "editType": "plot", + "description": "A single toggle to hide the axis while preserving interaction like dragging. Default is true when a cheater plot is present on the axis, otherwise false" + }, + "showspikes": { + "valType": "boolean", + "role": "info", + "dflt": true, + "description": "Sets whether or not spikes starting from data points to this axis' wall are shown on hover.", + "editType": "plot" + }, + "spikesides": { + "valType": "boolean", + "role": "info", + "dflt": true, + "description": "Sets whether or not spikes extending from the projection data points to this axis' wall boundaries are shown on hover.", + "editType": "plot" + }, + "spikethickness": { + "valType": "number", + "role": "style", + "min": 0, + "dflt": 2, + "description": "Sets the thickness (in px) of the spikes.", + "editType": "plot" + }, + "spikecolor": { + "valType": "color", + "role": "style", + "dflt": "#444", + "description": "Sets the color of the spikes.", + "editType": "plot" + }, + "showbackground": { + "valType": "boolean", + "role": "info", + "dflt": false, + "description": "Sets whether or not this axis' wall has a background color.", + "editType": "plot" + }, + "backgroundcolor": { + "valType": "color", + "role": "style", + "dflt": "rgba(204, 204, 204, 0.5)", + "description": "Sets the background color of this axis' wall.", + "editType": "plot" + }, + "showaxeslabels": { + "valType": "boolean", + "role": "info", + "dflt": true, + "description": "Sets whether or not this axis is labeled", + "editType": "plot" + }, + "color": { + "valType": "color", + "dflt": "#444", + "role": "style", + "editType": "plot", + "description": "Sets default for all colors associated with this axis all at once: line, font, tick, and grid colors. Grid color is lightened by blending this with the plot background Individual pieces can override this." + }, + "categoryorder": { + "valType": "enumerated", + "values": [ + "trace", + "category ascending", + "category descending", + "array" + ], + "dflt": "trace", + "role": "info", + "editType": "plot", + "description": "Specifies the ordering logic for the case of categorical variables. By default, plotly uses *trace*, which specifies the order that is present in the data supplied. Set `categoryorder` to *category ascending* or *category descending* if order should be determined by the alphanumerical order of the category names. Set `categoryorder` to *array* to derive the ordering from the attribute `categoryarray`. If a category is not found in the `categoryarray` array, the sorting behavior for that attribute will be identical to the *trace* mode. The unspecified categories will follow the categories in `categoryarray`." + }, + "categoryarray": { + "valType": "data_array", + "role": "data", + "editType": "plot", + "description": "Sets the order in which categories on this axis appear. Only has an effect if `categoryorder` is set to *array*. Used with `categoryorder`." + }, + "title": { + "valType": "string", + "role": "info", + "editType": "plot", + "description": "Sets the title of this axis." + }, + "titlefont": { + "family": { + "valType": "string", + "role": "style", + "noBlank": true, + "strict": true, + "editType": "plot", + "description": "HTML font family - the typeface that will be applied by the web browser. The web browser will only be able to apply a font if it is available on the system which it operates. Provide multiple font families, separated by commas, to indicate the preference in which to apply fonts if they aren't available on the system. The plotly service (at https://plot.ly or on-premise) generates images on a server, where only a select number of fonts are installed and supported. These include *Arial*, *Balto*, *Courier New*, *Droid Sans*,, *Droid Serif*, *Droid Sans Mono*, *Gravitas One*, *Old Standard TT*, *Open Sans*, *Overpass*, *PT Sans Narrow*, *Raleway*, *Times New Roman*." + }, + "size": { + "valType": "number", + "role": "style", + "min": 1, + "editType": "plot" + }, + "color": { + "valType": "color", + "role": "style", + "editType": "plot" + }, + "editType": "plot", + "description": "Sets this axis' title font.", + "role": "object" + }, + "type": { + "valType": "enumerated", + "values": [ + "-", + "linear", + "log", + "date", + "category" + ], + "dflt": "-", + "role": "info", + "editType": "plot", + "description": "Sets the axis type. By default, plotly attempts to determined the axis type by looking into the data of the traces that referenced the axis in question." + }, + "autorange": { + "valType": "enumerated", + "values": [ + true, + false, + "reversed" + ], + "dflt": true, + "role": "style", + "editType": "plot", + "impliedEdits": {}, + "description": "Determines whether or not the range of this axis is computed in relation to the input data. See `rangemode` for more info. If `range` is provided, then `autorange` is set to *false*." + }, + "rangemode": { + "valType": "enumerated", + "values": [ + "normal", + "tozero", + "nonnegative" + ], + "dflt": "normal", + "role": "style", + "editType": "plot", + "description": "If *normal*, the range is computed in relation to the extrema of the input data. If *tozero*`, the range extends to 0, regardless of the input data If *nonnegative*, the range is non-negative, regardless of the input data." + }, + "range": { + "valType": "info_array", + "role": "info", + "items": [ + { + "valType": "any", + "editType": "plot", + "impliedEdits": { + "^autorange": false + } + }, + { + "valType": "any", + "editType": "plot", + "impliedEdits": { + "^autorange": false + } + } + ], + "editType": "plot", + "impliedEdits": { + "autorange": false + }, + "description": "Sets the range of this axis. If the axis `type` is *log*, then you must take the log of your desired range (e.g. to set the range from 1 to 100, set the range from 0 to 2). If the axis `type` is *date*, it should be date strings, like date data, though Date objects and unix milliseconds will be accepted and converted to strings. If the axis `type` is *category*, it should be numbers, using the scale where each category is assigned a serial number from zero in the order it appears." + }, + "tickmode": { + "valType": "enumerated", + "values": [ + "auto", + "linear", + "array" + ], + "role": "info", + "editType": "plot", + "impliedEdits": {}, + "description": "Sets the tick mode for this axis. If *auto*, the number of ticks is set via `nticks`. If *linear*, the placement of the ticks is determined by a starting position `tick0` and a tick step `dtick` (*linear* is the default value if `tick0` and `dtick` are provided). If *array*, the placement of the ticks is set via `tickvals` and the tick text is `ticktext`. (*array* is the default value if `tickvals` is provided)." + }, + "nticks": { + "valType": "integer", + "min": 0, + "dflt": 0, + "role": "style", + "editType": "plot", + "description": "Specifies the maximum number of ticks for the particular axis. The actual number of ticks will be chosen automatically to be less than or equal to `nticks`. Has an effect only if `tickmode` is set to *auto*." + }, + "tick0": { + "valType": "any", + "role": "style", + "editType": "plot", + "impliedEdits": { + "tickmode": "linear" + }, + "description": "Sets the placement of the first tick on this axis. Use with `dtick`. If the axis `type` is *log*, then you must take the log of your starting tick (e.g. to set the starting tick to 100, set the `tick0` to 2) except when `dtick`=*L* (see `dtick` for more info). If the axis `type` is *date*, it should be a date string, like date data. If the axis `type` is *category*, it should be a number, using the scale where each category is assigned a serial number from zero in the order it appears." + }, + "dtick": { + "valType": "any", + "role": "style", + "editType": "plot", + "impliedEdits": { + "tickmode": "linear" + }, + "description": "Sets the step in-between ticks on this axis. Use with `tick0`. Must be a positive number, or special strings available to *log* and *date* axes. If the axis `type` is *log*, then ticks are set every 10^(n*dtick) where n is the tick number. For example, to set a tick mark at 1, 10, 100, 1000, ... set dtick to 1. To set tick marks at 1, 100, 10000, ... set dtick to 2. To set tick marks at 1, 5, 25, 125, 625, 3125, ... set dtick to log_10(5), or 0.69897000433. *log* has several special values; *L*, where `f` is a positive number, gives ticks linearly spaced in value (but not position). For example `tick0` = 0.1, `dtick` = *L0.5* will put ticks at 0.1, 0.6, 1.1, 1.6 etc. To show powers of 10 plus small digits between, use *D1* (all digits) or *D2* (only 2 and 5). `tick0` is ignored for *D1* and *D2*. If the axis `type` is *date*, then you must convert the time to milliseconds. For example, to set the interval between ticks to one day, set `dtick` to 86400000.0. *date* also has special values *M* gives ticks spaced by a number of months. `n` must be a positive integer. To set ticks on the 15th of every third month, set `tick0` to *2000-01-15* and `dtick` to *M3*. To set ticks every 4 years, set `dtick` to *M48*" + }, + "tickvals": { + "valType": "data_array", + "editType": "plot", + "description": "Sets the values at which ticks on this axis appear. Only has an effect if `tickmode` is set to *array*. Used with `ticktext`.", + "role": "data" + }, + "ticktext": { + "valType": "data_array", + "editType": "plot", + "description": "Sets the text displayed at the ticks position via `tickvals`. Only has an effect if `tickmode` is set to *array*. Used with `tickvals`.", + "role": "data" + }, + "ticks": { + "valType": "enumerated", + "values": [ + "outside", + "inside", + "" + ], + "role": "style", + "editType": "plot", + "description": "Determines whether ticks are drawn or not. If **, this axis' ticks are not drawn. If *outside* (*inside*), this axis' are drawn outside (inside) the axis lines." + }, + "mirror": { + "valType": "enumerated", + "values": [ + true, + "ticks", + false, + "all", + "allticks" + ], + "dflt": false, + "role": "style", + "editType": "plot", + "description": "Determines if the axis lines or/and ticks are mirrored to the opposite side of the plotting area. If *true*, the axis lines are mirrored. If *ticks*, the axis lines and ticks are mirrored. If *false*, mirroring is disable. If *all*, axis lines are mirrored on all shared-axes subplots. If *allticks*, axis lines and ticks are mirrored on all shared-axes subplots." + }, + "ticklen": { + "valType": "number", + "min": 0, + "dflt": 5, + "role": "style", + "editType": "plot", + "description": "Sets the tick length (in px)." + }, + "tickwidth": { + "valType": "number", + "min": 0, + "dflt": 1, + "role": "style", + "editType": "plot", + "description": "Sets the tick width (in px)." + }, + "tickcolor": { + "valType": "color", + "dflt": "#444", + "role": "style", + "editType": "plot", + "description": "Sets the tick color." + }, + "showticklabels": { + "valType": "boolean", + "dflt": true, + "role": "style", + "editType": "plot", + "description": "Determines whether or not the tick labels are drawn." + }, + "tickfont": { + "family": { + "valType": "string", + "role": "style", + "noBlank": true, + "strict": true, + "editType": "plot", + "description": "HTML font family - the typeface that will be applied by the web browser. The web browser will only be able to apply a font if it is available on the system which it operates. Provide multiple font families, separated by commas, to indicate the preference in which to apply fonts if they aren't available on the system. The plotly service (at https://plot.ly or on-premise) generates images on a server, where only a select number of fonts are installed and supported. These include *Arial*, *Balto*, *Courier New*, *Droid Sans*,, *Droid Serif*, *Droid Sans Mono*, *Gravitas One*, *Old Standard TT*, *Open Sans*, *Overpass*, *PT Sans Narrow*, *Raleway*, *Times New Roman*." + }, + "size": { + "valType": "number", + "role": "style", + "min": 1, + "editType": "plot" + }, + "color": { + "valType": "color", + "role": "style", + "editType": "plot" + }, + "editType": "plot", + "description": "Sets the tick font.", + "role": "object" + }, + "tickangle": { + "valType": "angle", + "dflt": "auto", + "role": "style", + "editType": "plot", + "description": "Sets the angle of the tick labels with respect to the horizontal. For example, a `tickangle` of -90 draws the tick labels vertically." + }, + "tickprefix": { + "valType": "string", + "dflt": "", + "role": "style", + "editType": "plot", + "description": "Sets a tick label prefix." + }, + "showtickprefix": { + "valType": "enumerated", + "values": [ + "all", + "first", + "last", + "none" + ], + "dflt": "all", + "role": "style", + "editType": "plot", + "description": "If *all*, all tick labels are displayed with a prefix. If *first*, only the first tick is displayed with a prefix. If *last*, only the last tick is displayed with a suffix. If *none*, tick prefixes are hidden." + }, + "ticksuffix": { + "valType": "string", + "dflt": "", + "role": "style", + "editType": "plot", + "description": "Sets a tick label suffix." + }, + "showticksuffix": { + "valType": "enumerated", + "values": [ + "all", + "first", + "last", + "none" + ], + "dflt": "all", + "role": "style", + "editType": "plot", + "description": "Same as `showtickprefix` but for tick suffixes." + }, + "showexponent": { + "valType": "enumerated", + "values": [ + "all", + "first", + "last", + "none" + ], + "dflt": "all", + "role": "style", + "editType": "plot", + "description": "If *all*, all exponents are shown besides their significands. If *first*, only the exponent of the first tick is shown. If *last*, only the exponent of the last tick is shown. If *none*, no exponents appear." + }, + "exponentformat": { + "valType": "enumerated", + "values": [ + "none", + "e", + "E", + "power", + "SI", + "B" + ], + "dflt": "B", + "role": "style", + "editType": "plot", + "description": "Determines a formatting rule for the tick exponents. For example, consider the number 1,000,000,000. If *none*, it appears as 1,000,000,000. If *e*, 1e+9. If *E*, 1E+9. If *power*, 1x10^9 (with 9 in a super script). If *SI*, 1G. If *B*, 1B." + }, + "separatethousands": { + "valType": "boolean", + "dflt": false, + "role": "style", + "editType": "plot", + "description": "If \"true\", even 4-digit integers are separated" + }, + "tickformat": { + "valType": "string", + "dflt": "", + "role": "style", + "editType": "plot", + "description": "Sets the tick label formatting rule using d3 formatting mini-languages which are very similar to those in Python. For numbers, see: https://github.com/d3/d3-format/blob/master/README.md#locale_format And for dates see: https://github.com/d3/d3-time-format/blob/master/README.md#locale_format We add one item to d3's date formatter: *%{n}f* for fractional seconds with n digits. For example, *2016-10-13 09:15:23.456* with tickformat *%H~%M~%S.%2f* would display *09~15~23.46*" + }, + "tickformatstops": { + "items": { + "tickformatstop": { + "dtickrange": { + "valType": "info_array", + "role": "info", + "items": [ + { + "valType": "any", + "editType": "plot" + }, + { + "valType": "any", + "editType": "plot" + } + ], + "editType": "plot", + "description": "range [*min*, *max*], where *min*, *max* - dtick values which describe some zoom level, it is possible to omit *min* or *max* value by passing *null*" + }, + "value": { + "valType": "string", + "dflt": "", + "role": "style", + "editType": "plot", + "description": "string - dtickformat for described zoom level, the same as *tickformat*" + }, + "editType": "plot", + "role": "object" + } + }, + "role": "object" + }, + "hoverformat": { + "valType": "string", + "dflt": "", + "role": "style", + "editType": "plot", + "description": "Sets the hover text formatting rule using d3 formatting mini-languages which are very similar to those in Python. For numbers, see: https://github.com/d3/d3-format/blob/master/README.md#locale_format And for dates see: https://github.com/d3/d3-time-format/blob/master/README.md#locale_format We add one item to d3's date formatter: *%{n}f* for fractional seconds with n digits. For example, *2016-10-13 09:15:23.456* with tickformat *%H~%M~%S.%2f* would display *09~15~23.46*" + }, + "showline": { + "valType": "boolean", + "dflt": false, + "role": "style", + "editType": "plot", + "description": "Determines whether or not a line bounding this axis is drawn." + }, + "linecolor": { + "valType": "color", + "dflt": "#444", + "role": "style", + "editType": "plot", + "description": "Sets the axis line color." + }, + "linewidth": { + "valType": "number", + "min": 0, + "dflt": 1, + "role": "style", + "editType": "plot", + "description": "Sets the width (in px) of the axis line." + }, + "showgrid": { + "valType": "boolean", + "role": "style", + "editType": "plot", + "description": "Determines whether or not grid lines are drawn. If *true*, the grid lines are drawn at every tick mark." + }, + "gridcolor": { + "valType": "color", + "dflt": "rgb(204, 204, 204)", + "role": "style", + "editType": "plot", + "description": "Sets the color of the grid lines." + }, + "gridwidth": { + "valType": "number", + "min": 0, + "dflt": 1, + "role": "style", + "editType": "plot", + "description": "Sets the width (in px) of the grid lines." + }, + "zeroline": { + "valType": "boolean", + "role": "style", + "editType": "plot", + "description": "Determines whether or not a line is drawn at along the 0 value of this axis. If *true*, the zero line is drawn on top of the grid lines." + }, + "zerolinecolor": { + "valType": "color", + "dflt": "#444", + "role": "style", + "editType": "plot", + "description": "Sets the line color of the zero line." + }, + "zerolinewidth": { + "valType": "number", + "dflt": 1, + "role": "style", + "editType": "plot", + "description": "Sets the width (in px) of the zero line." + }, + "editType": "plot", + "calendar": { + "valType": "enumerated", + "values": [ + "gregorian", + "chinese", + "coptic", + "discworld", + "ethiopian", + "hebrew", + "islamic", + "julian", + "mayan", + "nanakshahi", + "nepali", + "persian", + "jalali", + "taiwan", + "thai", + "ummalqura" + ], + "role": "info", + "editType": "calc", + "dflt": "gregorian", + "description": "Sets the calendar system to use for `range` and `tick0` if this is a date axis. This does not set the calendar for interpreting data on this axis, that's specified in the trace or via the global `layout.calendar`" + }, + "role": "object", + "categoryarraysrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for categoryarray .", + "editType": "none" + }, + "tickvalssrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for tickvals .", + "editType": "none" + }, + "ticktextsrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for ticktext .", + "editType": "none" + } + }, + "yaxis": { + "visible": { + "valType": "boolean", + "role": "info", + "editType": "plot", + "description": "A single toggle to hide the axis while preserving interaction like dragging. Default is true when a cheater plot is present on the axis, otherwise false" + }, + "showspikes": { + "valType": "boolean", + "role": "info", + "dflt": true, + "description": "Sets whether or not spikes starting from data points to this axis' wall are shown on hover.", + "editType": "plot" + }, + "spikesides": { + "valType": "boolean", + "role": "info", + "dflt": true, + "description": "Sets whether or not spikes extending from the projection data points to this axis' wall boundaries are shown on hover.", + "editType": "plot" + }, + "spikethickness": { + "valType": "number", + "role": "style", + "min": 0, + "dflt": 2, + "description": "Sets the thickness (in px) of the spikes.", + "editType": "plot" + }, + "spikecolor": { + "valType": "color", + "role": "style", + "dflt": "#444", + "description": "Sets the color of the spikes.", + "editType": "plot" + }, + "showbackground": { + "valType": "boolean", + "role": "info", + "dflt": false, + "description": "Sets whether or not this axis' wall has a background color.", + "editType": "plot" + }, + "backgroundcolor": { + "valType": "color", + "role": "style", + "dflt": "rgba(204, 204, 204, 0.5)", + "description": "Sets the background color of this axis' wall.", + "editType": "plot" + }, + "showaxeslabels": { + "valType": "boolean", + "role": "info", + "dflt": true, + "description": "Sets whether or not this axis is labeled", + "editType": "plot" + }, + "color": { + "valType": "color", + "dflt": "#444", + "role": "style", + "editType": "plot", + "description": "Sets default for all colors associated with this axis all at once: line, font, tick, and grid colors. Grid color is lightened by blending this with the plot background Individual pieces can override this." + }, + "categoryorder": { + "valType": "enumerated", + "values": [ + "trace", + "category ascending", + "category descending", + "array" + ], + "dflt": "trace", + "role": "info", + "editType": "plot", + "description": "Specifies the ordering logic for the case of categorical variables. By default, plotly uses *trace*, which specifies the order that is present in the data supplied. Set `categoryorder` to *category ascending* or *category descending* if order should be determined by the alphanumerical order of the category names. Set `categoryorder` to *array* to derive the ordering from the attribute `categoryarray`. If a category is not found in the `categoryarray` array, the sorting behavior for that attribute will be identical to the *trace* mode. The unspecified categories will follow the categories in `categoryarray`." + }, + "categoryarray": { + "valType": "data_array", + "role": "data", + "editType": "plot", + "description": "Sets the order in which categories on this axis appear. Only has an effect if `categoryorder` is set to *array*. Used with `categoryorder`." + }, + "title": { + "valType": "string", + "role": "info", + "editType": "plot", + "description": "Sets the title of this axis." + }, + "titlefont": { + "family": { + "valType": "string", + "role": "style", + "noBlank": true, + "strict": true, + "editType": "plot", + "description": "HTML font family - the typeface that will be applied by the web browser. The web browser will only be able to apply a font if it is available on the system which it operates. Provide multiple font families, separated by commas, to indicate the preference in which to apply fonts if they aren't available on the system. The plotly service (at https://plot.ly or on-premise) generates images on a server, where only a select number of fonts are installed and supported. These include *Arial*, *Balto*, *Courier New*, *Droid Sans*,, *Droid Serif*, *Droid Sans Mono*, *Gravitas One*, *Old Standard TT*, *Open Sans*, *Overpass*, *PT Sans Narrow*, *Raleway*, *Times New Roman*." + }, + "size": { + "valType": "number", + "role": "style", + "min": 1, + "editType": "plot" + }, + "color": { + "valType": "color", + "role": "style", + "editType": "plot" + }, + "editType": "plot", + "description": "Sets this axis' title font.", + "role": "object" + }, + "type": { + "valType": "enumerated", + "values": [ + "-", + "linear", + "log", + "date", + "category" + ], + "dflt": "-", + "role": "info", + "editType": "plot", + "description": "Sets the axis type. By default, plotly attempts to determined the axis type by looking into the data of the traces that referenced the axis in question." + }, + "autorange": { + "valType": "enumerated", + "values": [ + true, + false, + "reversed" + ], + "dflt": true, + "role": "style", + "editType": "plot", + "impliedEdits": {}, + "description": "Determines whether or not the range of this axis is computed in relation to the input data. See `rangemode` for more info. If `range` is provided, then `autorange` is set to *false*." + }, + "rangemode": { + "valType": "enumerated", + "values": [ + "normal", + "tozero", + "nonnegative" + ], + "dflt": "normal", + "role": "style", + "editType": "plot", + "description": "If *normal*, the range is computed in relation to the extrema of the input data. If *tozero*`, the range extends to 0, regardless of the input data If *nonnegative*, the range is non-negative, regardless of the input data." + }, + "range": { + "valType": "info_array", + "role": "info", + "items": [ + { + "valType": "any", + "editType": "plot", + "impliedEdits": { + "^autorange": false + } + }, + { + "valType": "any", + "editType": "plot", + "impliedEdits": { + "^autorange": false + } + } + ], + "editType": "plot", + "impliedEdits": { + "autorange": false + }, + "description": "Sets the range of this axis. If the axis `type` is *log*, then you must take the log of your desired range (e.g. to set the range from 1 to 100, set the range from 0 to 2). If the axis `type` is *date*, it should be date strings, like date data, though Date objects and unix milliseconds will be accepted and converted to strings. If the axis `type` is *category*, it should be numbers, using the scale where each category is assigned a serial number from zero in the order it appears." + }, + "tickmode": { + "valType": "enumerated", + "values": [ + "auto", + "linear", + "array" + ], + "role": "info", + "editType": "plot", + "impliedEdits": {}, + "description": "Sets the tick mode for this axis. If *auto*, the number of ticks is set via `nticks`. If *linear*, the placement of the ticks is determined by a starting position `tick0` and a tick step `dtick` (*linear* is the default value if `tick0` and `dtick` are provided). If *array*, the placement of the ticks is set via `tickvals` and the tick text is `ticktext`. (*array* is the default value if `tickvals` is provided)." + }, + "nticks": { + "valType": "integer", + "min": 0, + "dflt": 0, + "role": "style", + "editType": "plot", + "description": "Specifies the maximum number of ticks for the particular axis. The actual number of ticks will be chosen automatically to be less than or equal to `nticks`. Has an effect only if `tickmode` is set to *auto*." + }, + "tick0": { + "valType": "any", + "role": "style", + "editType": "plot", + "impliedEdits": { + "tickmode": "linear" + }, + "description": "Sets the placement of the first tick on this axis. Use with `dtick`. If the axis `type` is *log*, then you must take the log of your starting tick (e.g. to set the starting tick to 100, set the `tick0` to 2) except when `dtick`=*L* (see `dtick` for more info). If the axis `type` is *date*, it should be a date string, like date data. If the axis `type` is *category*, it should be a number, using the scale where each category is assigned a serial number from zero in the order it appears." + }, + "dtick": { + "valType": "any", + "role": "style", + "editType": "plot", + "impliedEdits": { + "tickmode": "linear" + }, + "description": "Sets the step in-between ticks on this axis. Use with `tick0`. Must be a positive number, or special strings available to *log* and *date* axes. If the axis `type` is *log*, then ticks are set every 10^(n*dtick) where n is the tick number. For example, to set a tick mark at 1, 10, 100, 1000, ... set dtick to 1. To set tick marks at 1, 100, 10000, ... set dtick to 2. To set tick marks at 1, 5, 25, 125, 625, 3125, ... set dtick to log_10(5), or 0.69897000433. *log* has several special values; *L*, where `f` is a positive number, gives ticks linearly spaced in value (but not position). For example `tick0` = 0.1, `dtick` = *L0.5* will put ticks at 0.1, 0.6, 1.1, 1.6 etc. To show powers of 10 plus small digits between, use *D1* (all digits) or *D2* (only 2 and 5). `tick0` is ignored for *D1* and *D2*. If the axis `type` is *date*, then you must convert the time to milliseconds. For example, to set the interval between ticks to one day, set `dtick` to 86400000.0. *date* also has special values *M* gives ticks spaced by a number of months. `n` must be a positive integer. To set ticks on the 15th of every third month, set `tick0` to *2000-01-15* and `dtick` to *M3*. To set ticks every 4 years, set `dtick` to *M48*" + }, + "tickvals": { + "valType": "data_array", + "editType": "plot", + "description": "Sets the values at which ticks on this axis appear. Only has an effect if `tickmode` is set to *array*. Used with `ticktext`.", + "role": "data" + }, + "ticktext": { + "valType": "data_array", + "editType": "plot", + "description": "Sets the text displayed at the ticks position via `tickvals`. Only has an effect if `tickmode` is set to *array*. Used with `tickvals`.", + "role": "data" + }, + "ticks": { + "valType": "enumerated", + "values": [ + "outside", + "inside", + "" + ], + "role": "style", + "editType": "plot", + "description": "Determines whether ticks are drawn or not. If **, this axis' ticks are not drawn. If *outside* (*inside*), this axis' are drawn outside (inside) the axis lines." + }, + "mirror": { + "valType": "enumerated", + "values": [ + true, + "ticks", + false, + "all", + "allticks" + ], + "dflt": false, + "role": "style", + "editType": "plot", + "description": "Determines if the axis lines or/and ticks are mirrored to the opposite side of the plotting area. If *true*, the axis lines are mirrored. If *ticks*, the axis lines and ticks are mirrored. If *false*, mirroring is disable. If *all*, axis lines are mirrored on all shared-axes subplots. If *allticks*, axis lines and ticks are mirrored on all shared-axes subplots." + }, + "ticklen": { + "valType": "number", + "min": 0, + "dflt": 5, + "role": "style", + "editType": "plot", + "description": "Sets the tick length (in px)." + }, + "tickwidth": { + "valType": "number", + "min": 0, + "dflt": 1, + "role": "style", + "editType": "plot", + "description": "Sets the tick width (in px)." + }, + "tickcolor": { + "valType": "color", + "dflt": "#444", + "role": "style", + "editType": "plot", + "description": "Sets the tick color." + }, + "showticklabels": { + "valType": "boolean", + "dflt": true, + "role": "style", + "editType": "plot", + "description": "Determines whether or not the tick labels are drawn." + }, + "tickfont": { + "family": { + "valType": "string", + "role": "style", + "noBlank": true, + "strict": true, + "editType": "plot", + "description": "HTML font family - the typeface that will be applied by the web browser. The web browser will only be able to apply a font if it is available on the system which it operates. Provide multiple font families, separated by commas, to indicate the preference in which to apply fonts if they aren't available on the system. The plotly service (at https://plot.ly or on-premise) generates images on a server, where only a select number of fonts are installed and supported. These include *Arial*, *Balto*, *Courier New*, *Droid Sans*,, *Droid Serif*, *Droid Sans Mono*, *Gravitas One*, *Old Standard TT*, *Open Sans*, *Overpass*, *PT Sans Narrow*, *Raleway*, *Times New Roman*." + }, + "size": { + "valType": "number", + "role": "style", + "min": 1, + "editType": "plot" + }, + "color": { + "valType": "color", + "role": "style", + "editType": "plot" + }, + "editType": "plot", + "description": "Sets the tick font.", + "role": "object" + }, + "tickangle": { + "valType": "angle", + "dflt": "auto", + "role": "style", + "editType": "plot", + "description": "Sets the angle of the tick labels with respect to the horizontal. For example, a `tickangle` of -90 draws the tick labels vertically." + }, + "tickprefix": { + "valType": "string", + "dflt": "", + "role": "style", + "editType": "plot", + "description": "Sets a tick label prefix." + }, + "showtickprefix": { + "valType": "enumerated", + "values": [ + "all", + "first", + "last", + "none" + ], + "dflt": "all", + "role": "style", + "editType": "plot", + "description": "If *all*, all tick labels are displayed with a prefix. If *first*, only the first tick is displayed with a prefix. If *last*, only the last tick is displayed with a suffix. If *none*, tick prefixes are hidden." + }, + "ticksuffix": { + "valType": "string", + "dflt": "", + "role": "style", + "editType": "plot", + "description": "Sets a tick label suffix." + }, + "showticksuffix": { + "valType": "enumerated", + "values": [ + "all", + "first", + "last", + "none" + ], + "dflt": "all", + "role": "style", + "editType": "plot", + "description": "Same as `showtickprefix` but for tick suffixes." + }, + "showexponent": { + "valType": "enumerated", + "values": [ + "all", + "first", + "last", + "none" + ], + "dflt": "all", + "role": "style", + "editType": "plot", + "description": "If *all*, all exponents are shown besides their significands. If *first*, only the exponent of the first tick is shown. If *last*, only the exponent of the last tick is shown. If *none*, no exponents appear." + }, + "exponentformat": { + "valType": "enumerated", + "values": [ + "none", + "e", + "E", + "power", + "SI", + "B" + ], + "dflt": "B", + "role": "style", + "editType": "plot", + "description": "Determines a formatting rule for the tick exponents. For example, consider the number 1,000,000,000. If *none*, it appears as 1,000,000,000. If *e*, 1e+9. If *E*, 1E+9. If *power*, 1x10^9 (with 9 in a super script). If *SI*, 1G. If *B*, 1B." + }, + "separatethousands": { + "valType": "boolean", + "dflt": false, + "role": "style", + "editType": "plot", + "description": "If \"true\", even 4-digit integers are separated" + }, + "tickformat": { + "valType": "string", + "dflt": "", + "role": "style", + "editType": "plot", + "description": "Sets the tick label formatting rule using d3 formatting mini-languages which are very similar to those in Python. For numbers, see: https://github.com/d3/d3-format/blob/master/README.md#locale_format And for dates see: https://github.com/d3/d3-time-format/blob/master/README.md#locale_format We add one item to d3's date formatter: *%{n}f* for fractional seconds with n digits. For example, *2016-10-13 09:15:23.456* with tickformat *%H~%M~%S.%2f* would display *09~15~23.46*" + }, + "tickformatstops": { + "items": { + "tickformatstop": { + "dtickrange": { + "valType": "info_array", + "role": "info", + "items": [ + { + "valType": "any", + "editType": "plot" + }, + { + "valType": "any", + "editType": "plot" + } + ], + "editType": "plot", + "description": "range [*min*, *max*], where *min*, *max* - dtick values which describe some zoom level, it is possible to omit *min* or *max* value by passing *null*" + }, + "value": { + "valType": "string", + "dflt": "", + "role": "style", + "editType": "plot", + "description": "string - dtickformat for described zoom level, the same as *tickformat*" + }, + "editType": "plot", + "role": "object" + } + }, + "role": "object" + }, + "hoverformat": { + "valType": "string", + "dflt": "", + "role": "style", + "editType": "plot", + "description": "Sets the hover text formatting rule using d3 formatting mini-languages which are very similar to those in Python. For numbers, see: https://github.com/d3/d3-format/blob/master/README.md#locale_format And for dates see: https://github.com/d3/d3-time-format/blob/master/README.md#locale_format We add one item to d3's date formatter: *%{n}f* for fractional seconds with n digits. For example, *2016-10-13 09:15:23.456* with tickformat *%H~%M~%S.%2f* would display *09~15~23.46*" + }, + "showline": { + "valType": "boolean", + "dflt": false, + "role": "style", + "editType": "plot", + "description": "Determines whether or not a line bounding this axis is drawn." + }, + "linecolor": { + "valType": "color", + "dflt": "#444", + "role": "style", + "editType": "plot", + "description": "Sets the axis line color." + }, + "linewidth": { + "valType": "number", + "min": 0, + "dflt": 1, + "role": "style", + "editType": "plot", + "description": "Sets the width (in px) of the axis line." + }, + "showgrid": { + "valType": "boolean", + "role": "style", + "editType": "plot", + "description": "Determines whether or not grid lines are drawn. If *true*, the grid lines are drawn at every tick mark." + }, + "gridcolor": { + "valType": "color", + "dflt": "rgb(204, 204, 204)", + "role": "style", + "editType": "plot", + "description": "Sets the color of the grid lines." + }, + "gridwidth": { + "valType": "number", + "min": 0, + "dflt": 1, + "role": "style", + "editType": "plot", + "description": "Sets the width (in px) of the grid lines." + }, + "zeroline": { + "valType": "boolean", + "role": "style", + "editType": "plot", + "description": "Determines whether or not a line is drawn at along the 0 value of this axis. If *true*, the zero line is drawn on top of the grid lines." + }, + "zerolinecolor": { + "valType": "color", + "dflt": "#444", + "role": "style", + "editType": "plot", + "description": "Sets the line color of the zero line." + }, + "zerolinewidth": { + "valType": "number", + "dflt": 1, + "role": "style", + "editType": "plot", + "description": "Sets the width (in px) of the zero line." + }, + "editType": "plot", + "calendar": { + "valType": "enumerated", + "values": [ + "gregorian", + "chinese", + "coptic", + "discworld", + "ethiopian", + "hebrew", + "islamic", + "julian", + "mayan", + "nanakshahi", + "nepali", + "persian", + "jalali", + "taiwan", + "thai", + "ummalqura" + ], + "role": "info", + "editType": "calc", + "dflt": "gregorian", + "description": "Sets the calendar system to use for `range` and `tick0` if this is a date axis. This does not set the calendar for interpreting data on this axis, that's specified in the trace or via the global `layout.calendar`" + }, + "role": "object", + "categoryarraysrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for categoryarray .", + "editType": "none" + }, + "tickvalssrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for tickvals .", + "editType": "none" + }, + "ticktextsrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for ticktext .", + "editType": "none" + } + }, + "zaxis": { + "visible": { + "valType": "boolean", + "role": "info", + "editType": "plot", + "description": "A single toggle to hide the axis while preserving interaction like dragging. Default is true when a cheater plot is present on the axis, otherwise false" + }, + "showspikes": { + "valType": "boolean", + "role": "info", + "dflt": true, + "description": "Sets whether or not spikes starting from data points to this axis' wall are shown on hover.", + "editType": "plot" + }, + "spikesides": { + "valType": "boolean", + "role": "info", + "dflt": true, + "description": "Sets whether or not spikes extending from the projection data points to this axis' wall boundaries are shown on hover.", + "editType": "plot" + }, + "spikethickness": { + "valType": "number", + "role": "style", + "min": 0, + "dflt": 2, + "description": "Sets the thickness (in px) of the spikes.", + "editType": "plot" + }, + "spikecolor": { + "valType": "color", + "role": "style", + "dflt": "#444", + "description": "Sets the color of the spikes.", + "editType": "plot" + }, + "showbackground": { + "valType": "boolean", + "role": "info", + "dflt": false, + "description": "Sets whether or not this axis' wall has a background color.", + "editType": "plot" + }, + "backgroundcolor": { + "valType": "color", + "role": "style", + "dflt": "rgba(204, 204, 204, 0.5)", + "description": "Sets the background color of this axis' wall.", + "editType": "plot" + }, + "showaxeslabels": { + "valType": "boolean", + "role": "info", + "dflt": true, + "description": "Sets whether or not this axis is labeled", + "editType": "plot" + }, + "color": { + "valType": "color", + "dflt": "#444", + "role": "style", + "editType": "plot", + "description": "Sets default for all colors associated with this axis all at once: line, font, tick, and grid colors. Grid color is lightened by blending this with the plot background Individual pieces can override this." + }, + "categoryorder": { + "valType": "enumerated", + "values": [ + "trace", + "category ascending", + "category descending", + "array" + ], + "dflt": "trace", + "role": "info", + "editType": "plot", + "description": "Specifies the ordering logic for the case of categorical variables. By default, plotly uses *trace*, which specifies the order that is present in the data supplied. Set `categoryorder` to *category ascending* or *category descending* if order should be determined by the alphanumerical order of the category names. Set `categoryorder` to *array* to derive the ordering from the attribute `categoryarray`. If a category is not found in the `categoryarray` array, the sorting behavior for that attribute will be identical to the *trace* mode. The unspecified categories will follow the categories in `categoryarray`." + }, + "categoryarray": { + "valType": "data_array", + "role": "data", + "editType": "plot", + "description": "Sets the order in which categories on this axis appear. Only has an effect if `categoryorder` is set to *array*. Used with `categoryorder`." + }, + "title": { + "valType": "string", + "role": "info", + "editType": "plot", + "description": "Sets the title of this axis." + }, + "titlefont": { + "family": { + "valType": "string", + "role": "style", + "noBlank": true, + "strict": true, + "editType": "plot", + "description": "HTML font family - the typeface that will be applied by the web browser. The web browser will only be able to apply a font if it is available on the system which it operates. Provide multiple font families, separated by commas, to indicate the preference in which to apply fonts if they aren't available on the system. The plotly service (at https://plot.ly or on-premise) generates images on a server, where only a select number of fonts are installed and supported. These include *Arial*, *Balto*, *Courier New*, *Droid Sans*,, *Droid Serif*, *Droid Sans Mono*, *Gravitas One*, *Old Standard TT*, *Open Sans*, *Overpass*, *PT Sans Narrow*, *Raleway*, *Times New Roman*." + }, + "size": { + "valType": "number", + "role": "style", + "min": 1, + "editType": "plot" + }, + "color": { + "valType": "color", + "role": "style", + "editType": "plot" + }, + "editType": "plot", + "description": "Sets this axis' title font.", + "role": "object" + }, + "type": { + "valType": "enumerated", + "values": [ + "-", + "linear", + "log", + "date", + "category" + ], + "dflt": "-", + "role": "info", + "editType": "plot", + "description": "Sets the axis type. By default, plotly attempts to determined the axis type by looking into the data of the traces that referenced the axis in question." + }, + "autorange": { + "valType": "enumerated", + "values": [ + true, + false, + "reversed" + ], + "dflt": true, + "role": "style", + "editType": "plot", + "impliedEdits": {}, + "description": "Determines whether or not the range of this axis is computed in relation to the input data. See `rangemode` for more info. If `range` is provided, then `autorange` is set to *false*." + }, + "rangemode": { + "valType": "enumerated", + "values": [ + "normal", + "tozero", + "nonnegative" + ], + "dflt": "normal", + "role": "style", + "editType": "plot", + "description": "If *normal*, the range is computed in relation to the extrema of the input data. If *tozero*`, the range extends to 0, regardless of the input data If *nonnegative*, the range is non-negative, regardless of the input data." + }, + "range": { + "valType": "info_array", + "role": "info", + "items": [ + { + "valType": "any", + "editType": "plot", + "impliedEdits": { + "^autorange": false + } + }, + { + "valType": "any", + "editType": "plot", + "impliedEdits": { + "^autorange": false + } + } + ], + "editType": "plot", + "impliedEdits": { + "autorange": false + }, + "description": "Sets the range of this axis. If the axis `type` is *log*, then you must take the log of your desired range (e.g. to set the range from 1 to 100, set the range from 0 to 2). If the axis `type` is *date*, it should be date strings, like date data, though Date objects and unix milliseconds will be accepted and converted to strings. If the axis `type` is *category*, it should be numbers, using the scale where each category is assigned a serial number from zero in the order it appears." + }, + "tickmode": { + "valType": "enumerated", + "values": [ + "auto", + "linear", + "array" + ], + "role": "info", + "editType": "plot", + "impliedEdits": {}, + "description": "Sets the tick mode for this axis. If *auto*, the number of ticks is set via `nticks`. If *linear*, the placement of the ticks is determined by a starting position `tick0` and a tick step `dtick` (*linear* is the default value if `tick0` and `dtick` are provided). If *array*, the placement of the ticks is set via `tickvals` and the tick text is `ticktext`. (*array* is the default value if `tickvals` is provided)." + }, + "nticks": { + "valType": "integer", + "min": 0, + "dflt": 0, + "role": "style", + "editType": "plot", + "description": "Specifies the maximum number of ticks for the particular axis. The actual number of ticks will be chosen automatically to be less than or equal to `nticks`. Has an effect only if `tickmode` is set to *auto*." + }, + "tick0": { + "valType": "any", + "role": "style", + "editType": "plot", + "impliedEdits": { + "tickmode": "linear" + }, + "description": "Sets the placement of the first tick on this axis. Use with `dtick`. If the axis `type` is *log*, then you must take the log of your starting tick (e.g. to set the starting tick to 100, set the `tick0` to 2) except when `dtick`=*L* (see `dtick` for more info). If the axis `type` is *date*, it should be a date string, like date data. If the axis `type` is *category*, it should be a number, using the scale where each category is assigned a serial number from zero in the order it appears." + }, + "dtick": { + "valType": "any", + "role": "style", + "editType": "plot", + "impliedEdits": { + "tickmode": "linear" + }, + "description": "Sets the step in-between ticks on this axis. Use with `tick0`. Must be a positive number, or special strings available to *log* and *date* axes. If the axis `type` is *log*, then ticks are set every 10^(n*dtick) where n is the tick number. For example, to set a tick mark at 1, 10, 100, 1000, ... set dtick to 1. To set tick marks at 1, 100, 10000, ... set dtick to 2. To set tick marks at 1, 5, 25, 125, 625, 3125, ... set dtick to log_10(5), or 0.69897000433. *log* has several special values; *L*, where `f` is a positive number, gives ticks linearly spaced in value (but not position). For example `tick0` = 0.1, `dtick` = *L0.5* will put ticks at 0.1, 0.6, 1.1, 1.6 etc. To show powers of 10 plus small digits between, use *D1* (all digits) or *D2* (only 2 and 5). `tick0` is ignored for *D1* and *D2*. If the axis `type` is *date*, then you must convert the time to milliseconds. For example, to set the interval between ticks to one day, set `dtick` to 86400000.0. *date* also has special values *M* gives ticks spaced by a number of months. `n` must be a positive integer. To set ticks on the 15th of every third month, set `tick0` to *2000-01-15* and `dtick` to *M3*. To set ticks every 4 years, set `dtick` to *M48*" + }, + "tickvals": { + "valType": "data_array", + "editType": "plot", + "description": "Sets the values at which ticks on this axis appear. Only has an effect if `tickmode` is set to *array*. Used with `ticktext`.", + "role": "data" + }, + "ticktext": { + "valType": "data_array", + "editType": "plot", + "description": "Sets the text displayed at the ticks position via `tickvals`. Only has an effect if `tickmode` is set to *array*. Used with `tickvals`.", + "role": "data" + }, + "ticks": { + "valType": "enumerated", + "values": [ + "outside", + "inside", + "" + ], + "role": "style", + "editType": "plot", + "description": "Determines whether ticks are drawn or not. If **, this axis' ticks are not drawn. If *outside* (*inside*), this axis' are drawn outside (inside) the axis lines." + }, + "mirror": { + "valType": "enumerated", + "values": [ + true, + "ticks", + false, + "all", + "allticks" + ], + "dflt": false, + "role": "style", + "editType": "plot", + "description": "Determines if the axis lines or/and ticks are mirrored to the opposite side of the plotting area. If *true*, the axis lines are mirrored. If *ticks*, the axis lines and ticks are mirrored. If *false*, mirroring is disable. If *all*, axis lines are mirrored on all shared-axes subplots. If *allticks*, axis lines and ticks are mirrored on all shared-axes subplots." + }, + "ticklen": { + "valType": "number", + "min": 0, + "dflt": 5, + "role": "style", + "editType": "plot", + "description": "Sets the tick length (in px)." + }, + "tickwidth": { + "valType": "number", + "min": 0, + "dflt": 1, + "role": "style", + "editType": "plot", + "description": "Sets the tick width (in px)." + }, + "tickcolor": { + "valType": "color", + "dflt": "#444", + "role": "style", + "editType": "plot", + "description": "Sets the tick color." + }, + "showticklabels": { + "valType": "boolean", + "dflt": true, + "role": "style", + "editType": "plot", + "description": "Determines whether or not the tick labels are drawn." + }, + "tickfont": { + "family": { + "valType": "string", + "role": "style", + "noBlank": true, + "strict": true, + "editType": "plot", + "description": "HTML font family - the typeface that will be applied by the web browser. The web browser will only be able to apply a font if it is available on the system which it operates. Provide multiple font families, separated by commas, to indicate the preference in which to apply fonts if they aren't available on the system. The plotly service (at https://plot.ly or on-premise) generates images on a server, where only a select number of fonts are installed and supported. These include *Arial*, *Balto*, *Courier New*, *Droid Sans*,, *Droid Serif*, *Droid Sans Mono*, *Gravitas One*, *Old Standard TT*, *Open Sans*, *Overpass*, *PT Sans Narrow*, *Raleway*, *Times New Roman*." + }, + "size": { + "valType": "number", + "role": "style", + "min": 1, + "editType": "plot" + }, + "color": { + "valType": "color", + "role": "style", + "editType": "plot" + }, + "editType": "plot", + "description": "Sets the tick font.", + "role": "object" + }, + "tickangle": { + "valType": "angle", + "dflt": "auto", + "role": "style", + "editType": "plot", + "description": "Sets the angle of the tick labels with respect to the horizontal. For example, a `tickangle` of -90 draws the tick labels vertically." + }, + "tickprefix": { + "valType": "string", + "dflt": "", + "role": "style", + "editType": "plot", + "description": "Sets a tick label prefix." + }, + "showtickprefix": { + "valType": "enumerated", + "values": [ + "all", + "first", + "last", + "none" + ], + "dflt": "all", + "role": "style", + "editType": "plot", + "description": "If *all*, all tick labels are displayed with a prefix. If *first*, only the first tick is displayed with a prefix. If *last*, only the last tick is displayed with a suffix. If *none*, tick prefixes are hidden." + }, + "ticksuffix": { + "valType": "string", + "dflt": "", + "role": "style", + "editType": "plot", + "description": "Sets a tick label suffix." + }, + "showticksuffix": { + "valType": "enumerated", + "values": [ + "all", + "first", + "last", + "none" + ], + "dflt": "all", + "role": "style", + "editType": "plot", + "description": "Same as `showtickprefix` but for tick suffixes." + }, + "showexponent": { + "valType": "enumerated", + "values": [ + "all", + "first", + "last", + "none" + ], + "dflt": "all", + "role": "style", + "editType": "plot", + "description": "If *all*, all exponents are shown besides their significands. If *first*, only the exponent of the first tick is shown. If *last*, only the exponent of the last tick is shown. If *none*, no exponents appear." + }, + "exponentformat": { + "valType": "enumerated", + "values": [ + "none", + "e", + "E", + "power", + "SI", + "B" + ], + "dflt": "B", + "role": "style", + "editType": "plot", + "description": "Determines a formatting rule for the tick exponents. For example, consider the number 1,000,000,000. If *none*, it appears as 1,000,000,000. If *e*, 1e+9. If *E*, 1E+9. If *power*, 1x10^9 (with 9 in a super script). If *SI*, 1G. If *B*, 1B." + }, + "separatethousands": { + "valType": "boolean", + "dflt": false, + "role": "style", + "editType": "plot", + "description": "If \"true\", even 4-digit integers are separated" + }, + "tickformat": { + "valType": "string", + "dflt": "", + "role": "style", + "editType": "plot", + "description": "Sets the tick label formatting rule using d3 formatting mini-languages which are very similar to those in Python. For numbers, see: https://github.com/d3/d3-format/blob/master/README.md#locale_format And for dates see: https://github.com/d3/d3-time-format/blob/master/README.md#locale_format We add one item to d3's date formatter: *%{n}f* for fractional seconds with n digits. For example, *2016-10-13 09:15:23.456* with tickformat *%H~%M~%S.%2f* would display *09~15~23.46*" + }, + "tickformatstops": { + "items": { + "tickformatstop": { + "dtickrange": { + "valType": "info_array", + "role": "info", + "items": [ + { + "valType": "any", + "editType": "plot" + }, + { + "valType": "any", + "editType": "plot" + } + ], + "editType": "plot", + "description": "range [*min*, *max*], where *min*, *max* - dtick values which describe some zoom level, it is possible to omit *min* or *max* value by passing *null*" + }, + "value": { + "valType": "string", + "dflt": "", + "role": "style", + "editType": "plot", + "description": "string - dtickformat for described zoom level, the same as *tickformat*" + }, + "editType": "plot", + "role": "object" + } + }, + "role": "object" + }, + "hoverformat": { + "valType": "string", + "dflt": "", + "role": "style", + "editType": "plot", + "description": "Sets the hover text formatting rule using d3 formatting mini-languages which are very similar to those in Python. For numbers, see: https://github.com/d3/d3-format/blob/master/README.md#locale_format And for dates see: https://github.com/d3/d3-time-format/blob/master/README.md#locale_format We add one item to d3's date formatter: *%{n}f* for fractional seconds with n digits. For example, *2016-10-13 09:15:23.456* with tickformat *%H~%M~%S.%2f* would display *09~15~23.46*" + }, + "showline": { + "valType": "boolean", + "dflt": false, + "role": "style", + "editType": "plot", + "description": "Determines whether or not a line bounding this axis is drawn." + }, + "linecolor": { + "valType": "color", + "dflt": "#444", + "role": "style", + "editType": "plot", + "description": "Sets the axis line color." + }, + "linewidth": { + "valType": "number", + "min": 0, + "dflt": 1, + "role": "style", + "editType": "plot", + "description": "Sets the width (in px) of the axis line." + }, + "showgrid": { + "valType": "boolean", + "role": "style", + "editType": "plot", + "description": "Determines whether or not grid lines are drawn. If *true*, the grid lines are drawn at every tick mark." + }, + "gridcolor": { + "valType": "color", + "dflt": "rgb(204, 204, 204)", + "role": "style", + "editType": "plot", + "description": "Sets the color of the grid lines." + }, + "gridwidth": { + "valType": "number", + "min": 0, + "dflt": 1, + "role": "style", + "editType": "plot", + "description": "Sets the width (in px) of the grid lines." + }, + "zeroline": { + "valType": "boolean", + "role": "style", + "editType": "plot", + "description": "Determines whether or not a line is drawn at along the 0 value of this axis. If *true*, the zero line is drawn on top of the grid lines." + }, + "zerolinecolor": { + "valType": "color", + "dflt": "#444", + "role": "style", + "editType": "plot", + "description": "Sets the line color of the zero line." + }, + "zerolinewidth": { + "valType": "number", + "dflt": 1, + "role": "style", + "editType": "plot", + "description": "Sets the width (in px) of the zero line." + }, + "editType": "plot", + "calendar": { + "valType": "enumerated", + "values": [ + "gregorian", + "chinese", + "coptic", + "discworld", + "ethiopian", + "hebrew", + "islamic", + "julian", + "mayan", + "nanakshahi", + "nepali", + "persian", + "jalali", + "taiwan", + "thai", + "ummalqura" + ], + "role": "info", + "editType": "calc", + "dflt": "gregorian", + "description": "Sets the calendar system to use for `range` and `tick0` if this is a date axis. This does not set the calendar for interpreting data on this axis, that's specified in the trace or via the global `layout.calendar`" + }, + "role": "object", + "categoryarraysrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for categoryarray .", + "editType": "none" + }, + "tickvalssrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for tickvals .", + "editType": "none" + }, + "ticktextsrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for ticktext .", + "editType": "none" + } + }, + "dragmode": { + "valType": "enumerated", + "role": "info", + "values": [ + "orbit", + "turntable", + "zoom", + "pan", + false + ], + "dflt": "turntable", + "editType": "plot", + "description": "Determines the mode of drag interactions for this scene." + }, + "hovermode": { + "valType": "enumerated", + "role": "info", + "values": [ + "closest", + false + ], + "dflt": "closest", + "editType": "modebar", + "description": "Determines the mode of hover interactions for this scene." + }, + "editType": "plot", + "_deprecated": { + "cameraposition": { + "valType": "info_array", + "role": "info", + "editType": "camera", + "description": "Obsolete. Use `camera` instead." + } + }, + "annotations": { + "items": { + "annotation": { + "visible": { + "valType": "boolean", + "role": "info", + "dflt": true, + "editType": "calc", + "description": "Determines whether or not this annotation is visible." + }, + "x": { + "valType": "any", + "role": "info", + "description": "Sets the annotation's x position.", + "editType": "calc" + }, + "y": { + "valType": "any", + "role": "info", + "description": "Sets the annotation's y position.", + "editType": "calc" + }, + "z": { + "valType": "any", + "role": "info", + "description": "Sets the annotation's z position.", + "editType": "calc" + }, + "ax": { + "valType": "number", + "role": "info", + "description": "Sets the x component of the arrow tail about the arrow head (in pixels).", + "editType": "calc" + }, + "ay": { + "valType": "number", + "role": "info", + "description": "Sets the y component of the arrow tail about the arrow head (in pixels).", + "editType": "calc" + }, + "xanchor": { + "valType": "enumerated", + "values": [ + "auto", + "left", + "center", + "right" + ], + "dflt": "auto", + "role": "info", + "editType": "calc", + "description": "Sets the text box's horizontal position anchor This anchor binds the `x` position to the *left*, *center* or *right* of the annotation. For example, if `x` is set to 1, `xref` to *paper* and `xanchor` to *right* then the right-most portion of the annotation lines up with the right-most edge of the plotting area. If *auto*, the anchor is equivalent to *center* for data-referenced annotations or if there is an arrow, whereas for paper-referenced with no arrow, the anchor picked corresponds to the closest side." + }, + "xshift": { + "valType": "number", + "dflt": 0, + "role": "style", + "editType": "calc", + "description": "Shifts the position of the whole annotation and arrow to the right (positive) or left (negative) by this many pixels." + }, + "yanchor": { + "valType": "enumerated", + "values": [ + "auto", + "top", + "middle", + "bottom" + ], + "dflt": "auto", + "role": "info", + "editType": "calc", + "description": "Sets the text box's vertical position anchor This anchor binds the `y` position to the *top*, *middle* or *bottom* of the annotation. For example, if `y` is set to 1, `yref` to *paper* and `yanchor` to *top* then the top-most portion of the annotation lines up with the top-most edge of the plotting area. If *auto*, the anchor is equivalent to *middle* for data-referenced annotations or if there is an arrow, whereas for paper-referenced with no arrow, the anchor picked corresponds to the closest side." + }, + "yshift": { + "valType": "number", + "dflt": 0, + "role": "style", + "editType": "calc", + "description": "Shifts the position of the whole annotation and arrow up (positive) or down (negative) by this many pixels." + }, + "text": { + "valType": "string", + "role": "info", + "editType": "calc", + "description": "Sets the text associated with this annotation. Plotly uses a subset of HTML tags to do things like newline (
), bold (), italics (), hyperlinks (). Tags , , are also supported." + }, + "textangle": { + "valType": "angle", + "dflt": 0, + "role": "style", + "editType": "calc", + "description": "Sets the angle at which the `text` is drawn with respect to the horizontal." + }, + "font": { + "family": { + "valType": "string", + "role": "style", + "noBlank": true, + "strict": true, + "editType": "calc", + "description": "HTML font family - the typeface that will be applied by the web browser. The web browser will only be able to apply a font if it is available on the system which it operates. Provide multiple font families, separated by commas, to indicate the preference in which to apply fonts if they aren't available on the system. The plotly service (at https://plot.ly or on-premise) generates images on a server, where only a select number of fonts are installed and supported. These include *Arial*, *Balto*, *Courier New*, *Droid Sans*,, *Droid Serif*, *Droid Sans Mono*, *Gravitas One*, *Old Standard TT*, *Open Sans*, *Overpass*, *PT Sans Narrow*, *Raleway*, *Times New Roman*." + }, + "size": { + "valType": "number", + "role": "style", + "min": 1, + "editType": "calc" + }, + "color": { + "valType": "color", + "role": "style", + "editType": "calc" + }, + "editType": "calc", + "description": "Sets the annotation text font.", + "role": "object" + }, + "width": { + "valType": "number", + "min": 1, + "dflt": null, + "role": "style", + "editType": "calc", + "description": "Sets an explicit width for the text box. null (default) lets the text set the box width. Wider text will be clipped. There is no automatic wrapping; use
to start a new line." + }, + "height": { + "valType": "number", + "min": 1, + "dflt": null, + "role": "style", + "editType": "calc", + "description": "Sets an explicit height for the text box. null (default) lets the text set the box height. Taller text will be clipped." + }, + "opacity": { + "valType": "number", + "min": 0, + "max": 1, + "dflt": 1, + "role": "style", + "editType": "calc", + "description": "Sets the opacity of the annotation (text + arrow)." + }, + "align": { + "valType": "enumerated", + "values": [ + "left", + "center", + "right" + ], + "dflt": "center", + "role": "style", + "editType": "calc", + "description": "Sets the horizontal alignment of the `text` within the box. Has an effect only if `text` spans more two or more lines (i.e. `text` contains one or more
HTML tags) or if an explicit width is set to override the text width." + }, + "valign": { + "valType": "enumerated", + "values": [ + "top", + "middle", + "bottom" + ], + "dflt": "middle", + "role": "style", + "editType": "calc", + "description": "Sets the vertical alignment of the `text` within the box. Has an effect only if an explicit height is set to override the text height." + }, + "bgcolor": { + "valType": "color", + "dflt": "rgba(0,0,0,0)", + "role": "style", + "editType": "calc", + "description": "Sets the background color of the annotation." + }, + "bordercolor": { + "valType": "color", + "dflt": "rgba(0,0,0,0)", + "role": "style", + "editType": "calc", + "description": "Sets the color of the border enclosing the annotation `text`." + }, + "borderpad": { + "valType": "number", + "min": 0, + "dflt": 1, + "role": "style", + "editType": "calc", + "description": "Sets the padding (in px) between the `text` and the enclosing border." + }, + "borderwidth": { + "valType": "number", + "min": 0, + "dflt": 1, + "role": "style", + "editType": "calc", + "description": "Sets the width (in px) of the border enclosing the annotation `text`." + }, + "showarrow": { + "valType": "boolean", + "dflt": true, + "role": "style", + "editType": "calc", + "description": "Determines whether or not the annotation is drawn with an arrow. If *true*, `text` is placed near the arrow's tail. If *false*, `text` lines up with the `x` and `y` provided." + }, + "arrowcolor": { + "valType": "color", + "role": "style", + "editType": "calc", + "description": "Sets the color of the annotation arrow." + }, + "arrowhead": { + "valType": "integer", + "min": 0, + "max": 8, + "dflt": 1, + "role": "style", + "editType": "calc", + "description": "Sets the annotation arrow head style." + }, + "arrowsize": { + "valType": "number", + "min": 0.3, + "dflt": 1, + "role": "style", + "editType": "calc", + "description": "Sets the size of the annotation arrow head, relative to `arrowwidth`. A value of 1 (default) gives a head about 3x as wide as the line." + }, + "arrowwidth": { + "valType": "number", + "min": 0.1, + "role": "style", + "editType": "calc", + "description": "Sets the width (in px) of annotation arrow line." + }, + "standoff": { + "valType": "number", + "min": 0, + "dflt": 0, + "role": "style", + "editType": "calc", + "description": "Sets a distance, in pixels, to move the arrowhead away from the position it is pointing at, for example to point at the edge of a marker independent of zoom. Note that this shortens the arrow from the `ax` / `ay` vector, in contrast to `xshift` / `yshift` which moves everything by this amount." + }, + "hovertext": { + "valType": "string", + "role": "info", + "editType": "calc", + "description": "Sets text to appear when hovering over this annotation. If omitted or blank, no hover label will appear." + }, + "hoverlabel": { + "bgcolor": { + "valType": "color", + "role": "style", + "editType": "calc", + "description": "Sets the background color of the hover label. By default uses the annotation's `bgcolor` made opaque, or white if it was transparent." + }, + "bordercolor": { + "valType": "color", + "role": "style", + "editType": "calc", + "description": "Sets the border color of the hover label. By default uses either dark grey or white, for maximum contrast with `hoverlabel.bgcolor`." + }, + "font": { + "family": { + "valType": "string", + "role": "style", + "noBlank": true, + "strict": true, + "editType": "calc", + "description": "HTML font family - the typeface that will be applied by the web browser. The web browser will only be able to apply a font if it is available on the system which it operates. Provide multiple font families, separated by commas, to indicate the preference in which to apply fonts if they aren't available on the system. The plotly service (at https://plot.ly or on-premise) generates images on a server, where only a select number of fonts are installed and supported. These include *Arial*, *Balto*, *Courier New*, *Droid Sans*,, *Droid Serif*, *Droid Sans Mono*, *Gravitas One*, *Old Standard TT*, *Open Sans*, *Overpass*, *PT Sans Narrow*, *Raleway*, *Times New Roman*." + }, + "size": { + "valType": "number", + "role": "style", + "min": 1, + "editType": "calc" + }, + "color": { + "valType": "color", + "role": "style", + "editType": "calc" + }, + "editType": "calc", + "description": "Sets the hover label text font. By default uses the global hover font and size, with color from `hoverlabel.bordercolor`.", + "role": "object" + }, + "editType": "calc", + "role": "object" + }, + "captureevents": { + "valType": "boolean", + "role": "info", + "editType": "calc", + "description": "Determines whether the annotation text box captures mouse move and click events, or allows those events to pass through to data points in the plot that may be behind the annotation. By default `captureevents` is *false* unless `hovertext` is provided. If you use the event `plotly_clickannotation` without `hovertext` you must explicitly enable `captureevents`." + }, + "editType": "calc", + "role": "object" + } + }, + "role": "object" + }, + "_isSubplotObj": true, + "role": "object" + }, + "geo": { + "domain": { + "x": { + "valType": "info_array", + "role": "info", + "items": [ + { + "valType": "number", + "min": 0, + "max": 1, + "editType": "plot" + }, + { + "valType": "number", + "min": 0, + "max": 1, + "editType": "plot" + } + ], + "dflt": [ + 0, + 1 + ], + "description": "Sets the maximum horizontal domain of this map (in plot fraction). Note that geo subplots are constrained by domain. In general, when `projection.scale` is set to 1. a map will fit either its x or y domain, but not both. ", + "editType": "plot" + }, + "y": { + "valType": "info_array", + "role": "info", + "items": [ + { + "valType": "number", + "min": 0, + "max": 1, + "editType": "plot" + }, + { + "valType": "number", + "min": 0, + "max": 1, + "editType": "plot" + } + ], + "dflt": [ + 0, + 1 + ], + "description": "Sets the maximum vertical domain of this map (in plot fraction). Note that geo subplots are constrained by domain. In general, when `projection.scale` is set to 1. a map will fit either its x or y domain, but not both. ", + "editType": "plot" + }, + "editType": "plot", + "role": "object" + }, + "resolution": { + "valType": "enumerated", + "values": [ + 110, + 50 + ], + "role": "info", + "dflt": 110, + "coerceNumber": true, + "description": "Sets the resolution of the base layers. The values have units of km/mm e.g. 110 corresponds to a scale ratio of 1:110,000,000.", + "editType": "plot" + }, + "scope": { + "valType": "enumerated", + "role": "info", + "values": [ + "world", + "usa", + "europe", + "asia", + "africa", + "north america", + "south america" + ], + "dflt": "world", + "description": "Set the scope of the map.", + "editType": "plot" + }, + "projection": { + "type": { + "valType": "enumerated", + "role": "info", + "values": [ + "equirectangular", + "mercator", + "orthographic", + "natural earth", + "kavrayskiy7", + "miller", + "robinson", + "eckert4", + "azimuthal equal area", + "azimuthal equidistant", + "conic equal area", + "conic conformal", + "conic equidistant", + "gnomonic", + "stereographic", + "mollweide", + "hammer", + "transverse mercator", + "albers usa", + "winkel tripel", + "aitoff", + "sinusoidal" + ], + "description": "Sets the projection type.", + "editType": "plot" + }, + "rotation": { + "lon": { + "valType": "number", + "role": "info", + "description": "Rotates the map along parallels (in degrees East). Defaults to the center of the `lonaxis.range` values.", + "editType": "plot" + }, + "lat": { + "valType": "number", + "role": "info", + "description": "Rotates the map along meridians (in degrees North).", + "editType": "plot" + }, + "roll": { + "valType": "number", + "role": "info", + "description": "Roll the map (in degrees) For example, a roll of *180* makes the map appear upside down.", + "editType": "plot" + }, + "editType": "plot", + "role": "object" + }, + "parallels": { + "valType": "info_array", + "role": "info", + "items": [ + { + "valType": "number", + "editType": "plot" + }, + { + "valType": "number", + "editType": "plot" + } + ], + "description": "For conic projection types only. Sets the parallels (tangent, secant) where the cone intersects the sphere.", + "editType": "plot" + }, + "scale": { + "valType": "number", + "role": "info", + "min": 0, + "dflt": 1, + "description": "Zooms in or out on the map view. A scale of *1* corresponds to the largest zoom level that fits the map's lon and lat ranges. ", + "editType": "plot" + }, + "editType": "plot", + "role": "object" + }, + "center": { + "lon": { + "valType": "number", + "role": "info", + "description": "Sets the longitude of the map's center. By default, the map's longitude center lies at the middle of the longitude range for scoped projection and above `projection.rotation.lon` otherwise.", + "editType": "plot" + }, + "lat": { + "valType": "number", + "role": "info", + "description": "Sets the latitude of the map's center. For all projection types, the map's latitude center lies at the middle of the latitude range by default.", + "editType": "plot" + }, + "editType": "plot", + "role": "object" + }, + "showcoastlines": { + "valType": "boolean", + "role": "info", + "description": "Sets whether or not the coastlines are drawn.", + "editType": "plot" + }, + "coastlinecolor": { + "valType": "color", + "role": "style", + "dflt": "#444", + "description": "Sets the coastline color.", + "editType": "plot" + }, + "coastlinewidth": { + "valType": "number", + "role": "style", + "min": 0, + "dflt": 1, + "description": "Sets the coastline stroke width (in px).", + "editType": "plot" + }, + "showland": { + "valType": "boolean", + "role": "info", + "dflt": false, + "description": "Sets whether or not land masses are filled in color.", + "editType": "plot" + }, + "landcolor": { + "valType": "color", + "role": "style", + "dflt": "#F0DC82", + "description": "Sets the land mass color.", + "editType": "plot" + }, + "showocean": { + "valType": "boolean", + "role": "info", + "dflt": false, + "description": "Sets whether or not oceans are filled in color.", + "editType": "plot" + }, + "oceancolor": { + "valType": "color", + "role": "style", + "dflt": "#3399FF", + "description": "Sets the ocean color", + "editType": "plot" + }, + "showlakes": { + "valType": "boolean", + "role": "info", + "dflt": false, + "description": "Sets whether or not lakes are drawn.", + "editType": "plot" + }, + "lakecolor": { + "valType": "color", + "role": "style", + "dflt": "#3399FF", + "description": "Sets the color of the lakes.", + "editType": "plot" + }, + "showrivers": { + "valType": "boolean", + "role": "info", + "dflt": false, + "description": "Sets whether or not rivers are drawn.", + "editType": "plot" + }, + "rivercolor": { + "valType": "color", + "role": "style", + "dflt": "#3399FF", + "description": "Sets color of the rivers.", + "editType": "plot" + }, + "riverwidth": { + "valType": "number", + "role": "style", + "min": 0, + "dflt": 1, + "description": "Sets the stroke width (in px) of the rivers.", + "editType": "plot" + }, + "showcountries": { + "valType": "boolean", + "role": "info", + "description": "Sets whether or not country boundaries are drawn.", + "editType": "plot" + }, + "countrycolor": { + "valType": "color", + "role": "style", + "dflt": "#444", + "description": "Sets line color of the country boundaries.", + "editType": "plot" + }, + "countrywidth": { + "valType": "number", + "role": "style", + "min": 0, + "dflt": 1, + "description": "Sets line width (in px) of the country boundaries.", + "editType": "plot" + }, + "showsubunits": { + "valType": "boolean", + "role": "info", + "description": "Sets whether or not boundaries of subunits within countries (e.g. states, provinces) are drawn.", + "editType": "plot" + }, + "subunitcolor": { + "valType": "color", + "role": "style", + "dflt": "#444", + "description": "Sets the color of the subunits boundaries.", + "editType": "plot" + }, + "subunitwidth": { + "valType": "number", + "role": "style", + "min": 0, + "dflt": 1, + "description": "Sets the stroke width (in px) of the subunits boundaries.", + "editType": "plot" + }, + "showframe": { + "valType": "boolean", + "role": "info", + "description": "Sets whether or not a frame is drawn around the map.", + "editType": "plot" + }, + "framecolor": { + "valType": "color", + "role": "style", + "dflt": "#444", + "description": "Sets the color the frame.", + "editType": "plot" + }, + "framewidth": { + "valType": "number", + "role": "style", + "min": 0, + "dflt": 1, + "description": "Sets the stroke width (in px) of the frame.", + "editType": "plot" + }, + "bgcolor": { + "valType": "color", + "role": "style", + "dflt": "#fff", + "description": "Set the background color of the map", + "editType": "plot" + }, + "lonaxis": { + "range": { + "valType": "info_array", + "role": "info", + "items": [ + { + "valType": "number", + "editType": "plot" + }, + { + "valType": "number", + "editType": "plot" + } + ], + "description": "Sets the range of this axis (in degrees), sets the map's clipped coordinates.", + "editType": "plot" + }, + "showgrid": { + "valType": "boolean", + "role": "info", + "dflt": false, + "description": "Sets whether or not graticule are shown on the map.", + "editType": "plot" + }, + "tick0": { + "valType": "number", + "role": "info", + "description": "Sets the graticule's starting tick longitude/latitude.", + "editType": "plot" + }, + "dtick": { + "valType": "number", + "role": "info", + "description": "Sets the graticule's longitude/latitude tick step.", + "editType": "plot" + }, + "gridcolor": { + "valType": "color", + "role": "style", + "dflt": "#eee", + "description": "Sets the graticule's stroke color.", + "editType": "plot" + }, + "gridwidth": { + "valType": "number", + "role": "style", + "min": 0, + "dflt": 1, + "description": "Sets the graticule's stroke width (in px).", + "editType": "plot" + }, + "editType": "plot", + "role": "object" + }, + "lataxis": { + "range": { + "valType": "info_array", + "role": "info", + "items": [ + { + "valType": "number", + "editType": "plot" + }, + { + "valType": "number", + "editType": "plot" + } + ], + "description": "Sets the range of this axis (in degrees), sets the map's clipped coordinates.", + "editType": "plot" + }, + "showgrid": { + "valType": "boolean", + "role": "info", + "dflt": false, + "description": "Sets whether or not graticule are shown on the map.", + "editType": "plot" + }, + "tick0": { + "valType": "number", + "role": "info", + "description": "Sets the graticule's starting tick longitude/latitude.", + "editType": "plot" + }, + "dtick": { + "valType": "number", + "role": "info", + "description": "Sets the graticule's longitude/latitude tick step.", + "editType": "plot" + }, + "gridcolor": { + "valType": "color", + "role": "style", + "dflt": "#eee", + "description": "Sets the graticule's stroke color.", + "editType": "plot" + }, + "gridwidth": { + "valType": "number", + "role": "style", + "min": 0, + "dflt": 1, + "description": "Sets the graticule's stroke width (in px).", + "editType": "plot" + }, + "editType": "plot", + "role": "object" + }, + "editType": "plot", + "_isSubplotObj": true, + "role": "object" + }, + "mapbox": { + "_arrayAttrRegexps": [ + {} + ], + "domain": { + "x": { + "valType": "info_array", + "role": "info", + "items": [ + { + "valType": "number", + "min": 0, + "max": 1, + "editType": "plot" + }, + { + "valType": "number", + "min": 0, + "max": 1, + "editType": "plot" + } + ], + "dflt": [ + 0, + 1 + ], + "description": "Sets the horizontal domain of this subplot (in plot fraction).", + "editType": "plot" + }, + "y": { + "valType": "info_array", + "role": "info", + "items": [ + { + "valType": "number", + "min": 0, + "max": 1, + "editType": "plot" + }, + { + "valType": "number", + "min": 0, + "max": 1, + "editType": "plot" + } + ], + "dflt": [ + 0, + 1 + ], + "description": "Sets the vertical domain of this subplot (in plot fraction).", + "editType": "plot" + }, + "editType": "plot", + "role": "object" + }, + "accesstoken": { + "valType": "string", + "noBlank": true, + "strict": true, + "role": "info", + "description": "Sets the mapbox access token to be used for this mapbox map. Alternatively, the mapbox access token can be set in the configuration options under `mapboxAccessToken`.", + "editType": "plot" + }, + "style": { + "valType": "any", + "values": [ + "basic", + "streets", + "outdoors", + "light", + "dark", + "satellite", + "satellite-streets" + ], + "dflt": "basic", + "role": "style", + "description": "Sets the Mapbox map style. Either input one of the default Mapbox style names or the URL to a custom style or a valid Mapbox style JSON.", + "editType": "plot" + }, + "center": { + "lon": { + "valType": "number", + "dflt": 0, + "role": "info", + "description": "Sets the longitude of the center of the map (in degrees East).", + "editType": "plot" + }, + "lat": { + "valType": "number", + "dflt": 0, + "role": "info", + "description": "Sets the latitude of the center of the map (in degrees North).", + "editType": "plot" + }, + "editType": "plot", + "role": "object" + }, + "zoom": { + "valType": "number", + "dflt": 1, + "role": "info", + "description": "Sets the zoom level of the map.", + "editType": "plot" + }, + "bearing": { + "valType": "number", + "dflt": 0, + "role": "info", + "description": "Sets the bearing angle of the map (in degrees counter-clockwise from North).", + "editType": "plot" + }, + "pitch": { + "valType": "number", + "dflt": 0, + "role": "info", + "description": "Sets the pitch angle of the map (in degrees, where *0* means perpendicular to the surface of the map).", + "editType": "plot" + }, + "layers": { + "items": { + "layer": { + "sourcetype": { + "valType": "enumerated", + "values": [ + "geojson", + "vector" + ], + "dflt": "geojson", + "role": "info", + "description": "Sets the source type for this layer. Support for *raster*, *image* and *video* source types is coming soon.", + "editType": "plot" + }, + "source": { + "valType": "any", + "role": "info", + "description": "Sets the source data for this layer. Source can be either a URL, a geojson object (with `sourcetype` set to *geojson*) or an array of tile URLS (with `sourcetype` set to *vector*).", + "editType": "plot" + }, + "sourcelayer": { + "valType": "string", + "dflt": "", + "role": "info", + "description": "Specifies the layer to use from a vector tile source. Required for *vector* source type that supports multiple layers.", + "editType": "plot" + }, + "type": { + "valType": "enumerated", + "values": [ + "circle", + "line", + "fill", + "symbol" + ], + "dflt": "circle", + "role": "info", + "description": "Sets the layer type. Support for *raster*, *background* types is coming soon. Note that *line* and *fill* are not compatible with Point GeoJSON geometries.", + "editType": "plot" + }, + "below": { + "valType": "string", + "dflt": "", + "role": "info", + "description": "Determines if the layer will be inserted before the layer with the specified ID. If omitted or set to '', the layer will be inserted above every existing layer.", + "editType": "plot" + }, + "color": { + "valType": "color", + "dflt": "#444", + "role": "style", + "description": "Sets the primary layer color. If `type` is *circle*, color corresponds to the circle color If `type` is *line*, color corresponds to the line color If `type` is *fill*, color corresponds to the fill color If `type` is *symbol*, color corresponds to the icon color", + "editType": "plot" + }, + "opacity": { + "valType": "number", + "min": 0, + "max": 1, + "dflt": 1, + "role": "info", + "description": "Sets the opacity of the layer.", + "editType": "plot" + }, + "circle": { + "radius": { + "valType": "number", + "dflt": 15, + "role": "style", + "description": "Sets the circle radius. Has an effect only when `type` is set to *circle*.", + "editType": "plot" + }, + "editType": "plot", + "role": "object" + }, + "line": { + "width": { + "valType": "number", + "dflt": 2, + "role": "style", + "description": "Sets the line width. Has an effect only when `type` is set to *line*.", + "editType": "plot" + }, + "editType": "plot", + "role": "object" + }, + "fill": { + "outlinecolor": { + "valType": "color", + "dflt": "#444", + "role": "style", + "description": "Sets the fill outline color. Has an effect only when `type` is set to *fill*.", + "editType": "plot" + }, + "editType": "plot", + "role": "object" + }, + "symbol": { + "icon": { + "valType": "string", + "dflt": "marker", + "role": "style", + "description": "Sets the symbol icon image. Full list: https://www.mapbox.com/maki-icons/", + "editType": "plot" + }, + "iconsize": { + "valType": "number", + "dflt": 10, + "role": "style", + "description": "Sets the symbol icon size. Has an effect only when `type` is set to *symbol*.", + "editType": "plot" + }, + "text": { + "valType": "string", + "dflt": "", + "role": "info", + "description": "Sets the symbol text.", + "editType": "plot" + }, + "textfont": { + "family": { + "valType": "string", + "role": "style", + "noBlank": true, + "strict": true, + "description": "HTML font family - the typeface that will be applied by the web browser. The web browser will only be able to apply a font if it is available on the system which it operates. Provide multiple font families, separated by commas, to indicate the preference in which to apply fonts if they aren't available on the system. The plotly service (at https://plot.ly or on-premise) generates images on a server, where only a select number of fonts are installed and supported. These include *Arial*, *Balto*, *Courier New*, *Droid Sans*,, *Droid Serif*, *Droid Sans Mono*, *Gravitas One*, *Old Standard TT*, *Open Sans*, *Overpass*, *PT Sans Narrow*, *Raleway*, *Times New Roman*.", + "dflt": "Open Sans Regular, Arial Unicode MS Regular", + "editType": "plot" + }, + "size": { + "valType": "number", + "role": "style", + "min": 1, + "editType": "plot" + }, + "color": { + "valType": "color", + "role": "style", + "editType": "plot" + }, + "description": "Sets the icon text font. Has an effect only when `type` is set to *symbol*.", + "editType": "plot", + "role": "object" + }, + "textposition": { + "valType": "enumerated", + "values": [ + "top left", + "top center", + "top right", + "middle left", + "middle center", + "middle right", + "bottom left", + "bottom center", + "bottom right" + ], + "dflt": "middle center", + "arrayOk": false, + "role": "style", + "editType": "plot", + "description": "Sets the positions of the `text` elements with respects to the (x,y) coordinates." + }, + "editType": "plot", + "role": "object" + }, + "editType": "plot", + "role": "object" + } + }, + "role": "object" + }, + "editType": "plot", + "_isSubplotObj": true, + "role": "object" + }, + "radialaxis": { + "range": { + "valType": "info_array", + "role": "info", + "items": [ + { + "valType": "number", + "editType": "plot" + }, + { + "valType": "number", + "editType": "plot" + } + ], + "description": "Defines the start and end point of this radial axis.", + "editType": "plot" + }, + "domain": { + "valType": "info_array", + "role": "info", + "items": [ + { + "valType": "number", + "min": 0, + "max": 1, + "editType": "plot" + }, + { + "valType": "number", + "min": 0, + "max": 1, + "editType": "plot" + } + ], + "dflt": [ + 0, + 1 + ], + "editType": "plot", + "description": "Polar chart subplots are not supported yet. This key has currently no effect." + }, + "orientation": { + "valType": "number", + "role": "style", + "description": "Sets the orientation (an angle with respect to the origin) of the radial axis.", + "editType": "plot" + }, + "showline": { + "valType": "boolean", + "role": "style", + "description": "Determines whether or not the line bounding this radial axis will be shown on the figure.", + "editType": "plot" + }, + "showticklabels": { + "valType": "boolean", + "role": "style", + "description": "Determines whether or not the radial axis ticks will feature tick labels.", + "editType": "plot" + }, + "tickorientation": { + "valType": "enumerated", + "values": [ + "horizontal", + "vertical" + ], + "role": "style", + "description": "Sets the orientation (from the paper perspective) of the radial axis tick labels.", + "editType": "plot" + }, + "ticklen": { + "valType": "number", + "min": 0, + "role": "style", + "description": "Sets the length of the tick lines on this radial axis.", + "editType": "plot" + }, + "tickcolor": { + "valType": "color", + "role": "style", + "description": "Sets the color of the tick lines on this radial axis.", + "editType": "plot" + }, + "ticksuffix": { + "valType": "string", + "role": "style", + "description": "Sets the length of the tick lines on this radial axis.", + "editType": "plot" + }, + "endpadding": { + "valType": "number", + "role": "style", + "editType": "plot" + }, + "visible": { + "valType": "boolean", + "role": "info", + "description": "Determines whether or not this axis will be visible.", + "editType": "plot" + }, + "editType": "plot", + "role": "object" + }, + "angularaxis": { + "range": { + "valType": "info_array", + "role": "info", + "items": [ + { + "valType": "number", + "dflt": 0, + "editType": "plot" + }, + { + "valType": "number", + "dflt": 360, + "editType": "plot" + } + ], + "description": "Defines the start and end point of this angular axis.", + "editType": "plot" + }, + "domain": { + "valType": "info_array", + "role": "info", + "items": [ + { + "valType": "number", + "min": 0, + "max": 1, + "editType": "plot" + }, + { + "valType": "number", + "min": 0, + "max": 1, + "editType": "plot" + } + ], + "dflt": [ + 0, + 1 + ], + "editType": "plot", + "description": "Polar chart subplots are not supported yet. This key has currently no effect." + }, + "showline": { + "valType": "boolean", + "role": "style", + "description": "Determines whether or not the line bounding this angular axis will be shown on the figure.", + "editType": "plot" + }, + "showticklabels": { + "valType": "boolean", + "role": "style", + "description": "Determines whether or not the angular axis ticks will feature tick labels.", + "editType": "plot" + }, + "tickorientation": { + "valType": "enumerated", + "values": [ + "horizontal", + "vertical" + ], + "role": "style", + "description": "Sets the orientation (from the paper perspective) of the angular axis tick labels.", + "editType": "plot" + }, + "ticklen": { + "valType": "number", + "min": 0, + "role": "style", + "description": "Sets the length of the tick lines on this angular axis.", + "editType": "plot" + }, + "tickcolor": { + "valType": "color", + "role": "style", + "description": "Sets the color of the tick lines on this angular axis.", + "editType": "plot" + }, + "ticksuffix": { + "valType": "string", + "role": "style", + "description": "Sets the length of the tick lines on this angular axis.", + "editType": "plot" + }, + "endpadding": { + "valType": "number", + "role": "style", + "editType": "plot" + }, + "visible": { + "valType": "boolean", + "role": "info", + "description": "Determines whether or not this axis will be visible.", + "editType": "plot" + }, + "editType": "plot", + "role": "object" + }, + "direction": { + "valType": "enumerated", + "values": [ + "clockwise", + "counterclockwise" + ], + "role": "info", + "description": "For polar plots only. Sets the direction corresponding to positive angles.", + "editType": "plot" + }, + "orientation": { + "valType": "angle", + "role": "info", + "description": "For polar plots only. Rotates the entire polar by the given angle.", + "editType": "plot" + }, + "editType": "plot", + "legend": { + "bgcolor": { + "valType": "color", + "role": "style", + "editType": "legend", + "description": "Sets the legend background color." + }, + "bordercolor": { + "valType": "color", + "dflt": "#444", + "role": "style", + "editType": "legend", + "description": "Sets the color of the border enclosing the legend." + }, + "borderwidth": { + "valType": "number", + "min": 0, + "dflt": 0, + "role": "style", + "editType": "legend", + "description": "Sets the width (in px) of the border enclosing the legend." + }, + "font": { + "family": { + "valType": "string", + "role": "style", + "noBlank": true, + "strict": true, + "editType": "legend", + "description": "HTML font family - the typeface that will be applied by the web browser. The web browser will only be able to apply a font if it is available on the system which it operates. Provide multiple font families, separated by commas, to indicate the preference in which to apply fonts if they aren't available on the system. The plotly service (at https://plot.ly or on-premise) generates images on a server, where only a select number of fonts are installed and supported. These include *Arial*, *Balto*, *Courier New*, *Droid Sans*,, *Droid Serif*, *Droid Sans Mono*, *Gravitas One*, *Old Standard TT*, *Open Sans*, *Overpass*, *PT Sans Narrow*, *Raleway*, *Times New Roman*." + }, + "size": { + "valType": "number", + "role": "style", + "min": 1, + "editType": "legend" + }, + "color": { + "valType": "color", + "role": "style", + "editType": "legend" + }, + "editType": "legend", + "description": "Sets the font used to text the legend items.", + "role": "object" + }, + "orientation": { + "valType": "enumerated", + "values": [ + "v", + "h" + ], + "dflt": "v", + "role": "info", + "editType": "legend", + "description": "Sets the orientation of the legend." + }, + "traceorder": { + "valType": "flaglist", + "flags": [ + "reversed", + "grouped" + ], + "extras": [ + "normal" + ], + "role": "style", + "editType": "legend", + "description": "Determines the order at which the legend items are displayed. If *normal*, the items are displayed top-to-bottom in the same order as the input data. If *reversed*, the items are displayed in the opposite order as *normal*. If *grouped*, the items are displayed in groups (when a trace `legendgroup` is provided). if *grouped+reversed*, the items are displayed in the opposite order as *grouped*." + }, + "tracegroupgap": { + "valType": "number", + "min": 0, + "dflt": 10, + "role": "style", + "editType": "legend", + "description": "Sets the amount of vertical space (in px) between legend groups." + }, + "x": { + "valType": "number", + "min": -2, + "max": 3, + "dflt": 1.02, + "role": "style", + "editType": "legend", + "description": "Sets the x position (in normalized coordinates) of the legend." + }, + "xanchor": { + "valType": "enumerated", + "values": [ + "auto", + "left", + "center", + "right" + ], + "dflt": "left", + "role": "info", + "editType": "legend", + "description": "Sets the legend's horizontal position anchor. This anchor binds the `x` position to the *left*, *center* or *right* of the legend." + }, + "y": { + "valType": "number", + "min": -2, + "max": 3, + "dflt": 1, + "role": "style", + "editType": "legend", + "description": "Sets the y position (in normalized coordinates) of the legend." + }, + "yanchor": { + "valType": "enumerated", + "values": [ + "auto", + "top", + "middle", + "bottom" + ], + "dflt": "auto", + "role": "info", + "editType": "legend", + "description": "Sets the legend's vertical position anchor This anchor binds the `y` position to the *top*, *middle* or *bottom* of the legend." + }, + "editType": "legend", + "role": "object" + }, + "annotations": { + "items": { + "annotation": { + "visible": { + "valType": "boolean", + "role": "info", + "dflt": true, + "editType": "calcIfAutorange", + "description": "Determines whether or not this annotation is visible." + }, + "text": { + "valType": "string", + "role": "info", + "editType": "calcIfAutorange", + "description": "Sets the text associated with this annotation. Plotly uses a subset of HTML tags to do things like newline (
), bold (), italics (), hyperlinks (). Tags , , are also supported." + }, + "textangle": { + "valType": "angle", + "dflt": 0, + "role": "style", + "editType": "calcIfAutorange", + "description": "Sets the angle at which the `text` is drawn with respect to the horizontal." + }, + "font": { + "family": { + "valType": "string", + "role": "style", + "noBlank": true, + "strict": true, + "editType": "calcIfAutorange", + "description": "HTML font family - the typeface that will be applied by the web browser. The web browser will only be able to apply a font if it is available on the system which it operates. Provide multiple font families, separated by commas, to indicate the preference in which to apply fonts if they aren't available on the system. The plotly service (at https://plot.ly or on-premise) generates images on a server, where only a select number of fonts are installed and supported. These include *Arial*, *Balto*, *Courier New*, *Droid Sans*,, *Droid Serif*, *Droid Sans Mono*, *Gravitas One*, *Old Standard TT*, *Open Sans*, *Overpass*, *PT Sans Narrow*, *Raleway*, *Times New Roman*." + }, + "size": { + "valType": "number", + "role": "style", + "min": 1, + "editType": "calcIfAutorange" + }, + "color": { + "valType": "color", + "role": "style", + "editType": "arraydraw" + }, + "editType": "calcIfAutorange", + "description": "Sets the annotation text font.", + "role": "object" + }, + "width": { + "valType": "number", + "min": 1, + "dflt": null, + "role": "style", + "editType": "calcIfAutorange", + "description": "Sets an explicit width for the text box. null (default) lets the text set the box width. Wider text will be clipped. There is no automatic wrapping; use
to start a new line." + }, + "height": { + "valType": "number", + "min": 1, + "dflt": null, + "role": "style", + "editType": "calcIfAutorange", + "description": "Sets an explicit height for the text box. null (default) lets the text set the box height. Taller text will be clipped." + }, + "opacity": { + "valType": "number", + "min": 0, + "max": 1, + "dflt": 1, + "role": "style", + "editType": "arraydraw", + "description": "Sets the opacity of the annotation (text + arrow)." + }, + "align": { + "valType": "enumerated", + "values": [ + "left", + "center", + "right" + ], + "dflt": "center", + "role": "style", + "editType": "arraydraw", + "description": "Sets the horizontal alignment of the `text` within the box. Has an effect only if `text` spans more two or more lines (i.e. `text` contains one or more
HTML tags) or if an explicit width is set to override the text width." + }, + "valign": { + "valType": "enumerated", + "values": [ + "top", + "middle", + "bottom" + ], + "dflt": "middle", + "role": "style", + "editType": "arraydraw", + "description": "Sets the vertical alignment of the `text` within the box. Has an effect only if an explicit height is set to override the text height." + }, + "bgcolor": { + "valType": "color", + "dflt": "rgba(0,0,0,0)", + "role": "style", + "editType": "arraydraw", + "description": "Sets the background color of the annotation." + }, + "bordercolor": { + "valType": "color", + "dflt": "rgba(0,0,0,0)", + "role": "style", + "editType": "arraydraw", + "description": "Sets the color of the border enclosing the annotation `text`." + }, + "borderpad": { + "valType": "number", + "min": 0, + "dflt": 1, + "role": "style", + "editType": "calcIfAutorange", + "description": "Sets the padding (in px) between the `text` and the enclosing border." + }, + "borderwidth": { + "valType": "number", + "min": 0, + "dflt": 1, + "role": "style", + "editType": "calcIfAutorange", + "description": "Sets the width (in px) of the border enclosing the annotation `text`." + }, + "showarrow": { + "valType": "boolean", + "dflt": true, + "role": "style", + "editType": "calcIfAutorange", + "description": "Determines whether or not the annotation is drawn with an arrow. If *true*, `text` is placed near the arrow's tail. If *false*, `text` lines up with the `x` and `y` provided." + }, + "arrowcolor": { + "valType": "color", + "role": "style", + "editType": "arraydraw", + "description": "Sets the color of the annotation arrow." + }, + "arrowhead": { + "valType": "integer", + "min": 0, + "max": 8, + "dflt": 1, + "role": "style", + "editType": "arraydraw", + "description": "Sets the annotation arrow head style." + }, + "arrowsize": { + "valType": "number", + "min": 0.3, + "dflt": 1, + "role": "style", + "editType": "calcIfAutorange", + "description": "Sets the size of the annotation arrow head, relative to `arrowwidth`. A value of 1 (default) gives a head about 3x as wide as the line." + }, + "arrowwidth": { + "valType": "number", + "min": 0.1, + "role": "style", + "editType": "calcIfAutorange", + "description": "Sets the width (in px) of annotation arrow line." + }, + "standoff": { + "valType": "number", + "min": 0, + "dflt": 0, + "role": "style", + "editType": "calcIfAutorange", + "description": "Sets a distance, in pixels, to move the arrowhead away from the position it is pointing at, for example to point at the edge of a marker independent of zoom. Note that this shortens the arrow from the `ax` / `ay` vector, in contrast to `xshift` / `yshift` which moves everything by this amount." + }, + "ax": { + "valType": "any", + "role": "info", + "editType": "calcIfAutorange", + "description": "Sets the x component of the arrow tail about the arrow head. If `axref` is `pixel`, a positive (negative) component corresponds to an arrow pointing from right to left (left to right). If `axref` is an axis, this is an absolute value on that axis, like `x`, NOT a relative value." + }, + "ay": { + "valType": "any", + "role": "info", + "editType": "calcIfAutorange", + "description": "Sets the y component of the arrow tail about the arrow head. If `ayref` is `pixel`, a positive (negative) component corresponds to an arrow pointing from bottom to top (top to bottom). If `ayref` is an axis, this is an absolute value on that axis, like `y`, NOT a relative value." + }, + "axref": { + "valType": "enumerated", + "dflt": "pixel", + "values": [ + "pixel", + "/^x([2-9]|[1-9][0-9]+)?$/" + ], + "role": "info", + "editType": "calc", + "description": "Indicates in what terms the tail of the annotation (ax,ay) is specified. If `pixel`, `ax` is a relative offset in pixels from `x`. If set to an x axis id (e.g. *x* or *x2*), `ax` is specified in the same terms as that axis. This is useful for trendline annotations which should continue to indicate the correct trend when zoomed." + }, + "ayref": { + "valType": "enumerated", + "dflt": "pixel", + "values": [ + "pixel", + "/^y([2-9]|[1-9][0-9]+)?$/" + ], + "role": "info", + "editType": "calc", + "description": "Indicates in what terms the tail of the annotation (ax,ay) is specified. If `pixel`, `ay` is a relative offset in pixels from `y`. If set to a y axis id (e.g. *y* or *y2*), `ay` is specified in the same terms as that axis. This is useful for trendline annotations which should continue to indicate the correct trend when zoomed." + }, + "xref": { + "valType": "enumerated", + "values": [ + "paper", + "/^x([2-9]|[1-9][0-9]+)?$/" + ], + "role": "info", + "editType": "calc", + "description": "Sets the annotation's x coordinate axis. If set to an x axis id (e.g. *x* or *x2*), the `x` position refers to an x coordinate If set to *paper*, the `x` position refers to the distance from the left side of the plotting area in normalized coordinates where 0 (1) corresponds to the left (right) side." + }, + "x": { + "valType": "any", + "role": "info", + "editType": "calcIfAutorange", + "description": "Sets the annotation's x position. If the axis `type` is *log*, then you must take the log of your desired range. If the axis `type` is *date*, it should be date strings, like date data, though Date objects and unix milliseconds will be accepted and converted to strings. If the axis `type` is *category*, it should be numbers, using the scale where each category is assigned a serial number from zero in the order it appears." + }, + "xanchor": { + "valType": "enumerated", + "values": [ + "auto", + "left", + "center", + "right" + ], + "dflt": "auto", + "role": "info", + "editType": "calcIfAutorange", + "description": "Sets the text box's horizontal position anchor This anchor binds the `x` position to the *left*, *center* or *right* of the annotation. For example, if `x` is set to 1, `xref` to *paper* and `xanchor` to *right* then the right-most portion of the annotation lines up with the right-most edge of the plotting area. If *auto*, the anchor is equivalent to *center* for data-referenced annotations or if there is an arrow, whereas for paper-referenced with no arrow, the anchor picked corresponds to the closest side." + }, + "xshift": { + "valType": "number", + "dflt": 0, + "role": "style", + "editType": "calcIfAutorange", + "description": "Shifts the position of the whole annotation and arrow to the right (positive) or left (negative) by this many pixels." + }, + "yref": { + "valType": "enumerated", + "values": [ + "paper", + "/^y([2-9]|[1-9][0-9]+)?$/" + ], + "role": "info", + "editType": "calc", + "description": "Sets the annotation's y coordinate axis. If set to an y axis id (e.g. *y* or *y2*), the `y` position refers to an y coordinate If set to *paper*, the `y` position refers to the distance from the bottom of the plotting area in normalized coordinates where 0 (1) corresponds to the bottom (top)." + }, + "y": { + "valType": "any", + "role": "info", + "editType": "calcIfAutorange", + "description": "Sets the annotation's y position. If the axis `type` is *log*, then you must take the log of your desired range. If the axis `type` is *date*, it should be date strings, like date data, though Date objects and unix milliseconds will be accepted and converted to strings. If the axis `type` is *category*, it should be numbers, using the scale where each category is assigned a serial number from zero in the order it appears." + }, + "yanchor": { + "valType": "enumerated", + "values": [ + "auto", + "top", + "middle", + "bottom" + ], + "dflt": "auto", + "role": "info", + "editType": "calcIfAutorange", + "description": "Sets the text box's vertical position anchor This anchor binds the `y` position to the *top*, *middle* or *bottom* of the annotation. For example, if `y` is set to 1, `yref` to *paper* and `yanchor` to *top* then the top-most portion of the annotation lines up with the top-most edge of the plotting area. If *auto*, the anchor is equivalent to *middle* for data-referenced annotations or if there is an arrow, whereas for paper-referenced with no arrow, the anchor picked corresponds to the closest side." + }, + "yshift": { + "valType": "number", + "dflt": 0, + "role": "style", + "editType": "calcIfAutorange", + "description": "Shifts the position of the whole annotation and arrow up (positive) or down (negative) by this many pixels." + }, + "clicktoshow": { + "valType": "enumerated", + "values": [ + false, + "onoff", + "onout" + ], + "dflt": false, + "role": "style", + "editType": "arraydraw", + "description": "Makes this annotation respond to clicks on the plot. If you click a data point that exactly matches the `x` and `y` values of this annotation, and it is hidden (visible: false), it will appear. In *onoff* mode, you must click the same point again to make it disappear, so if you click multiple points, you can show multiple annotations. In *onout* mode, a click anywhere else in the plot (on another data point or not) will hide this annotation. If you need to show/hide this annotation in response to different `x` or `y` values, you can set `xclick` and/or `yclick`. This is useful for example to label the side of a bar. To label markers though, `standoff` is preferred over `xclick` and `yclick`." + }, + "xclick": { + "valType": "any", + "role": "info", + "editType": "arraydraw", + "description": "Toggle this annotation when clicking a data point whose `x` value is `xclick` rather than the annotation's `x` value." + }, + "yclick": { + "valType": "any", + "role": "info", + "editType": "arraydraw", + "description": "Toggle this annotation when clicking a data point whose `y` value is `yclick` rather than the annotation's `y` value." + }, + "hovertext": { + "valType": "string", + "role": "info", + "editType": "arraydraw", + "description": "Sets text to appear when hovering over this annotation. If omitted or blank, no hover label will appear." + }, + "hoverlabel": { + "bgcolor": { + "valType": "color", + "role": "style", + "editType": "arraydraw", + "description": "Sets the background color of the hover label. By default uses the annotation's `bgcolor` made opaque, or white if it was transparent." + }, + "bordercolor": { + "valType": "color", + "role": "style", + "editType": "arraydraw", + "description": "Sets the border color of the hover label. By default uses either dark grey or white, for maximum contrast with `hoverlabel.bgcolor`." + }, + "font": { + "family": { + "valType": "string", + "role": "style", + "noBlank": true, + "strict": true, + "editType": "arraydraw", + "description": "HTML font family - the typeface that will be applied by the web browser. The web browser will only be able to apply a font if it is available on the system which it operates. Provide multiple font families, separated by commas, to indicate the preference in which to apply fonts if they aren't available on the system. The plotly service (at https://plot.ly or on-premise) generates images on a server, where only a select number of fonts are installed and supported. These include *Arial*, *Balto*, *Courier New*, *Droid Sans*,, *Droid Serif*, *Droid Sans Mono*, *Gravitas One*, *Old Standard TT*, *Open Sans*, *Overpass*, *PT Sans Narrow*, *Raleway*, *Times New Roman*." + }, + "size": { + "valType": "number", + "role": "style", + "min": 1, + "editType": "arraydraw" + }, + "color": { + "valType": "color", + "role": "style", + "editType": "arraydraw" + }, + "editType": "arraydraw", + "description": "Sets the hover label text font. By default uses the global hover font and size, with color from `hoverlabel.bordercolor`.", + "role": "object" + }, + "editType": "arraydraw", + "role": "object" + }, + "captureevents": { + "valType": "boolean", + "role": "info", + "editType": "arraydraw", + "description": "Determines whether the annotation text box captures mouse move and click events, or allows those events to pass through to data points in the plot that may be behind the annotation. By default `captureevents` is *false* unless `hovertext` is provided. If you use the event `plotly_clickannotation` without `hovertext` you must explicitly enable `captureevents`." + }, + "editType": "calc", + "_deprecated": { + "ref": { + "valType": "string", + "role": "info", + "editType": "calc", + "description": "Obsolete. Set `xref` and `yref` separately instead." + } + }, + "role": "object" + } + }, + "role": "object" + }, + "shapes": { + "items": { + "shape": { + "visible": { + "valType": "boolean", + "role": "info", + "dflt": true, + "editType": "calcIfAutorange", + "description": "Determines whether or not this shape is visible." + }, + "type": { + "valType": "enumerated", + "values": [ + "circle", + "rect", + "path", + "line" + ], + "role": "info", + "editType": "calcIfAutorange", + "description": "Specifies the shape type to be drawn. If *line*, a line is drawn from (`x0`,`y0`) to (`x1`,`y1`) If *circle*, a circle is drawn from ((`x0`+`x1`)/2, (`y0`+`y1`)/2)) with radius (|(`x0`+`x1`)/2 - `x0`|, |(`y0`+`y1`)/2 -`y0`)|) If *rect*, a rectangle is drawn linking (`x0`,`y0`), (`x1`,`y0`), (`x1`,`y1`), (`x0`,`y1`), (`x0`,`y0`) If *path*, draw a custom SVG path using `path`." + }, + "layer": { + "valType": "enumerated", + "values": [ + "below", + "above" + ], + "dflt": "above", + "role": "info", + "editType": "arraydraw", + "description": "Specifies whether shapes are drawn below or above traces." + }, + "xref": { + "valType": "enumerated", + "values": [ + "paper", + "/^x([2-9]|[1-9][0-9]+)?$/" + ], + "role": "info", + "editType": "calc", + "description": "Sets the shape's x coordinate axis. If set to an x axis id (e.g. *x* or *x2*), the `x` position refers to an x coordinate If set to *paper*, the `x` position refers to the distance from the left side of the plotting area in normalized coordinates where *0* (*1*) corresponds to the left (right) side. If the axis `type` is *log*, then you must take the log of your desired range. If the axis `type` is *date*, then you must convert the date to unix time in milliseconds." + }, + "x0": { + "valType": "any", + "role": "info", + "editType": "calcIfAutorange", + "description": "Sets the shape's starting x position. See `type` for more info." + }, + "x1": { + "valType": "any", + "role": "info", + "editType": "calcIfAutorange", + "description": "Sets the shape's end x position. See `type` for more info." + }, + "yref": { + "valType": "enumerated", + "values": [ + "paper", + "/^y([2-9]|[1-9][0-9]+)?$/" + ], + "role": "info", + "editType": "calc", + "description": "Sets the annotation's y coordinate axis. If set to an y axis id (e.g. *y* or *y2*), the `y` position refers to an y coordinate If set to *paper*, the `y` position refers to the distance from the bottom of the plotting area in normalized coordinates where *0* (*1*) corresponds to the bottom (top)." + }, + "y0": { + "valType": "any", + "role": "info", + "editType": "calcIfAutorange", + "description": "Sets the shape's starting y position. See `type` for more info." + }, + "y1": { + "valType": "any", + "role": "info", + "editType": "calcIfAutorange", + "description": "Sets the shape's end y position. See `type` for more info." + }, + "path": { + "valType": "string", + "role": "info", + "editType": "calcIfAutorange", + "description": "For `type` *path* - a valid SVG path but with the pixel values replaced by data values. There are a few restrictions / quirks only absolute instructions, not relative. So the allowed segments are: M, L, H, V, Q, C, T, S, and Z arcs (A) are not allowed because radius rx and ry are relative. In the future we could consider supporting relative commands, but we would have to decide on how to handle date and log axes. Note that even as is, Q and C Bezier paths that are smooth on linear axes may not be smooth on log, and vice versa. no chained \"polybezier\" commands - specify the segment type for each one. On category axes, values are numbers scaled to the serial numbers of categories because using the categories themselves there would be no way to describe fractional positions On data axes: because space and T are both normal components of path strings, we can't use either to separate date from time parts. Therefore we'll use underscore for this purpose: 2015-02-21_13:45:56.789" + }, + "opacity": { + "valType": "number", + "min": 0, + "max": 1, + "dflt": 1, + "role": "info", + "editType": "arraydraw", + "description": "Sets the opacity of the shape." + }, + "line": { + "color": { + "valType": "color", + "role": "style", + "editType": "arraydraw", + "description": "Sets the line color." + }, + "width": { + "valType": "number", + "min": 0, + "dflt": 2, + "role": "style", + "editType": "calcIfAutorange", + "description": "Sets the line width (in px)." + }, + "dash": { + "valType": "string", + "values": [ + "solid", + "dot", + "dash", + "longdash", + "dashdot", + "longdashdot" + ], + "dflt": "solid", + "role": "style", + "editType": "arraydraw", + "description": "Sets the dash style of lines. Set to a dash type string (*solid*, *dot*, *dash*, *longdash*, *dashdot*, or *longdashdot*) or a dash length list in px (eg *5px,10px,2px,2px*)." + }, + "role": "object", + "editType": "calcIfAutorange" + }, + "fillcolor": { + "valType": "color", + "dflt": "rgba(0,0,0,0)", + "role": "info", + "editType": "arraydraw", + "description": "Sets the color filling the shape's interior." + }, + "editType": "arraydraw", + "role": "object" + } + }, + "role": "object" + }, + "images": { + "items": { + "image": { + "visible": { + "valType": "boolean", + "role": "info", + "dflt": true, + "editType": "arraydraw", + "description": "Determines whether or not this image is visible." + }, + "source": { + "valType": "string", + "role": "info", + "editType": "arraydraw", + "description": "Specifies the URL of the image to be used. The URL must be accessible from the domain where the plot code is run, and can be either relative or absolute." + }, + "layer": { + "valType": "enumerated", + "values": [ + "below", + "above" + ], + "dflt": "above", + "role": "info", + "editType": "arraydraw", + "description": "Specifies whether images are drawn below or above traces. When `xref` and `yref` are both set to `paper`, image is drawn below the entire plot area." + }, + "sizex": { + "valType": "number", + "role": "info", + "dflt": 0, + "editType": "arraydraw", + "description": "Sets the image container size horizontally. The image will be sized based on the `position` value. When `xref` is set to `paper`, units are sized relative to the plot width." + }, + "sizey": { + "valType": "number", + "role": "info", + "dflt": 0, + "editType": "arraydraw", + "description": "Sets the image container size vertically. The image will be sized based on the `position` value. When `yref` is set to `paper`, units are sized relative to the plot height." + }, + "sizing": { + "valType": "enumerated", + "values": [ + "fill", + "contain", + "stretch" + ], + "dflt": "contain", + "role": "info", + "editType": "arraydraw", + "description": "Specifies which dimension of the image to constrain." + }, + "opacity": { + "valType": "number", + "role": "info", + "min": 0, + "max": 1, + "dflt": 1, + "editType": "arraydraw", + "description": "Sets the opacity of the image." + }, + "x": { + "valType": "any", + "role": "info", + "dflt": 0, + "editType": "arraydraw", + "description": "Sets the image's x position. When `xref` is set to `paper`, units are sized relative to the plot height. See `xref` for more info" + }, + "y": { + "valType": "any", + "role": "info", + "dflt": 0, + "editType": "arraydraw", + "description": "Sets the image's y position. When `yref` is set to `paper`, units are sized relative to the plot height. See `yref` for more info" + }, + "xanchor": { + "valType": "enumerated", + "values": [ + "left", + "center", + "right" + ], + "dflt": "left", + "role": "info", + "editType": "arraydraw", + "description": "Sets the anchor for the x position" + }, + "yanchor": { + "valType": "enumerated", + "values": [ + "top", + "middle", + "bottom" + ], + "dflt": "top", + "role": "info", + "editType": "arraydraw", + "description": "Sets the anchor for the y position." + }, + "xref": { + "valType": "enumerated", + "values": [ + "paper", + "/^x([2-9]|[1-9][0-9]+)?$/" + ], + "dflt": "paper", + "role": "info", + "editType": "arraydraw", + "description": "Sets the images's x coordinate axis. If set to a x axis id (e.g. *x* or *x2*), the `x` position refers to an x data coordinate If set to *paper*, the `x` position refers to the distance from the left of plot in normalized coordinates where *0* (*1*) corresponds to the left (right)." + }, + "yref": { + "valType": "enumerated", + "values": [ + "paper", + "/^y([2-9]|[1-9][0-9]+)?$/" + ], + "dflt": "paper", + "role": "info", + "editType": "arraydraw", + "description": "Sets the images's y coordinate axis. If set to a y axis id (e.g. *y* or *y2*), the `y` position refers to a y data coordinate. If set to *paper*, the `y` position refers to the distance from the bottom of the plot in normalized coordinates where *0* (*1*) corresponds to the bottom (top)." + }, + "editType": "arraydraw", + "role": "object" + } + }, + "role": "object" + }, + "updatemenus": { + "items": { + "updatemenu": { + "_arrayAttrRegexps": [ + {} + ], + "visible": { + "valType": "boolean", + "role": "info", + "description": "Determines whether or not the update menu is visible.", + "editType": "arraydraw" + }, + "type": { + "valType": "enumerated", + "values": [ + "dropdown", + "buttons" + ], + "dflt": "dropdown", + "role": "info", + "description": "Determines whether the buttons are accessible via a dropdown menu or whether the buttons are stacked horizontally or vertically", + "editType": "arraydraw" + }, + "direction": { + "valType": "enumerated", + "values": [ + "left", + "right", + "up", + "down" + ], + "dflt": "down", + "role": "info", + "description": "Determines the direction in which the buttons are laid out, whether in a dropdown menu or a row/column of buttons. For `left` and `up`, the buttons will still appear in left-to-right or top-to-bottom order respectively.", + "editType": "arraydraw" + }, + "active": { + "valType": "integer", + "role": "info", + "min": -1, + "dflt": 0, + "description": "Determines which button (by index starting from 0) is considered active.", + "editType": "arraydraw" + }, + "showactive": { + "valType": "boolean", + "role": "info", + "dflt": true, + "description": "Highlights active dropdown item or active button if true.", + "editType": "arraydraw" + }, + "buttons": { + "items": { + "button": { + "method": { + "valType": "enumerated", + "values": [ + "restyle", + "relayout", + "animate", + "update", + "skip" + ], + "dflt": "restyle", + "role": "info", + "description": "Sets the Plotly method to be called on click. If the `skip` method is used, the API updatemenu will function as normal but will perform no API calls and will not bind automatically to state updates. This may be used to create a component interface and attach to updatemenu events manually via JavaScript.", + "editType": "arraydraw" + }, + "args": { + "valType": "info_array", + "role": "info", + "freeLength": true, + "items": [ + { + "valType": "any", + "editType": "arraydraw" + }, + { + "valType": "any", + "editType": "arraydraw" + }, + { + "valType": "any", + "editType": "arraydraw" + } + ], + "description": "Sets the arguments values to be passed to the Plotly method set in `method` on click.", + "editType": "arraydraw" + }, + "label": { + "valType": "string", + "role": "info", + "dflt": "", + "description": "Sets the text label to appear on the button.", + "editType": "arraydraw" + }, + "execute": { + "valType": "boolean", + "role": "info", + "dflt": true, + "description": "When true, the API method is executed. When false, all other behaviors are the same and command execution is skipped. This may be useful when hooking into, for example, the `plotly_buttonclicked` method and executing the API command manually without losing the benefit of the updatemenu automatically binding to the state of the plot through the specification of `method` and `args`.", + "editType": "arraydraw" + }, + "editType": "arraydraw", + "role": "object" + } + }, + "role": "object" + }, + "x": { + "valType": "number", + "min": -2, + "max": 3, + "dflt": -0.05, + "role": "style", + "description": "Sets the x position (in normalized coordinates) of the update menu.", + "editType": "arraydraw" + }, + "xanchor": { + "valType": "enumerated", + "values": [ + "auto", + "left", + "center", + "right" + ], + "dflt": "right", + "role": "info", + "description": "Sets the update menu's horizontal position anchor. This anchor binds the `x` position to the *left*, *center* or *right* of the range selector.", + "editType": "arraydraw" + }, + "y": { + "valType": "number", + "min": -2, + "max": 3, + "dflt": 1, + "role": "style", + "description": "Sets the y position (in normalized coordinates) of the update menu.", + "editType": "arraydraw" + }, + "yanchor": { + "valType": "enumerated", + "values": [ + "auto", + "top", + "middle", + "bottom" + ], + "dflt": "top", + "role": "info", + "description": "Sets the update menu's vertical position anchor This anchor binds the `y` position to the *top*, *middle* or *bottom* of the range selector.", + "editType": "arraydraw" + }, + "pad": { + "t": { + "valType": "number", + "dflt": 0, + "role": "style", + "editType": "arraydraw", + "description": "The amount of padding (in px) along the top of the component." + }, + "r": { + "valType": "number", + "dflt": 0, + "role": "style", + "editType": "arraydraw", + "description": "The amount of padding (in px) on the right side of the component." + }, + "b": { + "valType": "number", + "dflt": 0, + "role": "style", + "editType": "arraydraw", + "description": "The amount of padding (in px) along the bottom of the component." + }, + "l": { + "valType": "number", + "dflt": 0, + "role": "style", + "editType": "arraydraw", + "description": "The amount of padding (in px) on the left side of the component." + }, + "editType": "arraydraw", + "description": "Sets the padding around the buttons or dropdown menu.", + "role": "object" + }, + "font": { + "family": { + "valType": "string", + "role": "style", + "noBlank": true, + "strict": true, + "description": "HTML font family - the typeface that will be applied by the web browser. The web browser will only be able to apply a font if it is available on the system which it operates. Provide multiple font families, separated by commas, to indicate the preference in which to apply fonts if they aren't available on the system. The plotly service (at https://plot.ly or on-premise) generates images on a server, where only a select number of fonts are installed and supported. These include *Arial*, *Balto*, *Courier New*, *Droid Sans*,, *Droid Serif*, *Droid Sans Mono*, *Gravitas One*, *Old Standard TT*, *Open Sans*, *Overpass*, *PT Sans Narrow*, *Raleway*, *Times New Roman*.", + "editType": "arraydraw" + }, + "size": { + "valType": "number", + "role": "style", + "min": 1, + "editType": "arraydraw" + }, + "color": { + "valType": "color", + "role": "style", + "editType": "arraydraw" + }, + "description": "Sets the font of the update menu button text.", + "editType": "arraydraw", + "role": "object" + }, + "bgcolor": { + "valType": "color", + "role": "style", + "description": "Sets the background color of the update menu buttons.", + "editType": "arraydraw" + }, + "bordercolor": { + "valType": "color", + "dflt": "#BEC8D9", + "role": "style", + "description": "Sets the color of the border enclosing the update menu.", + "editType": "arraydraw" + }, + "borderwidth": { + "valType": "number", + "min": 0, + "dflt": 1, + "role": "style", + "editType": "arraydraw", + "description": "Sets the width (in px) of the border enclosing the update menu." + }, + "editType": "arraydraw", + "role": "object" + } + }, + "role": "object" + }, + "sliders": { + "items": { + "slider": { + "visible": { + "valType": "boolean", + "role": "info", + "dflt": true, + "description": "Determines whether or not the slider is visible.", + "editType": "arraydraw" + }, + "active": { + "valType": "number", + "role": "info", + "min": 0, + "dflt": 0, + "description": "Determines which button (by index starting from 0) is considered active.", + "editType": "arraydraw" + }, + "steps": { + "items": { + "step": { + "method": { + "valType": "enumerated", + "values": [ + "restyle", + "relayout", + "animate", + "update", + "skip" + ], + "dflt": "restyle", + "role": "info", + "description": "Sets the Plotly method to be called when the slider value is changed. If the `skip` method is used, the API slider will function as normal but will perform no API calls and will not bind automatically to state updates. This may be used to create a component interface and attach to slider events manually via JavaScript.", + "editType": "arraydraw" + }, + "args": { + "valType": "info_array", + "role": "info", + "freeLength": true, + "items": [ + { + "valType": "any", + "editType": "arraydraw" + }, + { + "valType": "any", + "editType": "arraydraw" + }, + { + "valType": "any", + "editType": "arraydraw" + } + ], + "description": "Sets the arguments values to be passed to the Plotly method set in `method` on slide.", + "editType": "arraydraw" + }, + "label": { + "valType": "string", + "role": "info", + "description": "Sets the text label to appear on the slider", + "editType": "arraydraw" + }, + "value": { + "valType": "string", + "role": "info", + "description": "Sets the value of the slider step, used to refer to the step programatically. Defaults to the slider label if not provided.", + "editType": "arraydraw" + }, + "execute": { + "valType": "boolean", + "role": "info", + "dflt": true, + "description": "When true, the API method is executed. When false, all other behaviors are the same and command execution is skipped. This may be useful when hooking into, for example, the `plotly_sliderchange` method and executing the API command manually without losing the benefit of the slider automatically binding to the state of the plot through the specification of `method` and `args`.", + "editType": "arraydraw" + }, + "editType": "arraydraw", + "role": "object" + } + }, + "role": "object" + }, + "lenmode": { + "valType": "enumerated", + "values": [ + "fraction", + "pixels" + ], + "role": "info", + "dflt": "fraction", + "description": "Determines whether this slider length is set in units of plot *fraction* or in *pixels. Use `len` to set the value.", + "editType": "arraydraw" + }, + "len": { + "valType": "number", + "min": 0, + "dflt": 1, + "role": "style", + "description": "Sets the length of the slider This measure excludes the padding of both ends. That is, the slider's length is this length minus the padding on both ends.", + "editType": "arraydraw" + }, + "x": { + "valType": "number", + "min": -2, + "max": 3, + "dflt": 0, + "role": "style", + "description": "Sets the x position (in normalized coordinates) of the slider.", + "editType": "arraydraw" + }, + "pad": { + "t": { + "valType": "number", + "dflt": 20, + "role": "style", + "editType": "arraydraw", + "description": "The amount of padding (in px) along the top of the component." + }, + "r": { + "valType": "number", + "dflt": 0, + "role": "style", + "editType": "arraydraw", + "description": "The amount of padding (in px) on the right side of the component." + }, + "b": { + "valType": "number", + "dflt": 0, + "role": "style", + "editType": "arraydraw", + "description": "The amount of padding (in px) along the bottom of the component." + }, + "l": { + "valType": "number", + "dflt": 0, + "role": "style", + "editType": "arraydraw", + "description": "The amount of padding (in px) on the left side of the component." + }, + "editType": "arraydraw", + "description": "Set the padding of the slider component along each side.", + "role": "object" + }, + "xanchor": { + "valType": "enumerated", + "values": [ + "auto", + "left", + "center", + "right" + ], + "dflt": "left", + "role": "info", + "description": "Sets the slider's horizontal position anchor. This anchor binds the `x` position to the *left*, *center* or *right* of the range selector.", + "editType": "arraydraw" + }, + "y": { + "valType": "number", + "min": -2, + "max": 3, + "dflt": 0, + "role": "style", + "description": "Sets the y position (in normalized coordinates) of the slider.", + "editType": "arraydraw" + }, + "yanchor": { + "valType": "enumerated", + "values": [ + "auto", + "top", + "middle", + "bottom" + ], + "dflt": "top", + "role": "info", + "description": "Sets the slider's vertical position anchor This anchor binds the `y` position to the *top*, *middle* or *bottom* of the range selector.", + "editType": "arraydraw" + }, + "transition": { + "duration": { + "valType": "number", + "role": "info", + "min": 0, + "dflt": 150, + "description": "Sets the duration of the slider transition", + "editType": "arraydraw" + }, + "easing": { + "valType": "enumerated", + "values": [ + "linear", + "quad", + "cubic", + "sin", + "exp", + "circle", + "elastic", + "back", + "bounce", + "linear-in", + "quad-in", + "cubic-in", + "sin-in", + "exp-in", + "circle-in", + "elastic-in", + "back-in", + "bounce-in", + "linear-out", + "quad-out", + "cubic-out", + "sin-out", + "exp-out", + "circle-out", + "elastic-out", + "back-out", + "bounce-out", + "linear-in-out", + "quad-in-out", + "cubic-in-out", + "sin-in-out", + "exp-in-out", + "circle-in-out", + "elastic-in-out", + "back-in-out", + "bounce-in-out" + ], + "role": "info", + "dflt": "cubic-in-out", + "description": "Sets the easing function of the slider transition", + "editType": "arraydraw" + }, + "editType": "arraydraw", + "role": "object" + }, + "currentvalue": { + "visible": { + "valType": "boolean", + "role": "info", + "dflt": true, + "description": "Shows the currently-selected value above the slider.", + "editType": "arraydraw" + }, + "xanchor": { + "valType": "enumerated", + "values": [ + "left", + "center", + "right" + ], + "dflt": "left", + "role": "info", + "description": "The alignment of the value readout relative to the length of the slider.", + "editType": "arraydraw" + }, + "offset": { + "valType": "number", + "dflt": 10, + "role": "info", + "description": "The amount of space, in pixels, between the current value label and the slider.", + "editType": "arraydraw" + }, + "prefix": { + "valType": "string", + "role": "info", + "description": "When currentvalue.visible is true, this sets the prefix of the label.", + "editType": "arraydraw" + }, + "suffix": { + "valType": "string", + "role": "info", + "description": "When currentvalue.visible is true, this sets the suffix of the label.", + "editType": "arraydraw" + }, + "font": { + "family": { + "valType": "string", + "role": "style", + "noBlank": true, + "strict": true, + "description": "HTML font family - the typeface that will be applied by the web browser. The web browser will only be able to apply a font if it is available on the system which it operates. Provide multiple font families, separated by commas, to indicate the preference in which to apply fonts if they aren't available on the system. The plotly service (at https://plot.ly or on-premise) generates images on a server, where only a select number of fonts are installed and supported. These include *Arial*, *Balto*, *Courier New*, *Droid Sans*,, *Droid Serif*, *Droid Sans Mono*, *Gravitas One*, *Old Standard TT*, *Open Sans*, *Overpass*, *PT Sans Narrow*, *Raleway*, *Times New Roman*.", + "editType": "arraydraw" + }, + "size": { + "valType": "number", + "role": "style", + "min": 1, + "editType": "arraydraw" + }, + "color": { + "valType": "color", + "role": "style", + "editType": "arraydraw" + }, + "description": "Sets the font of the current value label text.", + "editType": "arraydraw", + "role": "object" + }, + "editType": "arraydraw", + "role": "object" + }, + "font": { + "family": { + "valType": "string", + "role": "style", + "noBlank": true, + "strict": true, + "description": "HTML font family - the typeface that will be applied by the web browser. The web browser will only be able to apply a font if it is available on the system which it operates. Provide multiple font families, separated by commas, to indicate the preference in which to apply fonts if they aren't available on the system. The plotly service (at https://plot.ly or on-premise) generates images on a server, where only a select number of fonts are installed and supported. These include *Arial*, *Balto*, *Courier New*, *Droid Sans*,, *Droid Serif*, *Droid Sans Mono*, *Gravitas One*, *Old Standard TT*, *Open Sans*, *Overpass*, *PT Sans Narrow*, *Raleway*, *Times New Roman*.", + "editType": "arraydraw" + }, + "size": { + "valType": "number", + "role": "style", + "min": 1, + "editType": "arraydraw" + }, + "color": { + "valType": "color", + "role": "style", + "editType": "arraydraw" + }, + "description": "Sets the font of the slider step labels.", + "editType": "arraydraw", + "role": "object" + }, + "activebgcolor": { + "valType": "color", + "role": "style", + "dflt": "#dbdde0", + "description": "Sets the background color of the slider grip while dragging.", + "editType": "arraydraw" + }, + "bgcolor": { + "valType": "color", + "role": "style", + "dflt": "#f8fafc", + "description": "Sets the background color of the slider.", + "editType": "arraydraw" + }, + "bordercolor": { + "valType": "color", + "dflt": "#bec8d9", + "role": "style", + "description": "Sets the color of the border enclosing the slider.", + "editType": "arraydraw" + }, + "borderwidth": { + "valType": "number", + "min": 0, + "dflt": 1, + "role": "style", + "description": "Sets the width (in px) of the border enclosing the slider.", + "editType": "arraydraw" + }, + "ticklen": { + "valType": "number", + "min": 0, + "dflt": 7, + "role": "style", + "description": "Sets the length in pixels of step tick marks", + "editType": "arraydraw" + }, + "tickcolor": { + "valType": "color", + "dflt": "#333", + "role": "style", + "description": "Sets the color of the border enclosing the slider.", + "editType": "arraydraw" + }, + "tickwidth": { + "valType": "number", + "min": 0, + "dflt": 1, + "role": "style", + "description": "Sets the tick width (in px).", + "editType": "arraydraw" + }, + "minorticklen": { + "valType": "number", + "min": 0, + "dflt": 4, + "role": "style", + "description": "Sets the length in pixels of minor step tick marks", + "editType": "arraydraw" + }, + "editType": "arraydraw", + "role": "object" + } + }, + "role": "object" + } + } + }, + "transforms": { + "ohlc": { + "attributes": {} + }, + "candlestick": { + "attributes": {} + }, + "aggregate": { + "attributes": { + "enabled": { + "valType": "boolean", + "dflt": true, + "role": "info", + "editType": "calc", + "description": "Determines whether this aggregate transform is enabled or disabled." + }, + "groups": { + "valType": "string", + "strict": true, + "noBlank": true, + "arrayOk": true, + "dflt": "x", + "role": "info", + "editType": "calc", + "description": "Sets the grouping target to which the aggregation is applied. Data points with matching group values will be coalesced into one point, using the supplied aggregation functions to reduce data in other data arrays. If a string, `groups` is assumed to be a reference to a data array in the parent trace object. To aggregate by nested variables, use *.* to access them. For example, set `groups` to *marker.color* to aggregate about the marker color array. If an array, `groups` is itself the data array by which we aggregate." + }, + "aggregations": { + "items": { + "aggregation": { + "target": { + "valType": "string", + "role": "info", + "editType": "calc", + "description": "A reference to the data array in the parent trace to aggregate. To aggregate by nested variables, use *.* to access them. For example, set `groups` to *marker.color* to aggregate over the marker color array. The referenced array must already exist, unless `func` is *count*, and each array may only be referenced once." + }, + "func": { + "valType": "enumerated", + "values": [ + "count", + "sum", + "avg", + "median", + "mode", + "rms", + "stddev", + "min", + "max", + "first", + "last" + ], + "dflt": "first", + "role": "info", + "editType": "calc", + "description": "Sets the aggregation function. All values from the linked `target`, corresponding to the same value in the `groups` array, are collected and reduced by this function. *count* is simply the number of values in the `groups` array, so does not even require the linked array to exist. *first* (*last*) is just the first (last) linked value. Invalid values are ignored, so for example in *avg* they do not contribute to either the numerator or the denominator. Any data type (numeric, date, category) may be aggregated with any function, even though in certain cases it is unlikely to make sense, for example a sum of dates or average of categories. *median* will return the average of the two central values if there is an even count. *mode* will return the first value to reach the maximum count, in case of a tie." + }, + "funcmode": { + "valType": "enumerated", + "values": [ + "sample", + "population" + ], + "dflt": "sample", + "role": "info", + "editType": "calc", + "description": "*stddev* supports two formula variants: *sample* (normalize by N-1) and *population* (normalize by N)." + }, + "enabled": { + "valType": "boolean", + "dflt": true, + "role": "info", + "editType": "calc", + "description": "Determines whether this aggregation function is enabled or disabled." + }, + "editType": "calc", + "role": "object" + } + }, + "role": "object" + }, + "editType": "calc", + "groupssrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for groups .", + "editType": "none" + } + } + }, + "filter": { + "attributes": { + "enabled": { + "valType": "boolean", + "dflt": true, + "role": "info", + "editType": "calc", + "description": "Determines whether this filter transform is enabled or disabled." + }, + "target": { + "valType": "string", + "strict": true, + "noBlank": true, + "arrayOk": true, + "dflt": "x", + "role": "info", + "editType": "calc", + "description": "Sets the filter target by which the filter is applied. If a string, `target` is assumed to be a reference to a data array in the parent trace object. To filter about nested variables, use *.* to access them. For example, set `target` to *marker.color* to filter about the marker color array. If an array, `target` is then the data array by which the filter is applied." + }, + "operation": { + "valType": "enumerated", + "values": [ + "=", + "!=", + "<", + ">=", + ">", + "<=", + "[]", + "()", + "[)", + "(]", + "][", + ")(", + "](", + ")[", + "{}", + "}{" + ], + "dflt": "=", + "role": "info", + "editType": "calc", + "description": "Sets the filter operation. *=* keeps items equal to `value` *!=* keeps items not equal to `value` *<* keeps items less than `value` *<=* keeps items less than or equal to `value` *>* keeps items greater than `value` *>=* keeps items greater than or equal to `value` *[]* keeps items inside `value[0]` to value[1]` including both bounds` *()* keeps items inside `value[0]` to value[1]` excluding both bounds` *[)* keeps items inside `value[0]` to value[1]` including `value[0]` but excluding `value[1] *(]* keeps items inside `value[0]` to value[1]` excluding `value[0]` but including `value[1] *][* keeps items outside `value[0]` to value[1]` and equal to both bounds` *)(* keeps items outside `value[0]` to value[1]` *](* keeps items outside `value[0]` to value[1]` and equal to `value[0]` *)[* keeps items outside `value[0]` to value[1]` and equal to `value[1]` *{}* keeps items present in a set of values *}{* keeps items not present in a set of values" + }, + "value": { + "valType": "any", + "dflt": 0, + "role": "info", + "editType": "calc", + "description": "Sets the value or values by which to filter. Values are expected to be in the same type as the data linked to `target`. When `operation` is set to one of the comparison values (=,!=,<,>=,>,<=) `value` is expected to be a number or a string. When `operation` is set to one of the interval values ([],(),[),(],][,)(,](,)[) `value` is expected to be 2-item array where the first item is the lower bound and the second item is the upper bound. When `operation`, is set to one of the set values ({},}{) `value` is expected to be an array with as many items as the desired set elements." + }, + "preservegaps": { + "valType": "boolean", + "dflt": false, + "role": "info", + "editType": "calc", + "description": "Determines whether or not gaps in data arrays produced by the filter operation are preserved. Setting this to *true* might be useful when plotting a line chart with `connectgaps` set to *false*." + }, + "editType": "calc", + "valuecalendar": { + "valType": "enumerated", + "values": [ + "gregorian", + "chinese", + "coptic", + "discworld", + "ethiopian", + "hebrew", + "islamic", + "julian", + "mayan", + "nanakshahi", + "nepali", + "persian", + "jalali", + "taiwan", + "thai", + "ummalqura" + ], + "role": "info", + "editType": "calc", + "dflt": "gregorian", + "description": "Sets the calendar system to use for `value`, if it is a date." + }, + "targetcalendar": { + "valType": "enumerated", + "values": [ + "gregorian", + "chinese", + "coptic", + "discworld", + "ethiopian", + "hebrew", + "islamic", + "julian", + "mayan", + "nanakshahi", + "nepali", + "persian", + "jalali", + "taiwan", + "thai", + "ummalqura" + ], + "role": "info", + "editType": "calc", + "dflt": "gregorian", + "description": "Sets the calendar system to use for `target`, if it is an array of dates. If `target` is a string (eg *x*) we use the corresponding trace attribute (eg `xcalendar`) if it exists, even if `targetcalendar` is provided." + }, + "targetsrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for target .", + "editType": "none" + } + } + }, + "groupby": { + "attributes": { + "enabled": { + "valType": "boolean", + "dflt": true, + "role": "info", + "editType": "calc", + "description": "Determines whether this group-by transform is enabled or disabled." + }, + "groups": { + "valType": "data_array", + "dflt": [], + "role": "data", + "editType": "calc", + "description": "Sets the groups in which the trace data will be split. For example, with `x` set to *[1, 2, 3, 4]* and `groups` set to *['a', 'b', 'a', 'b']*, the groupby transform with split in one trace with `x` [1, 3] and one trace with `x` [2, 4]." + }, + "nameformat": { + "valType": "string", + "role": "info", + "editType": "calc", + "description": "Pattern by which grouped traces are named. If only one trace is present, defaults to the group name (`\"%{group}\"`), otherwise defaults to the group name with trace name (`\"%{group} (%{trace})\"`). Available escape sequences are `%{group}`, which inserts the group name, and `%{trace}`, which inserts the trace name. If grouping GDP data by country when more than one trace is present, for example, the default \"%{group} (%{trace})\" would return \"Monaco (GDP per capita)\"." + }, + "styles": { + "items": { + "style": { + "target": { + "valType": "string", + "role": "info", + "editType": "calc", + "description": "The group value which receives these styles." + }, + "value": { + "valType": "any", + "role": "info", + "dflt": {}, + "editType": "calc", + "description": "Sets each group styles. For example, with `groups` set to *['a', 'b', 'a', 'b']* and `styles` set to *[{target: 'a', value: { marker: { color: 'red' } }}] marker points in group *'a'* will be drawn in red." + }, + "editType": "calc", + "role": "object" + } + }, + "role": "object" + }, + "editType": "calc", + "groupssrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for groups .", + "editType": "none" + } + } + }, + "sort": { + "attributes": { + "enabled": { + "valType": "boolean", + "dflt": true, + "role": "info", + "editType": "calc", + "description": "Determines whether this sort transform is enabled or disabled." + }, + "target": { + "valType": "string", + "strict": true, + "noBlank": true, + "arrayOk": true, + "dflt": "x", + "role": "info", + "editType": "calc", + "description": "Sets the target by which the sort transform is applied. If a string, *target* is assumed to be a reference to a data array in the parent trace object. To sort about nested variables, use *.* to access them. For example, set `target` to *marker.size* to sort about the marker size array. If an array, *target* is then the data array by which the sort transform is applied." + }, + "order": { + "valType": "enumerated", + "values": [ + "ascending", + "descending" + ], + "dflt": "ascending", + "role": "info", + "editType": "calc", + "description": "Sets the sort transform order." + }, + "editType": "calc", + "targetsrc": { + "valType": "string", + "role": "info", + "description": "Sets the source reference on plot.ly for target .", + "editType": "none" + } + } + } + }, + "frames": { + "items": { + "frames_entry": { + "group": { + "valType": "string", + "role": "info", + "description": "An identifier that specifies the group to which the frame belongs, used by animate to select a subset of frames." + }, + "name": { + "valType": "string", + "role": "info", + "description": "A label by which to identify the frame" + }, + "traces": { + "valType": "any", + "role": "info", + "description": "A list of trace indices that identify the respective traces in the data attribute" + }, + "baseframe": { + "valType": "string", + "role": "info", + "description": "The name of the frame into which this frame's properties are merged before applying. This is used to unify properties and avoid needing to specify the same values for the same properties in multiple frames." + }, + "data": { + "valType": "any", + "role": "object", + "description": "A list of traces this frame modifies. The format is identical to the normal trace definition." + }, + "layout": { + "valType": "any", + "role": "object", + "description": "Layout properties which this frame modifies. The format is identical to the normal layout definition." + }, + "role": "object" + } + }, + "role": "object" + }, + "animation": { + "mode": { + "valType": "enumerated", + "dflt": "afterall", + "role": "info", + "values": [ + "immediate", + "next", + "afterall" + ], + "description": "Describes how a new animate call interacts with currently-running animations. If `immediate`, current animations are interrupted and the new animation is started. If `next`, the current frame is allowed to complete, after which the new animation is started. If `afterall` all existing frames are animated to completion before the new animation is started." + }, + "direction": { + "valType": "enumerated", + "role": "info", + "values": [ + "forward", + "reverse" + ], + "dflt": "forward", + "description": "The direction in which to play the frames triggered by the animation call" + }, + "fromcurrent": { + "valType": "boolean", + "dflt": false, + "role": "info", + "description": "Play frames starting at the current frame instead of the beginning." + }, + "frame": { + "duration": { + "valType": "number", + "role": "info", + "min": 0, + "dflt": 500, + "description": "The duration in milliseconds of each frame. If greater than the frame duration, it will be limited to the frame duration." + }, + "redraw": { + "valType": "boolean", + "role": "info", + "dflt": true, + "description": "Redraw the plot at completion of the transition. This is desirable for transitions that include properties that cannot be transitioned, but may significantly slow down updates that do not require a full redraw of the plot" + }, + "role": "object" + }, + "transition": { + "duration": { + "valType": "number", + "role": "info", + "min": 0, + "dflt": 500, + "description": "The duration of the transition, in milliseconds. If equal to zero, updates are synchronous." + }, + "easing": { + "valType": "enumerated", + "dflt": "cubic-in-out", + "values": [ + "linear", + "quad", + "cubic", + "sin", + "exp", + "circle", + "elastic", + "back", + "bounce", + "linear-in", + "quad-in", + "cubic-in", + "sin-in", + "exp-in", + "circle-in", + "elastic-in", + "back-in", + "bounce-in", + "linear-out", + "quad-out", + "cubic-out", + "sin-out", + "exp-out", + "circle-out", + "elastic-out", + "back-out", + "bounce-out", + "linear-in-out", + "quad-in-out", + "cubic-in-out", + "sin-in-out", + "exp-in-out", + "circle-in-out", + "elastic-in-out", + "back-in-out", + "bounce-in-out" + ], + "role": "info", + "description": "The easing function used for the transition" + }, + "role": "object" + } + } +} \ No newline at end of file diff --git a/ipyplotly/codegen/utils.py b/ipyplotly/codegen/utils.py new file mode 100644 index 00000000000..614aedf40af --- /dev/null +++ b/ipyplotly/codegen/utils.py @@ -0,0 +1,521 @@ +import importlib +import inspect +import textwrap +from typing import List, Dict + +from io import StringIO +from yapf.yapflib.yapf_api import FormatCode + +from ipyplotly.basevalidators import BaseValidator, CompoundValidator, CompoundArrayValidator + + +def format_source(validator_source): + formatted_source, _ = FormatCode(validator_source, + style_config={'based_on_style': 'google', + 'DEDENT_CLOSING_BRACKETS': True, + 'COLUMN_LIMIT': 119}) + return formatted_source + + +custom_validator_datatypes = { + 'layout.image.source': 'ipyplotly.basevalidators.ImageUriValidator', + 'frame.data': 'ipyplotly.validators.DataValidator', + 'frame.layout': 'ipyplotly.validators.LayoutValidator' +} + +class PlotlyNode: + + # Constructor + # ----------- + def __init__(self, plotly_schema, node_path=(), parent=None): + self.plotly_schema = plotly_schema + if isinstance(node_path, str): + node_path = (node_path,) + self.node_path = node_path + + # Compute children + if isinstance(self.node_data, dict): + self._children = [self.__class__(self.plotly_schema, + node_path=self.node_path + (c,), + parent=self) + for c in self.node_data if c and c[0] != '_'] + else: + self._children = [] + + # Parent + self._parent = parent + + def __repr__(self): + return self.dir_str + + # Abstract methods + # ---------------- + @property + def node_data(self) -> dict: + raise NotImplementedError() + + @property + def description(self) -> str: + raise NotImplementedError() + + @property + def base_datatype_class(self): + raise NotImplementedError + + # Names + # ----- + @property + def base_name(self): + raise NotImplementedError() + + @property + def plotly_name(self) -> str: + if len(self.node_path) == 0: + return self.base_name + else: + return self.node_path[-1] + + @property + def name_pascal_case(self) -> str: + return self.plotly_name.title().replace('_', '') + + @property + def name_undercase(self) -> str: + if not self.plotly_name: + # Empty plotly_name + return self.plotly_name + + # Lowercase leading char + # ---------------------- + name1 = self.plotly_name[0].lower() + self.plotly_name[1:] + + # Replace capital chars by underscore-lower + # ----------------------------------------- + name2 = ''.join([('' if not c.isupper() else '_') + c.lower() for c in name1]) + + return name2 + + @property + def name_property(self) -> str: + return self.plotly_name + ('s' if self.is_array_element else '') + + @property + def name_validator(self) -> str: + return self.name_pascal_case + ('s' if self.is_array_element else '') + 'Validator' + + @property + def name_base_validator(self) -> str: + if self.dir_str in custom_validator_datatypes: + validator_base = f"{custom_validator_datatypes[self.dir_str]}" + else: + validator_base = f"ipyplotly.basevalidators.{self.datatype_pascal_case}Validator" + + return validator_base + + def get_constructor_params_docstring(self, indent=12, extra_nodes=[]): + assert self.is_compound + + buffer = StringIO() + + subtype_nodes = self.child_datatypes + extra_nodes + for subtype_node in subtype_nodes: + raw_description = subtype_node.description + subtype_description = '\n'.join(textwrap.wrap(raw_description, + subsequent_indent=' ' * (indent + 4), + width=80 - (indent + 4))) + + buffer.write('\n' + ' ' * indent + subtype_node.name_property) + buffer.write('\n' + ' ' * (indent + 4) + subtype_description) + + return buffer.getvalue() + + @property + def validator_instance(self) -> BaseValidator: + + module_parts = self.name_base_validator.split('.') + module_path = '.'.join(module_parts[:-1]) + cls_name = module_parts[-1] + + validators_module = importlib.import_module(module_path) + + validator_class_list = [cls + for _, cls in inspect.getmembers(validators_module, inspect.isclass) + if cls.__name__ == cls_name] + if not validator_class_list: + raise ValueError(f"Unknown base validator '{self.name_base_validator}'") + + validator_class = validator_class_list[0] + + args = dict(plotly_name=self.name_property, parent_name=self.parent_dir_str) + + if validator_class == CompoundValidator: + data_class_str = f"" + extra_args = {'data_class': data_class_str, 'data_docs': self.get_constructor_params_docstring()} + elif validator_class == CompoundArrayValidator: + element_class_str = f"" + extra_args = {'element_class': element_class_str, 'element_docs': self.get_constructor_params_docstring()} + else: + extra_args = {n.name_undercase: n.node_data for n in self.simple_attrs} + + # Add extra properties + if self.datatype == 'color': + # Check for colorscale sibling + colorscale_node_list = [node for node in self.parent.child_datatypes + if node.datatype == 'colorscale'] + if colorscale_node_list: + colorscale_path = colorscale_node_list[0].dir_str + extra_args['colorscale_path'] = repr(colorscale_path) + + return validator_class(**args, **extra_args) + + @property + def name_class(self) -> str: + return self.name_pascal_case + + # Datatypes + # --------- + @property + def datatype(self) -> str: + if self.is_array_element: + return 'compound_array' + elif self.is_compound: + return 'compound' + elif self.is_simple: + return self.node_data.get('valType') + else: + return 'literal' + + @property + def datatype_pascal_case(self) -> str: + return self.datatype.title().replace('_', '') + + @property + def is_compound(self) -> bool: + return isinstance(self.node_data, dict) and not self.is_simple and self.plotly_name != 'impliedEdits' + + @property + def is_literal(self) -> bool: + return isinstance(self.node_data, str) + + @property + def is_simple(self) -> bool: + return isinstance(self.node_data, dict) and 'valType' in self.node_data + + @property + def is_array(self) -> bool: + return isinstance(self.node_data, dict) and \ + self.node_data.get('role', '') == 'object' and \ + 'items' in self.node_data + + @property + def is_array_element(self): + if self.parent and self.parent.parent: + return self.parent.parent.is_array + else: + return False + + @property + def is_datatype(self) -> bool: + return self.is_simple or self.is_compound + + # Node path + # --------- + def tidy_dir_path(self, p): + return p + + @property + def dir_path(self) -> List[str]: + res = [self.base_name] if self.base_name else [] + for i, p in enumerate(self.node_path): + if p == 'items' or \ + (i < len(self.node_path) - 1 and self.node_path[i+1] == 'items'): + # e.g. [parcoords, dimensions, items, dimension] -> [parcoords, dimension] + pass + else: + res.append(self.tidy_dir_path(p)) + return res + + # Node path strings + # ----------------- + @property + def dir_str(self) -> str: + return '.'.join(self.dir_path) + + @property + def parent_dir_str(self) -> str: + return '.'.join(self.dir_path[:-1]) + + @property + def pkg_str(self) -> str: + path_str = '' + for p in self.dir_path: + path_str += '.' + p + return path_str + + # Children + # -------- + @property + def children(self) -> List['PlotlyNode']: + return self._children + + @property + def simple_attrs(self) -> List['PlotlyNode']: + if not self.is_simple: + raise ValueError(f"Cannot get simple attributes of the simple object '{self.dir_str}'") + + return [n for n in self.children if n.plotly_name not in ['valType', 'description', 'role']] + + @property + def parent(self) -> 'PlotlyNode': + return self._parent + + @property + def child_datatypes(self) -> List['PlotlyNode']: + """ + Returns + ------- + children: list of TraceNode + """ + # if self.is_array: + # items_child = [c for c in self.children if c.plotly_name == 'items'][0] + # return items_child.children + # else: + nodes = [] + for n in self.children: + if n.is_array: + nodes.append(n.children[0].children[0]) + elif n.is_datatype: + nodes.append(n) + + return nodes + + @property + def child_compound_datatypes(self) -> List['PlotlyNode']: + return [n for n in self.child_datatypes if n.is_compound] + + @property + def child_simple_datatypes(self) -> List['PlotlyNode']: + return [n for n in self.child_datatypes if n.is_simple] + + @property + def child_literals(self) -> List['PlotlyNode']: + return [n for n in self.children if n.is_literal] + + # Static helpers + # -------------- + @staticmethod + def get_all_compound_datatype_nodes(plotly_schema, node_class) -> List['PlotlyNode']: + nodes = [] + nodes_to_process = [node_class(plotly_schema)] + + while nodes_to_process: + node = nodes_to_process.pop() + + if not node.is_array: + nodes.append(node) + + nodes_to_process.extend(node.child_compound_datatypes) + + return nodes + + @staticmethod + def get_all_trace_layout_nodes(plotly_schema) -> Dict[str, 'LayoutNode']: + trace_names = plotly_schema['traces'].keys() + + datatype_nodes = {} + nodes_to_process = [TraceLayoutNode(plotly_schema, trace_name) + for trace_name in trace_names] + + while nodes_to_process: + parent_node = nodes_to_process.pop() + for node in parent_node.child_simple_datatypes: + datatype_nodes[node.dir_str] = node + + return datatype_nodes + + +class TraceNode(PlotlyNode): + + # Constructor + # ----------- + def __init__(self, plotly_schema, node_path=(), parent=None): + super().__init__(plotly_schema, node_path, parent) + + @property + def base_datatype_class(self): + if len(self.node_path) == 0: + return 'BaseTraceType' + else: + return 'BaseTraceHierarchyType' + + @property + def base_name(self): + return 'trace' + + # Raw data + # -------- + @property + def node_data(self) -> dict: + if not self.node_path: + node_data = self.plotly_schema['traces'] + else: + node_data = self.plotly_schema['traces'][self.node_path[0]]['attributes'] + for prop_name in self.node_path[1:]: + node_data = node_data[prop_name] + + return node_data + + # Description + # ----------- + @property + def description(self) -> str: + if len(self.node_path) == 0: + desc = "" + elif len(self.node_path) == 1: + desc = self.plotly_schema['traces'][self.node_path[0]]['meta'].get('description', '') + else: + desc = self.node_data.get('description', '') + + if isinstance(desc, list): + desc = ''.join(desc) + + return desc + + +class LayoutNode(PlotlyNode): + + # Constructor + # ----------- + def __init__(self, plotly_schema, node_path=(), parent=None): + super().__init__(plotly_schema, node_path, parent) + + @property + def base_datatype_class(self): + if len(self.node_path) == 0: + return 'BaseLayoutType' + else: + return 'BaseLayoutHierarchyType' + + @property + def base_name(self): + return '' + + @property + def plotly_name(self) -> str: + if len(self.node_path) == 0: + return self.base_name + elif len(self.node_path) == 1: + return 'layout' # override 'layoutAttributes' + else: + return self.node_path[-1] + + def tidy_dir_path(self, p): + return 'layout' if p == 'layoutAttributes' else p + + # Description + # ----------- + @property + def description(self) -> str: + desc = self.node_data.get('description', '') + if isinstance(desc, list): + desc = ''.join(desc) + return desc + + # Raw data + # -------- + @property + def node_data(self) -> dict: + node_data = self.plotly_schema['layout'] + for prop_name in self.node_path: + node_data = node_data[prop_name] + + return node_data + + +class TraceLayoutNode(LayoutNode): + + # Constructor + # ----------- + def __init__(self, plotly_schema, trace_name=None, node_path=(), parent=None): + + # Handle trace name + assert parent is not None or trace_name is not None + if parent is not None: + trace_name = parent.trace_name + + self.trace_name = trace_name + super().__init__(plotly_schema, node_path, parent) + + @property + def base_name(self): + return 'layout' + + @property + def plotly_name(self) -> str: + if len(self.node_path) == 0: + return self.base_name + else: + return self.node_path[-1] + + # Raw data + # -------- + @property + def node_data(self) -> dict: + try: + node_data = (self.plotly_schema['traces'] + [self.trace_name]['layoutAttributes']) + + for prop_name in self.node_path: + node_data = node_data[prop_name] + + except KeyError: + node_data = [] + + return node_data + + +class FrameNode(PlotlyNode): + + # Constructor + # ----------- + def __init__(self, plotly_schema, node_path=(), parent=None): + super().__init__(plotly_schema, node_path, parent) + + @property + def base_datatype_class(self): + return 'BaseFrameHierarchyType' + + @property + def base_name(self): + return '' + + @property + def plotly_name(self) -> str: + if len(self.node_path) < 2: + return self.base_name + elif len(self.node_path) == 2: + return 'frame' # override 'frames_entry' + else: + return self.node_path[-1] + + def tidy_dir_path(self, p): + return 'frame' if p == 'frames_entry' else p + + # Description + # ----------- + @property + def description(self) -> str: + desc = self.node_data.get('description', '') + if isinstance(desc, list): + desc = ''.join(desc) + return desc + + # Raw data + # -------- + @property + def node_data(self) -> dict: + node_data = self.plotly_schema['frames'] + for prop_name in self.node_path: + node_data = node_data[prop_name] + + return node_data diff --git a/ipyplotly/codegen/validators.py b/ipyplotly/codegen/validators.py new file mode 100644 index 00000000000..cac7238cfa3 --- /dev/null +++ b/ipyplotly/codegen/validators.py @@ -0,0 +1,169 @@ +import os +import os.path as opath +import shutil +from io import StringIO +from typing import Dict + +from codegen.utils import format_source, PlotlyNode, TraceNode + +def build_validators_py(parent_node: PlotlyNode, + extra_nodes: Dict[str, 'PlotlyNode'] = {}): + + extra_subtype_nodes = [node for node_name, node in + extra_nodes.items() if + parent_node.dir_str and node_name.startswith(parent_node.dir_str)] + + datatype_nodes = parent_node.child_datatypes + extra_subtype_nodes + + if not datatype_nodes: + return None + + buffer = StringIO() + + # Imports + # ------- + # Compute needed imports + import_strs = set() + for datatype_node in datatype_nodes: + module_str = '.'.join(datatype_node.name_base_validator.split('.')[:-1]) + import_strs.add(module_str) + + for import_str in import_strs: + buffer.write(f'import {import_str}\n') + + # Check for colorscale node + # ------------------------- + colorscale_node_list = [node for node in datatype_nodes if node.datatype == 'colorscale'] + if colorscale_node_list: + colorscale_path = colorscale_node_list[0].dir_str + else: + colorscale_path = None + + # Compound datatypes loop + # ----------------------- + for datatype_node in datatype_nodes: + + parent_dir_str = datatype_node.parent_dir_str if datatype_node.parent_dir_str else 'figure' + buffer.write(f""" + +class {datatype_node.name_validator}({datatype_node.name_base_validator}): + def __init__(self, plotly_name='{datatype_node.name_property}', parent_name='{parent_dir_str}'):""") + + # Add import + if datatype_node.is_compound: + buffer.write(f""" + from ipyplotly.datatypes{parent_node.pkg_str} import {datatype_node.name_pascal_case}""") + + buffer.write(f""" + super().__init__(plotly_name=plotly_name, + parent_name=parent_name""") + + if datatype_node.is_array_element: + buffer.write(f""", + element_class={datatype_node.name_class}, + element_docs=\"\"\"{datatype_node.get_constructor_params_docstring()}\"\"\"""") + elif datatype_node.is_compound: + buffer.write(f""", + data_class={datatype_node.name_class}, + data_docs=\"\"\"{datatype_node.get_constructor_params_docstring()}\"\"\"""") + else: + assert datatype_node.is_simple + + # Exclude general properties + excluded_props = ['valType', 'description', 'role', 'dflt'] + if datatype_node.datatype == 'subplotid': + # Default is required for subplotid validator + excluded_props.remove('dflt') + + attr_nodes = [n for n in datatype_node.simple_attrs + if n.plotly_name not in excluded_props] + + attr_dict = {node.name_undercase: repr(node.node_data) for node in attr_nodes} + + # Add special properties + if datatype_node.datatype == 'color' and colorscale_path: + attr_dict['colorscale_path'] = repr(colorscale_path) + + for attr_name, attr_val in attr_dict.items(): + buffer.write(f""", + {attr_name}={attr_val}""") + + buffer.write(')') + + return buffer.getvalue() + + +def write_validator_py(outdir, + node: PlotlyNode, + extra_nodes: Dict[str, 'PlotlyNode'] = {}): + + # Generate source code + # -------------------- + validator_source = build_validators_py(node, extra_nodes) + if validator_source: + try: + formatted_source = format_source(validator_source) + except Exception as e: + print(validator_source) + raise e + + # Write file + # ---------- + filedir = opath.join(outdir, 'validators', *node.dir_path) + os.makedirs(filedir, exist_ok=True) + filepath = opath.join(filedir, '__init__.py') + + mode = 'at' if os.path.exists(filepath) else 'wt' + with open(filepath, mode) as f: + if mode == 'at': + f.write("\n\n") + f.write(formatted_source) + f.flush() + os.fsync(f.fileno()) + + +def build_traces_validator_py(base_node: TraceNode): + tracetype_nodes = base_node.child_compound_datatypes + buffer = StringIO() + + import_csv = ', '.join([tracetype_node.name_class for tracetype_node in tracetype_nodes]) + + buffer.write(f""" +class DataValidator(ipyplotly.basevalidators.BaseDataValidator): + + def __init__(self, plotly_name='data', parent_name='figure'): + from ipyplotly.datatypes.trace import ({import_csv}) + super().__init__(class_map={{ + """) + + for i, tracetype_node in enumerate(tracetype_nodes): + sfx = ',' if i < len(tracetype_nodes) else '' + + buffer.write(f""" + '{tracetype_node.name_property}': {tracetype_node.name_class}{sfx}""") + + buffer.write(""" + }, + plotly_name=plotly_name, + parent_name=parent_name)""") + + return buffer.getvalue() + + +def append_traces_validator_py(outdir, base_node: TraceNode): + + if base_node.node_path: + raise ValueError('Expected root trace node. Received node with path "%s"' % base_node.dir_str) + + source = build_traces_validator_py(base_node) + formatted_source = format_source(source) + + # Append to file + # -------------- + filepath = opath.join(outdir, '__init__.py') + + with open(filepath, 'a') as f: + f.write('\n\n') + f.write(formatted_source) + f.flush() + os.fsync(f.fileno()) diff --git a/ipyplotly/ipyplotly/__init__.py b/ipyplotly/ipyplotly/__init__.py new file mode 100644 index 00000000000..93f6fe582e0 --- /dev/null +++ b/ipyplotly/ipyplotly/__init__.py @@ -0,0 +1,12 @@ +from ._version import version_info, __version__ + + +def _jupyter_nbextension_paths(): + return [{ + 'section': 'notebook', + 'src': 'static', + 'dest': 'ipyplotly', + 'require': 'ipyplotly/extension' + }] + +__frontend_version__ = '^0.1' diff --git a/ipyplotly/ipyplotly/_version.py b/ipyplotly/ipyplotly/_version.py new file mode 100644 index 00000000000..48aee4dcc67 --- /dev/null +++ b/ipyplotly/ipyplotly/_version.py @@ -0,0 +1,6 @@ +version_info = (0, 1, 0, 'alpha', 2) + +_specifier_ = {'alpha': 'a', 'beta': 'b', 'candidate': 'rc', 'final': ''} + +__version__ = '%s.%s.%s%s'%(version_info[0], version_info[1], version_info[2], + '' if version_info[3]=='final' else _specifier_[version_info[3]]+str(version_info[4])) diff --git a/ipyplotly/ipyplotly/animation.py b/ipyplotly/ipyplotly/animation.py new file mode 100644 index 00000000000..0e7b73819f5 --- /dev/null +++ b/ipyplotly/ipyplotly/animation.py @@ -0,0 +1,52 @@ +from ipyplotly.basevalidators import EnumeratedValidator, NumberValidator + + +class EasingValidator(EnumeratedValidator): + + def __init__(self, plotly_name='easing'): + super().__init__(plotly_name=plotly_name, + parent_name='batch_animate', + values=[ + "linear", + "quad", + "cubic", + "sin", + "exp", + "circle", + "elastic", + "back", + "bounce", + "linear-in", + "quad-in", + "cubic-in", + "sin-in", + "exp-in", + "circle-in", + "elastic-in", + "back-in", + "bounce-in", + "linear-out", + "quad-out", + "cubic-out", + "sin-out", + "exp-out", + "circle-out", + "elastic-out", + "back-out", + "bounce-out", + "linear-in-out", + "quad-in-out", + "cubic-in-out", + "sin-in-out", + "exp-in-out", + "circle-in-out", + "elastic-in-out", + "back-in-out", + "bounce-in-out" + ]) + + +class DurationValidator(NumberValidator): + + def __init__(self, plotly_name='duration'): + super().__init__(plotly_name=plotly_name, parent_name='batch_animate', min=0) diff --git a/ipyplotly/ipyplotly/basedatatypes.py b/ipyplotly/ipyplotly/basedatatypes.py new file mode 100644 index 00000000000..adedc854818 --- /dev/null +++ b/ipyplotly/ipyplotly/basedatatypes.py @@ -0,0 +1,1777 @@ +import collections +import numbers +import os +import re +import typing as typ +import uuid +from contextlib import contextmanager +from copy import deepcopy +from importlib import import_module +from pprint import pprint +from urllib import parse + +import numpy as np +from plotly.offline import plot as plotlypy_plot +from traitlets import Undefined + +from ipyplotly import animation +from ipyplotly.basevalidators import CompoundValidator, CompoundArrayValidator, BaseDataValidator +from ipyplotly.callbacks import Points, BoxSelector, LassoSelector, InputState +from ipyplotly.validators.layout import (XaxisValidator, YaxisValidator, GeoValidator, + TernaryValidator, SceneValidator) + + +class BaseFigure: + + # Constructor + # ----------- + def __init__(self, data=None, layout_plotly=None, frames=None): + super().__init__() + + layout = layout_plotly + + # Traces + # ------ + from ipyplotly.validators import DataValidator + self._data_validator = DataValidator() + + if data is None: + self._data_objs = () # type: typ.Tuple[BaseTraceType] + self._data_defaults = [] + self._data = [] + else: + data = self._data_validator.validate_coerce(data) + + self._data_objs = data + self._data_defaults = [{} for trace in data] + self._data = [deepcopy(trace._props) for trace in data] + for trace in data: + trace._orphan_props.clear() + trace._parent = self + + # Layout + # ------ + from ipyplotly.validators import LayoutValidator + self._layout_validator = LayoutValidator() + + from ipyplotly.datatypes import Layout + + if layout is None: + layout = Layout() # type: Layout + else: + layout = self._layout_validator.validate_coerce(layout) + + self._layout_obj = layout + self._layout = deepcopy(self._layout_obj._props) + self._layout_obj._parent = self + self._layout_defaults = {} + + # Frames + # ------ + from ipyplotly.validators import FramesValidator + self._frames_validator = FramesValidator() + + if frames: + self._frame_objs = self._frames_validator.validate_coerce(frames) + else: + self._frame_objs = () + + # Message States + # -------------- + self._relayout_in_process = False + self._waiting_relayout_callbacks = [] + self._last_relayout_msg_id = 0 + + self._restyle_in_process = False + self._waiting_restyle_callbacks = [] + self._last_restyle_msg_id = 0 + + # View count + # ---------- + self._view_count = 0 + + # Context manager + # --------------- + self._in_batch_mode = False + self._batch_style_commands = {} # type: typ.Dict[int, typ.Dict[str, typ.Any]] + self._batch_layout_commands = {} # type: typ.Dict[str, typ.Any] + self._animation_duration_validator = animation.DurationValidator() + self._animation_easing_validator = animation.EasingValidator() + + # SVG + # --- + self._svg_requests = {} + + # Logging + # ------- + self._log_plotly_commands = False + + # Magic Methods + # ------------- + def __setitem__(self, prop, value): + if prop == 'data': + self.data = value + elif prop == 'layout': + self.layout = value + elif prop == 'frames': + self.frames = value + else: + raise KeyError(prop) + + def __getitem__(self, prop): + if prop == 'data': + return self.data + elif prop == 'layout': + return self.layout + elif prop == 'frames': + return self.frames + else: + raise KeyError(prop) + + def __contains__(self, prop): + return prop in ('data', 'layout', 'frames') + + # Data + # ---- + @property + def data(self) -> typ.Tuple['BaseTraceType']: + return self._data_objs + + @data.setter + def data(self, new_data): + + # Validate new_data + new_data = self._data_validator.validate_coerce(new_data) + + + orig_uids = [_trace['uid'] for _trace in self._data] + new_uids = [trace.uid for trace in new_data] + + invalid_uids = set(new_uids).difference(set(orig_uids)) + if invalid_uids: + raise ValueError(('The trace property of a figure may only be assigned to ' + 'a permutation of a subset of itself\n' + ' Invalid trace(s) with uid(s): {invalid_uids}').format(invalid_uids=invalid_uids)) + + # Check for duplicates + uid_counter = collections.Counter(new_uids) + duplicate_uids = [uid for uid, count in uid_counter.items() if count > 1] + if duplicate_uids: + raise ValueError(('The trace property of a figure may not be assigned ' + 'multiple copies of a trace\n' + ' Duplicate trace uid(s): {duplicate_uids}' + ).format(duplicate_uids=duplicate_uids)) + + # Compute traces to remove + remove_uids = set(orig_uids).difference(set(new_uids)) + delete_inds = [] + for i, _trace in enumerate(self._data): + if _trace['uid'] in remove_uids: + delete_inds.append(i) + + # Unparent trace object to be removed + old_trace = self.data[i] + old_trace._orphan_props.update(deepcopy(self.data[i]._props)) + old_trace._parent = None + + # Compute trace data list after removal + traces_props_post_removal = [t for t in self._data] + traces_prop_defaults_post_removal = [t for t in self._data_defaults] + orig_uids_post_removal = [trace_data['uid'] for trace_data in self._data] + + for i in reversed(delete_inds): + del traces_props_post_removal[i] + del traces_prop_defaults_post_removal[i] + del orig_uids_post_removal[i] + + if delete_inds: + relayout_msg_id = self._last_relayout_msg_id + 1 + self._last_relayout_msg_id = relayout_msg_id + self._relayout_in_process = True + + for di in reversed(delete_inds): + del self._data[di] # Modify in-place so we don't trigger serialization + + if self._log_plotly_commands: + print('Plotly.deleteTraces') + pprint(delete_inds, indent=4) + + self._py2js_deleteTraces = {'delete_inds': delete_inds, + '_relayout_msg_id ': relayout_msg_id} + self._py2js_deleteTraces = None + + # Compute move traces + new_inds = [] + + for uid in orig_uids_post_removal: + new_inds.append(new_uids.index(uid)) + + current_inds = list(range(len(traces_props_post_removal))) + + if not all([i1 == i2 for i1, i2 in zip(new_inds, current_inds)]): + + move_msg = [current_inds, new_inds] + + if self._log_plotly_commands: + print('Plotly.moveTraces') + pprint(move_msg, indent=4) + + self._py2js_moveTraces = move_msg + self._py2js_moveTraces = None + + # ### Reorder trace elements ### + # We do so in-place so we don't trigger serialization + # pprint(self._traces_data) + + # #### Remove by curr_inds in reverse order #### + moving_traces_data = [] + for ci in reversed(current_inds): + # Push moving traces data to front of list + moving_traces_data.insert(0, self._data[ci]) + del self._data[ci] + + # #### Sort new_inds and moving_traces_data by new_inds #### + new_inds, moving_traces_data = zip(*sorted(zip(new_inds, moving_traces_data))) + + # #### Insert by new_inds in forward order #### + for ni, trace_data in zip(new_inds, moving_traces_data): + self._data.insert(ni, trace_data) + + # pprint(self._traces_data) + + # Update _traces order + self._data_defaults = [_trace for i, _trace in sorted(zip(new_inds, traces_prop_defaults_post_removal))] + self._data_objs = tuple(new_data) + + def restyle(self, style, trace_indexes=None): + if trace_indexes is None: + trace_indexes = list(range(len(self.data))) + + if not isinstance(trace_indexes, (list, tuple)): + trace_indexes = [trace_indexes] + + restyle_msg = self._perform_restyle_dict(style, trace_indexes) + if restyle_msg: + self._dispatch_change_callbacks_restyle(restyle_msg, trace_indexes) + self._send_restyle_msg(restyle_msg, trace_indexes=trace_indexes) + + def _perform_restyle_dict(self, style, trace_indexes): + # Make sure trace_indexes is an array + if not isinstance(trace_indexes, list): + trace_indexes = [trace_indexes] + + restyle_data = {} # Resytyle data to send to JS side as Plotly.restylePlot() + + for raw_key, v in style.items(): + # kstr may have periods. e.g. foo.bar + key_path = self._str_to_dict_path(raw_key) + + # Properties with leading underscores passed through as-is + if raw_key.startswith('_'): + restyle_data[raw_key] = v + continue + + if not isinstance(v, list): + v = [v] + + if isinstance(v, dict): + raise ValueError('Restyling objects not supported, only individual properties\n' + ' Received: {{k}: {v}}'.format(k=raw_key, v=v)) + else: + restyle_msg_vs = [] + any_vals_changed = False + for i, trace_ind in enumerate(trace_indexes): + if trace_ind >= len(self._data): + raise ValueError('Trace index {trace_ind} out of range'.format(trace_ind=trace_ind)) + val_parent = self._data[trace_ind] + for kp, key_path_el in enumerate(key_path[:-1]): + + # Extend val_parent list if needed + if isinstance(val_parent, list) and isinstance(key_path_el, int): + while len(val_parent) <= key_path_el: + val_parent.append(None) + + elif isinstance(val_parent, dict) and key_path_el not in val_parent: + if isinstance(key_path[kp + 1], int): + val_parent[key_path_el] = [] + else: + val_parent[key_path_el] = {} + + val_parent = val_parent[key_path_el] + + last_key = key_path[-1] + + trace_v = v[i % len(v)] + + restyle_msg_vs.append(trace_v) + + if BasePlotlyType._vals_equal(trace_v, Undefined): + # Do nothing + pass + elif trace_v is None: + if isinstance(val_parent, dict) and last_key in val_parent: + val_parent.pop(last_key) + any_vals_changed = True + elif isinstance(val_parent, dict): + if last_key not in val_parent or not BasePlotlyType._vals_equal(val_parent[last_key], trace_v): + val_parent[last_key] = trace_v + any_vals_changed = True + + if any_vals_changed: + # At lease one of the values for one of the traces has changed. Update them all + restyle_data[raw_key] = restyle_msg_vs + + return restyle_data + + def _dispatch_change_callbacks_restyle(self, style, trace_indexes): + if not isinstance(trace_indexes, list): + trace_indexes = [trace_indexes] + + dispatch_plan = {t: {} for t in trace_indexes} + # e.g. {0: {(): {'obj': layout, + # 'changed_paths': [('xaxis', 'range')]}}} + + for raw_key, v in style.items(): + key_path = self._str_to_dict_path(raw_key) + + # Test whether we should remove trailing integer in path + # e.g. ('xaxis', 'range', '1') -> ('xaxis', 'range') + # We only do this if the trailing index is an integer that references a primitive value + if isinstance(key_path[-1], int) and not isinstance(v, dict): + key_path = key_path[:-1] + + for trace_ind in trace_indexes: + + parent_obj = self.data[trace_ind] + key_path_so_far = () + keys_left = key_path + + # Iterate down the key path + for next_key in key_path: + if next_key not in parent_obj: + # Not a property + break + + if isinstance(parent_obj, BasePlotlyType): + if key_path_so_far not in dispatch_plan[trace_ind]: + dispatch_plan[trace_ind][key_path_so_far] = {'obj': parent_obj, 'changed_paths': set()} + + dispatch_plan[trace_ind][key_path_so_far]['changed_paths'].add(keys_left) + + next_val = parent_obj[next_key] + elif isinstance(parent_obj, (list, tuple)): + next_val = parent_obj[next_key] + else: + # Primitive value + break + + key_path_so_far = key_path_so_far + (next_key,) + keys_left = keys_left[1:] + parent_obj = next_val + + # pprint(dispatch_plan) + for trace_ind in trace_indexes: + for p in dispatch_plan[trace_ind].values(): + obj = p['obj'] + changed_paths = p['changed_paths'] + obj._dispatch_change_callbacks(changed_paths) + + def _send_restyle_msg(self, style, trace_indexes=None): + if not isinstance(trace_indexes, (list, tuple)): + trace_indexes = [trace_indexes] + + # Add and update message ids + relayout_msg_id = self._last_relayout_msg_id + 1 + style['_relayout_msg_id'] = relayout_msg_id + self._last_relayout_msg_id = relayout_msg_id + self._relayout_in_process = True + + restyle_msg_id = self._last_restyle_msg_id + 1 + style['_restyle_msg_id'] = restyle_msg_id + self._last_restyle_msg_id = restyle_msg_id + self._restyle_in_process = True + + restyle_msg = (style, trace_indexes) + if self._log_plotly_commands: + print('Plotly.restyle') + pprint(restyle_msg, indent=4) + + self._py2js_restyle = restyle_msg + self._py2js_restyle = None + + def _restyle_child(self, child, prop, val): + + trace_index = self.data.index(child) + + if not self._in_batch_mode: + send_val = [val] + restyle = {prop: send_val} + self._dispatch_change_callbacks_restyle(restyle, trace_index) + self._send_restyle_msg(restyle, trace_indexes=trace_index) + else: + if trace_index not in self._batch_style_commands: + self._batch_style_commands[trace_index] = {} + self._batch_style_commands[trace_index][prop] = val + + def add_traces(self, data: typ.List['BaseTraceType']): + + if self._in_batch_mode: + self._batch_layout_commands.clear() + self._batch_style_commands.clear() + raise ValueError('Traces may not be added in a batch context') + + if not isinstance(data, (list, tuple)): + data = [data] + + # Validate + data = self._data_validator.validate_coerce(data) + + # Make deep copy of trace data (Optimize later if needed) + new_traces_data = [deepcopy(trace._props) for trace in data] + + # Update trace parent + for trace in data: + trace._parent = self + trace._orphan_props.clear() + + # Update python side + self._data.extend(new_traces_data) # append instead of assignment so we don't trigger serialization + self._data_defaults = self._data_defaults + [{} for trace in data] + self._data_objs = self._data_objs + data + + # Update messages + relayout_msg_id = self._last_relayout_msg_id + 1 + self._last_relayout_msg_id = relayout_msg_id + self._relayout_in_process = True + + restyle_msg_id = self._last_restyle_msg_id + 1 + self._last_restyle_msg_id = restyle_msg_id + self._restyle_in_process = True + + # Add message ids + for traces_data in new_traces_data: + traces_data['_relayout_msg_id'] = relayout_msg_id + traces_data['_restyle_msg_id'] = restyle_msg_id + + # Send to front end + if self._log_plotly_commands: + print('Plotly.addTraces') + pprint(new_traces_data, indent=4) + + add_traces_msg = new_traces_data + self._py2js_addTraces = add_traces_msg + self._py2js_addTraces = None + + return data + + def _get_child_props(self, child): + try: + trace_index = self.data.index(child) + except ValueError as _: + trace_index = None + + if trace_index is not None: + return self._data[trace_index] + elif child is self.layout: + return self._layout + else: + raise ValueError('Unrecognized child: %s' % child) + + def _get_child_prop_defaults(self, child): + try: + trace_index = self.data.index(child) + except ValueError as _: + trace_index = None + + if trace_index is not None: + return self._data_defaults[trace_index] + elif child is self.layout: + return self._layout_defaults + else: + raise ValueError('Unrecognized child: %s' % child) + + def _init_child_props(self, child): + # layout and traces dict are never None + return + + # Layout + # ------ + @property + def layout(self): + return self._layout_obj + + @layout.setter + def layout(self, new_layout): + # Validate layout + new_layout = self._layout_validator.validate_coerce(new_layout) + new_layout_data = deepcopy(new_layout._props) + + # Unparent current layout + if self._layout_obj: + old_layout_data = deepcopy(self._layout_obj._props) + self._layout_obj._orphan_props.update(old_layout_data) + self._layout_obj._parent = None + + # Parent new layout + self._layout = new_layout_data + new_layout._parent = self + self._layout_obj = new_layout + + # Notify JS side + self._send_relayout_msg(new_layout_data) + + def _relayout_child(self, child, prop, val): + send_val = val # Don't wrap in a list for relayout + + if not self._in_batch_mode: + relayout_msg = {prop: send_val} + self._dispatch_change_callbacks_relayout(relayout_msg) + self._send_relayout_msg(relayout_msg) + else: + self._batch_layout_commands[prop] = send_val + + def _send_relayout_msg(self, layout): + + if self._log_plotly_commands: + print('Plotly.relayout') + pprint(layout, indent=4) + + # Add message id + msg_id = self._last_relayout_msg_id + 1 + layout['_relayout_msg_id'] = msg_id + self._last_relayout_msg_id = msg_id + + self._py2js_relayout = layout + self._py2js_relayout = None + + + def relayout(self, layout): + relayout_msg = self._perform_relayout_dict(layout) + if relayout_msg: + self._dispatch_change_callbacks_relayout(relayout_msg) + self._send_relayout_msg(relayout_msg) + + def _perform_relayout_dict(self, relayout_data): + relayout_msg = {} # relayout data to send to JS side as Plotly.relayout() + + # Update layout_data + # print('_perform_relayout') + for raw_key, v in relayout_data.items(): + # kstr may have periods. e.g. foo.bar + key_path = self._str_to_dict_path(raw_key) + + val_parent = self._layout + for kp, key_path_el in enumerate(key_path[:-1]): + if key_path_el not in val_parent: + + # Extend val_parent list if needed + if isinstance(val_parent, list) and isinstance(key_path_el, int): + while len(val_parent) <= key_path_el: + val_parent.append(None) + + elif isinstance(val_parent, dict) and key_path_el not in val_parent: + if isinstance(key_path[kp+1], int): + val_parent[key_path_el] = [] + else: + val_parent[key_path_el] = {} + + val_parent = val_parent[key_path_el] + + last_key = key_path[-1] + # print(f'{val_parent}, {key_path}, {last_key}, {v}') + + if v is Undefined: + # Do nothing + pass + elif v is None: + if isinstance(val_parent, dict) and last_key in val_parent: + val_parent.pop(last_key) + relayout_msg[raw_key] = None + else: + if isinstance(val_parent, list): + if isinstance(last_key, int): + while(len(val_parent) <= last_key): + val_parent.append(None) + val_parent[last_key] = v + relayout_msg[raw_key] = v + elif isinstance(val_parent, dict): + if last_key not in val_parent or not BasePlotlyType._vals_equal(val_parent[last_key], v): + val_parent[last_key] = v + relayout_msg[raw_key] = v + + return relayout_msg + + def _dispatch_change_callbacks_relayout(self, relayout_msg): + dispatch_plan = {} # e.g. {(): {'obj': layout, + # 'changed_paths': [('xaxis', 'range')]}} + for raw_key, v in relayout_msg.items(): + # kstr may have periods. e.g. foo.bar + key_path = self._str_to_dict_path(raw_key) + + # Test whether we should remove trailing integer in path + # e.g. ('xaxis', 'range', '1') -> ('xaxis', 'range') + # We only do this if the trailing index is an integer that references a primitive value + if isinstance(key_path[-1], int) and not isinstance(v, dict): + key_path = key_path[:-1] + + parent_obj = self.layout + key_path_so_far = () + keys_left = key_path + + # Iterate down the key path + for next_key in key_path: + if next_key not in parent_obj: + break + + if isinstance(parent_obj, BasePlotlyType): + if key_path_so_far not in dispatch_plan: + dispatch_plan[key_path_so_far] = {'obj': parent_obj, 'changed_paths': set()} + dispatch_plan[key_path_so_far]['changed_paths'].add(keys_left) + + next_val = parent_obj[next_key] + # parent_obj._dispatch_change_callbacks(next_key, next_val) + elif isinstance(parent_obj, (list, tuple)): + next_val = parent_obj[next_key] + else: + # Primitive value + break + + key_path_so_far = key_path_so_far + (next_key,) + keys_left = keys_left[1:] + parent_obj = next_val + + # pprint(dispatch_plan) + for p in dispatch_plan.values(): + obj = p['obj'] + changed_paths = p['changed_paths'] + obj._dispatch_change_callbacks(changed_paths) + + + # Frames + # ------ + @property + def frames(self): + return self._frame_objs + + @frames.setter + def frames(self, new_frames): + # Note: Frames are not supported by the FigureWidget subclass so we only validate coerce the frames + # We don't emit any events of frame change and we don't reparent the frames + + # Validate frames + self._frame_objs = self._frames_validator.validate_coerce(new_frames) + + # Update + # ------ + def update(self, style=None, layout=None, trace_indexes=None): + + restyle_msg, relayout_msg, trace_indexes = self._perform_update_dict(style=style, + layout=layout, + trace_indexes=trace_indexes) + # Perform restyle portion of update + if restyle_msg: + self._dispatch_change_callbacks_restyle(restyle_msg, trace_indexes) + + # Perform relayout portion of update + if relayout_msg: + self._dispatch_change_callbacks_relayout(relayout_msg) + + if restyle_msg or relayout_msg: + self._send_update_msg(restyle_msg, relayout_msg, trace_indexes) + + def _perform_update_dict(self, style=None, layout=None, trace_indexes=None): + if not style and not layout: + # Nothing to do + return None, None, None + + if style is None: + style = {} + if layout is None: + layout = {} + + # Process trace indexes + if trace_indexes is None: + trace_indexes = list(range(len(self.data))) + + if not isinstance(trace_indexes, (list, tuple)): + trace_indexes = [trace_indexes] + + relayout_msg = self._perform_relayout_dict(layout) + restyle_msg = self._perform_restyle_dict(style, trace_indexes) + # print(style, trace_indexes, restyle_msg) + # pprint(self._traces_data) + return restyle_msg, relayout_msg, trace_indexes + + def _send_update_msg(self, style, layout, trace_indexes=None): + if not isinstance(trace_indexes, (list, tuple)): + trace_indexes = [trace_indexes] + + # Add restyle message id + restyle_msg_id = self._last_restyle_msg_id + 1 + style['_restyle_msg_id'] = restyle_msg_id + self._last_restyle_msg_id = restyle_msg_id + self._restyle_in_process = True + + # Add relayout message id + relayout_msg_id = self._last_relayout_msg_id + 1 + layout['_relayout_msg_id'] = relayout_msg_id + self._last_relayout_msg_id = relayout_msg_id + self._relayout_in_process = True + + update_msg = (style, layout, trace_indexes) + + if self._log_plotly_commands: + print('Plotly.update') + pprint(update_msg, indent=4) + + self._py2js_update = update_msg + self._py2js_update = None + + # Callbacks + # --------- + def on_relayout_completed(self, fn): + if self._relayout_in_process: + self._waiting_relayout_callbacks.append(fn) + else: + fn() + + def on_restyle_completed(self, fn): + if self._restyle_in_process: + self._waiting_restyle_callbacks.append(fn) + else: + fn() + + # Context managers + # ---------------- + @contextmanager + def batch_update(self): + """Hold syncing any state until the outermost context manager exits""" + if self._in_batch_mode is True: + yield + else: + try: + self._in_batch_mode = True + yield + finally: + self._in_batch_mode = False + self._send_batch_update() + + def _build_update_params_from_batch(self): + # Handle Style / Trace Indexes + # ---------------------------- + batch_style_commands = self._batch_style_commands + trace_indexes = sorted(set([trace_ind for trace_ind in batch_style_commands])) + + all_props = sorted(set([prop + for trace_style in self._batch_style_commands.values() + for prop in trace_style])) + + # Initialize style dict with all values undefined + style = {prop: [Undefined for _ in range(len(trace_indexes))] + for prop in all_props} + + # Fill in values + for trace_ind, trace_style in batch_style_commands.items(): + for trace_prop, trace_val in trace_style.items(): + style[trace_prop][trace_indexes.index(trace_ind)] = trace_val + + # Handle Layout + # ------------- + layout = self._batch_layout_commands + + return style, layout, trace_indexes + + def _send_batch_update(self): + style, layout, trace_indexes = self._build_update_params_from_batch() + self.update(style=style, layout=layout, trace_indexes=trace_indexes) + self._batch_layout_commands.clear() + self._batch_style_commands.clear() + + @contextmanager + def batch_animate(self, duration=500, easing="cubic-in-out"): + """ + Context manager to animate trace / layout updates + + Parameters + ---------- + duration : number + The duration of the transition, in milliseconds. If equal to zero, updates are synchronous. + easing : string + The easing function used for the transition. + One of: + - linear + - quad + - cubic + - sin + - exp + - circle + - elastic + - back + - bounce + - linear-in + - quad-in + - cubic-in + - sin-in + - exp-in + - circle-in + - elastic-in + - back-in + - bounce-in + - linear-out + - quad-out + - cubic-out + - sin-out + - exp-out + - circle-out + - elastic-out + - back-out + - bounce-out + - linear-in-out + - quad-in-out + - cubic-in-out + - sin-in-out + - exp-in-out + - circle-in-out + - elastic-in-out + - back-in-out + - bounce-in-ou + + Returns + ------- + None + """ + duration = self._animation_duration_validator.validate_coerce(duration) + easing = self._animation_easing_validator.validate_coerce(easing) + + if self._in_batch_mode is True: + yield + else: + try: + self._in_batch_mode = True + yield + finally: + self._in_batch_mode = False + self._send_batch_animate( + {'transition': {'duration': duration,'easing': easing}, + 'frame': {'duration': duration}}) + + def _send_batch_animate(self, animation_opts): + + # Apply commands to internal dictionaries as an update + # ---------------------------------------------------- + style, layout, trace_indexes = self._build_update_params_from_batch() + restyle_msg, relayout_msg, trace_indexes = self._perform_update_dict(style, layout, trace_indexes) + + # ### Perform restyle portion of animate ### + if restyle_msg: + self._dispatch_change_callbacks_restyle(restyle_msg, trace_indexes) + + # ### Perform relayout portion of update ### + if relayout_msg: + self._dispatch_change_callbacks_relayout(relayout_msg) + + # Convert style / trace_indexes into animate form + # ----------------------------------------------- + if self._batch_style_commands: + animate_styles, animate_trace_indexes = zip(*[ + (trace_style, trace_index) for trace_index, trace_style in self._batch_style_commands.items()]) + else: + animate_styles, animate_trace_indexes = {}, [] + + animate_layout = self._batch_layout_commands + + # Send animate message to JS + # -------------------------- + self._send_animate_msg(list(animate_styles), animate_layout, list(animate_trace_indexes), animation_opts) + + # Clear batched commands + # ---------------------- + self._batch_layout_commands.clear() + self._batch_style_commands.clear() + + def _send_animate_msg(self, styles, layout, trace_indexes, animation_opts): + # print(styles, layout, trace_indexes, animation_opts) + if not isinstance(trace_indexes, (list, tuple)): + trace_indexes = [trace_indexes] + + # Add restyle message id + restyle_msg_id = self._last_restyle_msg_id + 1 + for style in styles: + style['_restyle_msg_id'] = restyle_msg_id + + self._last_restyle_msg_id = restyle_msg_id + self._restyle_in_process = True + + # Add relayout message id + relayout_msg_id = self._last_relayout_msg_id + 1 + layout['_relayout_msg_id'] = relayout_msg_id + self._last_relayout_msg_id = relayout_msg_id + self._relayout_in_process = True + + animate_msg = [{'data': styles, + 'layout': layout, + 'traces': trace_indexes}, + animation_opts] + + if self._log_plotly_commands: + print('Plotly.animate') + pprint(animate_msg, indent=4) + + self._py2js_animate = animate_msg + self._py2js_animate = None + + # Remove message ids + for style in styles: + style.pop('_restyle_msg_id') + + layout.pop('_relayout_msg_id') + + # Exports + # ------- + def to_dict(self): + + # Handle data + data = deepcopy([BaseFigure._remove_underscore_keys(trace) for trace in self._data]) + + # Handle layout + layout = deepcopy(BaseFigure._remove_underscore_keys(self._layout)) + + # Handle frames + res = {'data': data, 'layout': layout} + frames = deepcopy([BaseFigure._remove_underscore_keys(frame._props) for frame in self._frame_objs]) + if frames: + res['frames'] = frames + + return res + + def save_html(self, filename, auto_open=False, responsive=False): + data = self.to_dict() + if responsive: + if 'height' in data['layout']: + data['layout'].pop('height') + if 'width' in data['layout']: + data['layout'].pop('width') + else: + # Assign width/height explicitly in case these were defaults + data['layout']['height'] = self.layout.height + data['layout']['width'] = self.layout.width + + plotlypy_plot(data, filename=filename, show_link=False, auto_open=auto_open, validate=False) + + def save_image(self, filename, image_type=None, scale_factor=2): + """ + Save figure to a static image file + + Parameters + ---------- + filename : str + Image output file name + image_type : str + Image file type. One of: 'svg', 'png', 'pdf', or 'ps'. If not set, file type + is inferred from the filename extension + scale_factor : number + (For png image type) Factor by which to increase the number of pixels in each + dimension. A scale factor of 1 will result in a image with pixel dimensions + (layout.width, layout.height). A scale factor of 2 will result in an image + with dimensions (2*layout.width, 2*layout.height), doubling image's DPI. + (Default 2) + """ + + # Validate / infer image_type + supported_image_types = ['svg', 'png', 'pdf', 'ps'] + cairo_image_types = ['png', 'pdf', 'ps'] + supported_types_csv = ', '.join(supported_image_types) + + if not image_type: + # Infer image type from extension + _, extension = os.path.splitext(filename) + + if not extension: + raise ValueError('No image_type specified and file extension has no extension ' + 'from which to infer an image type ' + 'Supported image types are: {image_types}' + .format(image_types=supported_types_csv)) + + image_type = extension[1:] + + image_type = image_type.lower() + if image_type not in supported_image_types: + raise ValueError("Unsupported image type '{image_type}'\n" + "Supported image types are: {image_types}" + .format(image_type=image_type, + image_types=supported_types_csv)) + + # Validate cairo dependency + if image_type in cairo_image_types: + # Check whether we have cairosvg available + try: + import_module('cairosvg') + except ModuleNotFoundError: + raise ImportError('Exporting to {image_type} requires cairosvg' + .format(image_type=image_type)) + + # Validate scale_factor + if not isinstance(scale_factor, numbers.Number) or scale_factor <= 0: + raise ValueError('scale_factor must be a positive number.\n' + ' Received: {scale_factor}'.format(scale_factor=scale_factor)) + + req_id = str(uuid.uuid1()) + + # Register request + self._svg_requests[req_id] = {'filename': filename, + 'image_type': image_type, + 'scale_factor': scale_factor} + + self._py2js_requestSvg = req_id + self._py2js_requestSvg = None + + def _do_save_image(self, req_id, svg_uri): + req_info = self._svg_requests.pop(req_id, None) + if not req_info: + return + + # Remove svg header + if not svg_uri.startswith('data:image/svg+xml,'): + raise ValueError('Invalid svg data URI') + + svg = svg_uri.replace('data:image/svg+xml,', '') + + # Unquote characters (e.g. '%3Csvg%20' -> ' ['foo', 'bar[0]'] + key_path = raw_key.split('.') + + # Split out bracket indexes. e.g. ['foo', 'bar[0]'] -> ['foo', 'bar', '0'] + bracket_re = re.compile('(.*)\[(\d+)\]') + key_path2 = [] + for key in key_path: + match = bracket_re.fullmatch(key) + if match: + key_path2.extend(match.groups()) + else: + key_path2.append(key) + + # Convert elements to ints if possible. e.g. e.g. ['foo', 'bar', '0'] -> ['foo', 'bar', 0] + for i in range(len(key_path2)): + try: + key_path2[i] = int(key_path2[i]) + except ValueError as _: + pass + + return tuple(key_path2) + + @staticmethod + def _is_object_list(v): + return isinstance(v, list) and len(v) > 0 and isinstance(v[0], dict) + + @staticmethod + def _remove_overlapping_props(input_data, delta_data, prop_path=()): + """ + Remove properties in data that are also into delta. Do so recursively. + + Except, never remove uid from input_data + + Parameters + ---------- + data : + delta : + + Returns + ------- + List of removed property path tuples + """ + removed = [] + if isinstance(input_data, dict): + assert isinstance(delta_data, dict) + + for p, delta_val in delta_data.items(): + if isinstance(delta_val, dict) or BaseFigure._is_object_list(delta_val): + if p in input_data: + input_val = input_data[p] + removed.extend( + BaseFigure._remove_overlapping_props( + input_val, + delta_val, + prop_path + (p,))) + elif p in input_data and p != 'uid': + input_data.pop(p) + removed.append(prop_path + (p,)) + + elif isinstance(input_data, list): + assert isinstance(delta_data, list) + + for i, delta_val in enumerate(delta_data): + if i >= len(input_data): + break + + input_val = input_data[i] + if input_val is not None and isinstance(delta_val, dict) or BaseFigure._is_object_list(delta_val): + removed.extend( + BaseFigure._remove_overlapping_props( + input_val, + delta_val, + prop_path + (i,))) + + return removed + + @staticmethod + def transform_data(to_data, from_data, should_remove=True, relayout_path=()): + """ + Transform to_data into from_data and return relayout style description of transformation + + Parameters + ---------- + to_data : + from_data : + + Returns + ------- + + """ + relayout_terms = {} + if isinstance(to_data, dict): + if not isinstance(from_data, dict): + raise ValueError('Mismatched data types: to_data: {to_dict} {from_data}'.format( + to_dict=to_data, from_data=from_data)) + + # Handle addition / modification of terms + for from_prop, from_val in from_data.items(): + if isinstance(from_val, dict) or BaseFigure._is_object_list(from_val): + if from_prop not in to_data: + to_data[from_prop] = {} if isinstance(from_val, dict) else [] + + input_val = to_data[from_prop] + relayout_terms.update( + BaseFigure.transform_data( + input_val, + from_val, + should_remove=should_remove, + relayout_path=relayout_path + (from_prop,))) + else: + if from_prop not in to_data or not BasePlotlyType._vals_equal(to_data[from_prop], from_val): + # if from_prop in to_data: + # print(f'to_data[from_prop] != from_val -- {to_data}[{from_prop}] != {from_val}:') + to_data[from_prop] = from_val + relayout_terms[relayout_path + (from_prop,)] = from_val + + # Handle removal of terms + if should_remove: + for remove_prop in set(to_data.keys()).difference(set(from_data.keys())): + to_data.pop(remove_prop) + + elif isinstance(to_data, list): + if not isinstance(from_data, list): + raise ValueError('Mismatched data types: to_data: {to_data} {from_data}'.format( + to_data=to_data, from_data=from_data)) + + for i, from_val in enumerate(from_data): + if i >= len(to_data): + to_data.append(None) + + input_val = to_data[i] + if input_val is not None and isinstance(from_val, dict) or BaseFigure._is_object_list(from_val): + relayout_terms.update( + BaseFigure.transform_data( + input_val, + from_val, + should_remove=should_remove, + relayout_path=relayout_path + (i,))) + else: + if not BasePlotlyType._vals_equal(to_data[i], from_val): + to_data[i] = from_val + relayout_terms[relayout_path + (i,)] = from_val + + return relayout_terms + + +class BasePlotlyType: + _validators = None + + # Defaults to help mocking + def __init__(self, plotly_name, **kwargs): + + self._plotly_name = plotly_name + self._raise_on_invalid_property_error(**kwargs) + self._validators = {} + self._compound_props = {} + self._orphan_props = {} # properties dict for use while object has no parent + self._parent = None + self._change_callbacks = {} # type: typ.Dict[typ.Tuple, typ.Callable] + + @property + def plotly_name(self): + return self._plotly_name + + @property + def _parent_path(self) -> str: + raise NotImplementedError + + @property + def _prop_descriptions(self) -> str: + raise NotImplementedError + + def __setattr__(self, prop, value): + if prop.startswith('_') or hasattr(self, prop): + # Let known properties and private properties through + super().__setattr__(prop, value) + else: + # Raise error on unknown public properties + self._raise_on_invalid_property_error(**{prop: value}) + + def _raise_on_invalid_property_error(self, **kwargs): + invalid_props = list(kwargs.keys()) + if invalid_props: + if len(invalid_props) == 1: + prop_str = 'property' + invalid_str = repr(invalid_props[0]) + else: + prop_str = 'properties' + invalid_str = repr(invalid_props) + + if self._parent_path: + full_prop_name = self._parent_path + '.' + self.plotly_name + else: + full_prop_name = self.plotly_name + + raise ValueError("Invalid {prop_str} specified for {full_prop_name}: {invalid_str}\n\n" + " Valid properties:\n" + "{prop_descriptions}" + .format(prop_str=prop_str, + full_prop_name=full_prop_name, + invalid_str=invalid_str, + prop_descriptions=self._prop_descriptions)) + + @property + def _props(self): + if self.parent is None: + # Use orphan data + return self._orphan_props + else: + # Get data from parent's dict + return self.parent._get_child_props(self) + + def _init_props(self): + # Ensure that _data is initialized. + if self._props is not None: + pass + else: + self._parent._init_child_props(self) + + def _init_child_props(self, child): + if self.parent: + self.parent._init_child_props(self) + self_props = self.parent._get_child_props(self) + else: + self_props = self._orphan_props + + child_or_children = self._compound_props[child.plotly_name] + if child is child_or_children: + if child.plotly_name not in self_props: + self_props[child.plotly_name] = {} + elif isinstance(child_or_children, (list, tuple)): + child_ind = child_or_children.index(child) + if child.plotly_name not in self_props: + # Initialize list + self_props[child.plotly_name] = [] + + # Make sure list is long enough for child + child_list = self_props[child.plotly_name] + while(len(child_list) <= child_ind): + child_list.append({}) + + def _get_child_props(self, child): + + if self.parent: + self_props = self.parent._get_child_props(self) + else: + self_props = self._orphan_props + + if self_props is None: + return None + else: + child_or_children = self._compound_props[child.plotly_name] + if child is child_or_children: + return self_props.get(child.plotly_name, None) + elif isinstance(child_or_children, (list, tuple)): + child_ind = child_or_children.index(child) + children_props = self_props.get(child.plotly_name, None) + return children_props[child_ind] \ + if children_props is not None and len(children_props) > child_ind \ + else None + else: + ValueError('Unexpected child: %s' % child_or_children) + + @property + def _prop_defaults(self): + if self.parent is None: + return None + else: + return self.parent._get_child_prop_defaults(self) + + def _get_child_prop_defaults(self, child): + if self.parent is None: + return None + + self_prop_defaults = self.parent._get_child_prop_defaults(self) + if self_prop_defaults is None: + return None + else: + child_or_children = self._compound_props[child.plotly_name] + if child is child_or_children: + return self_prop_defaults.get(child.plotly_name, None) + elif isinstance(child_or_children, (list, tuple)): + child_ind = child_or_children.index(child) + children_props = self_prop_defaults.get(child.plotly_name, None) + return children_props[child_ind] if children_props is not None else None + else: + ValueError('Unexpected child: %s' % child_or_children) + + @property + def parent(self): + return self._parent + + def __getitem__(self, prop): + if isinstance(prop, tuple): + res = self + for p in prop: + res = res[p] + + return res + else: + if prop not in self._validators: + raise KeyError(prop) + + if prop in self._compound_props: + return self._compound_props[prop] + elif self._props is not None and prop in self._props: + return self._props[prop] + elif self._prop_defaults is not None: + return self._prop_defaults.get(prop, None) + else: + return None + + def __contains__(self, prop): + return prop in self._validators + + def __setitem__(self, key, value): + if key not in self._validators: + raise KeyError(key) + + validator = self._validators[key] + + if isinstance(validator, CompoundValidator): + self._set_compound_prop(key, value) + elif isinstance(validator, (CompoundArrayValidator, BaseDataValidator)): + self._set_array_prop(key, value) + else: + # Simple property + self._set_prop(key, value) + + @property + def _in_batch_mode(self): + return self.parent and self.parent._in_batch_mode + + @staticmethod + def _vals_equal(v1, v2): + if isinstance(v1, np.ndarray) or isinstance(v2, np.ndarray): + return np.array_equal(v1, v2) + else: + return v1 == v2 + + def _set_prop(self, prop, val): + if val is Undefined: + # Do nothing + return + + validator = self._validators.get(prop) + val = validator.validate_coerce(val) + + if val is None: + # Check if we should send null update + if self._props and prop in self._props: + if not self._in_batch_mode: + self._props.pop(prop) + self._send_update(prop, val) + else: + self._init_props() + if prop not in self._props or not BasePlotlyType._vals_equal(self._props[prop], val): + if not self._in_batch_mode: + self._props[prop] = val + self._send_update(prop, val) + + def _set_compound_prop(self, prop, val): + if val is Undefined: + # Do nothing + return + + # Validate coerce new value + validator = self._validators.get(prop) + val = validator.validate_coerce(val) # type: BasePlotlyType + + # Grab deep copies of current and new states + curr_val = self._compound_props.get(prop, None) + if curr_val is not None: + curr_dict_val = deepcopy(curr_val._props) + else: + curr_dict_val = None + + if val is not None: + new_dict_val = deepcopy(val._props) + else: + new_dict_val = None + + # Update data dict + if not self._in_batch_mode: + if not new_dict_val: + if prop in self._props: + self._props.pop(prop) + else: + self._init_props() + self._props[prop] = new_dict_val + + # Send update if there was a change in value + if not BasePlotlyType._vals_equal(curr_dict_val, new_dict_val): + self._send_update(prop, new_dict_val) + + # Reparent new value and clear orphan data + val._parent = self + val._orphan_props.clear() + + # Reparent old value and update orphan data + if curr_val is not None and curr_val is not val: + if curr_dict_val is not None: + curr_val._orphan_props.update(curr_dict_val) + curr_val._parent = None + + self._compound_props[prop] = val + return val + + def _set_array_prop(self, prop, val): + if val is Undefined: + # Do nothing + return + + # Validate coerce new value + validator = self._validators.get(prop) + val = validator.validate_coerce(val) # type: tuple + + # Update data dict + curr_val = self._compound_props.get(prop, None) + if curr_val is not None: + curr_dict_vals = [deepcopy(cv._props) for cv in curr_val] + else: + curr_dict_vals = None + + if val is not None: + new_dict_vals = [deepcopy(nv._props) for nv in val] + else: + new_dict_vals = None + + # Update data dict + if not self._in_batch_mode: + if not new_dict_vals: + if prop in self._props: + self._props.pop(prop) + else: + self._init_props() + self._props[prop] = new_dict_vals + + # Send update if there was a change in value + if not BasePlotlyType._vals_equal(curr_dict_vals, new_dict_vals): + self._send_update(prop, new_dict_vals) + + # Reparent new values and clear orphan data + if val is not None: + for v in val: + v._orphan_props.clear() + v._parent = self + + # Reparent + if curr_val is not None: + for cv, cv_dict in zip(curr_val, curr_dict_vals): + if cv_dict is not None: + cv._orphan_props.update(cv_dict) + cv._parent = None + self._compound_props[prop] = val + return val + + def _send_update(self, prop, val): + raise NotImplementedError() + + def _update_child(self, child, prop, val): + child_prop_val = getattr(self, child.plotly_name) + if isinstance(child_prop_val, (list, tuple)): + child_ind = child_prop_val.index(child) + obj_path = '{child_name}.{child_ind}.{prop}'.format( + child_name=child.plotly_name, + child_ind=child_ind, + prop=prop) + else: + obj_path = '{child_name}.{prop}'.format(child_name=child.plotly_name, prop=prop) + + self._send_update(obj_path, val) + + def _restyle_child(self, child, prop, val): + self._update_child(child, prop, val) + + def _relayout_child(self, child, prop, val): + self._update_child(child, prop, val) + + # Callbacks + # --------- + def _dispatch_change_callbacks(self, changed_paths): + # print(f'Change callback: {self.prop_name} - {changed_paths}') + changed_paths = set(changed_paths) + # pprint(changed_paths) + for callback_paths, callback in self._change_callbacks.items(): + # pprint(set(callback_paths)) + common_paths = changed_paths.intersection(set(callback_paths)) + if common_paths: + # Invoke callback + callback_args = [self[cb_path] for cb_path in callback_paths] + callback(self, *callback_args) + + def on_change(self, callback, *args): + """ + Register callback function to be called with a properties or subproperties of this object are modified + + Parameters + ---------- + callback : function + Function that accepts 1 + len(args) parameters. First parameter is this object. Second throug last + parameters are the values referenced by args + args : str or tuple(str) + Property name (for direct properties) or tuple of property names / indices (for sub properties). Callback + will be invoked whenever ANY of these properties is modified. Furthermore. The callback will only be + invoked once even if multiple properties are modified during the same restyle operation. + + Returns + ------- + + """ + + if len(args) == 0: + raise ValueError('At least one property/subproperty must be specified') + + # TODO: Validate that args valid properties / subproperties + validated_args = tuple([a if isinstance(a, tuple) else (a,) for a in args]) + + # TODO: add append arg and store list of callbacks + self._change_callbacks[validated_args] = callback + + +class BaseLayoutHierarchyType(BasePlotlyType): + + # _send_relayout analogous to _send_restyle above + def __init__(self, plotly_name, **kwargs): + super().__init__(plotly_name, **kwargs) + + def _send_update(self, prop, val): + if self.parent: + self.parent._relayout_child(self, prop, val) + + +class BaseLayoutType(BaseLayoutHierarchyType): + _subplotid_prop_names = ['xaxis', 'yaxis', 'geo', 'ternary', 'scene'] + _subplotid_validators = {'xaxis': XaxisValidator, + 'yaxis': YaxisValidator, + 'geo': GeoValidator, + 'ternary': TernaryValidator, + 'scene': SceneValidator} + + _subplotid_prop_re = re.compile('(' + '|'.join(_subplotid_prop_names) + ')(\d+)') + + def __init__(self, plotly_name, **kwargs): + # Compute invalid kwargs. Pass to parent for error message + invalid_kwargs = {k: v for k, v in kwargs.items() + if not self._subplotid_prop_re.fullmatch(k)} + super().__init__(plotly_name, **invalid_kwargs) + self._subplotid_props = {} + for prop, value in kwargs.items(): + self._set_subplotid_prop(prop, value) + + def _set_subplotid_prop(self, prop, value): + # We already tested for match in constructor + match = self._subplotid_prop_re.fullmatch(prop) + subplot_prop = match.group(1) + suffix_digit = int(match.group(2)) + if suffix_digit in [0, 1]: + raise TypeError('Subplot properties may only be suffixed by an integer > 1\n' + 'Received {k}'.format(k=prop)) + + # Add validator + if prop not in self._validators: + validator = self._subplotid_validators[subplot_prop](prop_name=prop) + self._validators[prop] = validator + + # Import value + self._subplotid_props[prop] = self._set_compound_prop(prop, value) + + def __getattr__(self, item): + # Check for subplot access (e.g. xaxis2) + # Validate then call self._get_prop(item) + if item in self._subplotid_props: + return self._subplotid_props[item] + + raise AttributeError("'Layout' object has no attribute '{item}'".format(item=item)) + + def __setattr__(self, prop, value): + # Check for subplot assignment (e.g. xaxis2) + # Call _set_compound_prop with the xaxis validator + match = self._subplotid_prop_re.fullmatch(prop) + if match is None: + # Try setting as ordinary property + super().__setattr__(prop, value) + else: + self._set_subplotid_prop(prop, value) + + def __dir__(self): + # Include any active subplot values (xaxis2 etc.) + return super().__dir__() + list(self._subplotid_props.keys()) + + +class BaseTraceHierarchyType(BasePlotlyType): + + def __init__(self, plotly_name, **kwargs): + super().__init__(plotly_name, **kwargs) + + def _send_update(self, prop, val): + if self.parent: + self.parent._restyle_child(self, prop, val) + + +class BaseTraceType(BaseTraceHierarchyType): + def __init__(self, plotly_name, **kwargs): + super().__init__(plotly_name, **kwargs) + + self._hover_callbacks = [] + self._unhover_callbacks = [] + self._click_callbacks = [] + self._select_callbacks = [] + + # uid + # --- + @property + def uid(self) -> str: + raise NotImplementedError + + @uid.setter + def uid(self, val): + raise NotImplementedError + + # Hover + # ----- + def on_hover(self, + callback: typ.Callable[['BaseTraceType', Points, InputState], None], + append=False): + """ + Register callback to be called when the user hovers over a point from this trace + + Parameters + ---------- + callback + Callable that accepts 3 arguments + + - This trace + - Points object + - InputState object + + append : + + Returns + ------- + None + """ + if not append: + self._hover_callbacks.clear() + + if callback: + self._hover_callbacks.append(callback) + + def _dispatch_on_hover(self, points: Points, state: InputState): + for callback in self._hover_callbacks: + callback(self, points, state) + + # Unhover + # ------- + def on_unhover(self, callback: typ.Callable[['BaseTraceType', Points, InputState], None], append=False): + if not append: + self._unhover_callbacks.clear() + + if callback: + self._unhover_callbacks.append(callback) + + def _dispatch_on_unhover(self, points: Points, state: InputState): + for callback in self._unhover_callbacks: + callback(self, points, state) + + # Click + # ----- + def on_click(self, callback: typ.Callable[['BaseTraceType', Points, InputState], None], append=False): + if not append: + self._click_callbacks.clear() + if callback: + self._click_callbacks.append(callback) + + def _dispatch_on_click(self, points: Points, state: InputState): + for callback in self._click_callbacks: + callback(self, points, state) + + # Select + # ------ + def on_selected(self, + callback: typ.Callable[['BaseTraceType', Points, typ.Union[BoxSelector, LassoSelector]], None], + append=False): + if not append: + self._select_callbacks.clear() + + if callback: + self._select_callbacks.append(callback) + + def _dispatch_on_selected(self, points: Points, selector: typ.Union[BoxSelector, LassoSelector]): + for callback in self._select_callbacks: + callback(self, points, selector) + + +class BaseFrameHierarchyType(BasePlotlyType): + + def __init__(self, plotly_name, **kwargs): + super().__init__(plotly_name, **kwargs) + + def _send_update(self, prop, val): + # Frames are not supported by FrameWidget and updates are not propagated to parents + pass + diff --git a/ipyplotly/ipyplotly/basevalidators.py b/ipyplotly/ipyplotly/basevalidators.py new file mode 100644 index 00000000000..4b598e3fff2 --- /dev/null +++ b/ipyplotly/ipyplotly/basevalidators.py @@ -0,0 +1,1266 @@ +import base64 +import numbers +import textwrap +import uuid +from importlib import import_module + +import io +from copy import deepcopy + +import numpy as np +import re + +# Utility functions +# ----------------- +def copy_to_contiguous_readonly_numpy_array(v, dtype=None, force_numeric=False): + + # Copy to numpy array and handle dtype param + # ------------------------------------------ + # If dtype was not specified then it will be passed to the numpy array constructor as None and the data type + # will be inferred automatically + + numeric_kinds = ['u', 'i', 'f'] + + if not isinstance(v, np.ndarray): + new_v = np.array(v, order='C', dtype=dtype) + elif v.dtype.kind in numeric_kinds: + new_v = np.ascontiguousarray(v.astype(dtype)) + else: + new_v = v.copy() + + # Handle force numeric param + # -------------------------- + if force_numeric and new_v.dtype.kind not in numeric_kinds: # (un)signed int, or float + raise ValueError('Input value is not numeric and force_numeric parameter set to True') + + if dtype != 'unicode': + # Force non-numeric arrays to have object type + # -------------------------------------------- + # Here we make sure that non-numeric arrays have the object datatype. This works around cases like + # np.array([1, 2, '3']) where numpy converts the integers to strings and returns array of dtype '= self.min_val) + + if self.max_val is not None: + v_valid = np.logical_and(v_valid, v_array <= self.max_val) + + if not np.all(v_valid): + # Grab up to the first 10 invalid values + some_invalid_els = np.array(v, dtype='object')[np.logical_not(v_valid)][:10].tolist() + self.raise_invalid_elements(some_invalid_els) + + v = v_array # Always numpy array of float64 + else: + if not isinstance(v, numbers.Number): + self.raise_invalid_val(v) + + if (self.min_val is not None and not v >= self.min_val) or \ + (self.max_val is not None and not v <= self.max_val): + + self.raise_invalid_val(v) + + return v + + +class IntegerValidator(BaseValidator): + """ + "integer": { + "description": "An integer or an integer inside a string. When applicable, values greater (less) than `max` (`min`) are coerced to the `dflt`.", + "requiredOpts": [], + "otherOpts": [ + "dflt", + "min", + "max", + "arrayOk" + ] + }, + """ + def __init__(self, plotly_name, parent_name, min=None, max=None, array_ok=False, **_): + super().__init__(plotly_name=plotly_name, parent_name=parent_name) + + # Handle min + if min is None and max is not None: + # Max was specified, so make min -inf + self.min_val = np.iinfo(np.int32).min + else: + self.min_val = min + + # Handle max + if max is None and min is not None: + # Min was specified, so make min inf + self.max_val = np.iinfo(np.int32).max + else: + self.max_val = max + + self.array_ok = array_ok + + def description(self): + desc = """\ + The '{plotly_name}' property is a integer and may be specified as:""".format(plotly_name=self.plotly_name) + + if self.min_val is None and self.max_val is None: + desc = desc + """ + - An int (or float that will be cast to an int)""" + else: + desc = desc + """ + - An int (or float that will be cast to an int) in the interval [{min_val}, {max_val}]""".format( + min_val=self.min_val, + max_val=self.max_val) + + if self.array_ok: + desc = desc + """ + - A tuple, list, or one-dimensional numpy array of the above""" + + return desc + + def validate_coerce(self, v): + if v is None: + # Pass None through + pass + elif self.array_ok and is_array(v): + + try: + v_array = copy_to_contiguous_readonly_numpy_array(v, dtype='int32') + + except (ValueError, TypeError, OverflowError) as ve: + self.raise_invalid_val(v) + + v_valid = np.ones(v_array.shape, dtype='bool') + if self.min_val is not None: + v_valid = np.logical_and(v_valid, v_array >= self.min_val) + + if self.max_val is not None: + v_valid = np.logical_and(v_valid, v_array <= self.max_val) + + if not np.all(v_valid): + invalid_els = np.array(v, dtype='object')[np.logical_not(v_valid)][:10].tolist() + self.raise_invalid_elements(invalid_els) + + v = v_array + else: + try: + if not isinstance(v, numbers.Number): + # don't let int() cast strings to ints + self.raise_invalid_val(v) + + v_int = int(v) + except (ValueError, TypeError, OverflowError) as ve: + self.raise_invalid_val(v) + + if (self.min_val is not None and not v >= self.min_val) or \ + (self.max_val is not None and not v <= self.max_val): + self.raise_invalid_val(v) + + v = v_int + + return v + + +class StringValidator(BaseValidator): + """ + "string": { + "description": "A string value. Numbers are converted to strings except for attributes with `strict` set to true.", + "requiredOpts": [], + "otherOpts": [ + "dflt", + "noBlank", + "strict", + "arrayOk", + "values" + ] + }, + """ + def __init__(self, plotly_name, parent_name, no_blank=False, strict=False, array_ok=False, values=None, **_): + super().__init__(plotly_name=plotly_name, parent_name=parent_name) + self.no_blank = no_blank + self.strict = strict # Not implemented. We're always strict + self.array_ok = array_ok + self.values = values + + def description(self): + desc = """\ + The '{plotly_name}' property is a string and must be specified as:""".format(plotly_name=self.plotly_name) + + if self.no_blank: + desc = desc + """ + - A non-empty string""" + elif self.values: + valid_str = '\n'.join(textwrap.wrap(repr(self.values), + subsequent_indent=' ' * 12, + break_on_hyphens=False)) + + desc = desc + """ + - One of the following strings: + {valid_str}""".format(valid_str=valid_str) + else: + desc = desc + """ + - A string""" + + if self.array_ok: + desc = desc + """ + - A tuple, list, or one-dimensional numpy array of the above""" + + return desc + + def validate_coerce(self, v): + if v is None: + # Pass None through + pass + elif self.array_ok and is_array(v): + + # Make sure all elements are strings. Is there a more efficient way to do this in numpy? + invalid_els = [e for e in v if not isinstance(e, str)] + if invalid_els: + self.raise_invalid_elements(invalid_els) + + v = copy_to_contiguous_readonly_numpy_array(v, dtype='unicode') + + if self.no_blank: + invalid_els = v[v == ''][:10].tolist() + if invalid_els: + self.raise_invalid_elements(invalid_els) + + if self.values: + invalid_els = v[np.logical_not(np.isin(v, self.values))][:10].tolist() + if invalid_els: + self.raise_invalid_elements(invalid_els) + else: + if not isinstance(v, str): + self.raise_invalid_val(v) + + if self.no_blank and len(v) == 0: + self.raise_invalid_val(v) + + if self.values and v not in self.values: + self.raise_invalid_val(v) + + return v + + +class ColorValidator(BaseValidator): + """ + "color": { + "description": "A string describing color. Supported formats: - hex (e.g. '#d3d3d3') - rgb (e.g. 'rgb(255, 0, 0)') - rgba (e.g. 'rgb(255, 0, 0, 0.5)') - hsl (e.g. 'hsl(0, 100%, 50%)') - hsv (e.g. 'hsv(0, 100%, 100%)') - named colors (full list: http://www.w3.org/TR/css3-color/#svg-color)", + "requiredOpts": [], + "otherOpts": [ + "dflt", + "arrayOk" + ] + }, + """ + re_hex = re.compile('#([A-Fa-f0-9]{6}|[A-Fa-f0-9]{3})') + re_rgb_etc = re.compile('(rgb|hsl|hsv)a?\([\d.]+%?(,[\d.]+%?){2,3}\)') + + named_colors = [ + "aliceblue", "antiquewhite", "aqua", "aquamarine", "azure", "beige", "bisque", "black", "blanchedalmond", + "blue", "blueviolet", "brown", "burlywood", "cadetblue", "chartreuse", "chocolate", "coral", "cornflowerblue", + "cornsilk", "crimson", "cyan", "darkblue", "darkcyan", "darkgoldenrod", "darkgray", "darkgrey", "darkgreen", + "darkkhaki", "darkmagenta", "darkolivegreen", "darkorange", "darkorchid", "darkred", "darksalmon", + "darkseagreen", "darkslateblue", "darkslategray", "darkslategrey", "darkturquoise", "darkviolet", "deeppink", + "deepskyblue", "dimgray", "dimgrey", "dodgerblue", "firebrick", "floralwhite", "forestgreen", "fuchsia", + "gainsboro", "ghostwhite", "gold", "goldenrod", "gray", "grey", "green", "greenyellow", "honeydew", "hotpink", + "indianred", "indigo", "ivory", "khaki", "lavender", "lavenderblush", "lawngreen", "lemonchiffon", "lightblue", + "lightcoral", "lightcyan", "lightgoldenrodyellow", "lightgray", "lightgrey", "lightgreen", "lightpink", + "lightsalmon", "lightseagreen", "lightskyblue", "lightslategray", "lightslategrey", "lightsteelblue", + "lightyellow", "lime", "limegreen", "linen", "magenta", "maroon", "mediumaquamarine", "mediumblue", + "mediumorchid", "mediumpurple", "mediumseagreen", "mediumslateblue", "mediumspringgreen", "mediumturquoise", + "mediumvioletred", "midnightblue", "mintcream", "mistyrose", "moccasin", "navajowhite", "navy", "oldlace", + "olive", "olivedrab", "orange", "orangered", "orchid", "palegoldenrod", "palegreen", "paleturquoise", + "palevioletred", "papayawhip", "peachpuff", "peru", "pink", "plum", "powderblue", "purple", "red", "rosybrown", + "royalblue", "saddlebrown", "salmon", "sandybrown", "seagreen", "seashell", "sienna", "silver", "skyblue", + "slateblue", "slategray", "slategrey", "snow", "springgreen", "steelblue", "tan", "teal", "thistle", "tomato", + "turquoise", "violet", "wheat", "white", "whitesmoke", "yellow", "yellowgreen"] + + def __init__(self, plotly_name, parent_name, array_ok=False, colorscale_path=None, **_): + super().__init__(plotly_name=plotly_name, parent_name=parent_name) + self.colorscale_path = colorscale_path + self.array_ok = array_ok + + def numbers_allowed(self): + return self.colorscale_path is not None + + def description(self): + + named_clrs_str = '\n'.join(textwrap.wrap(', '.join(self.named_colors), width=80, subsequent_indent=' ' * 12)) + + valid_color_description = """\ + The '{plotly_name}' property is a color and may be specified as: + - A hex string (e.g. '#ff0000') + - An rgb/rgba string (e.g. 'rgb(255,0,0)') + - An hsl/hsla string (e.g. 'hsl(0,100%,50%)') + - An hsv/hsva string (e.g. 'hsv(0,100%,100%)') + - A named CSS color: + {clrs}""".format( + plotly_name=self.plotly_name, + clrs=named_clrs_str) + + if self.colorscale_path: + valid_color_description = valid_color_description + """ + - A number that will be interpreted as a color according to {colorscale_path}""".format( + colorscale_path=self.colorscale_path) + + if self.array_ok: + valid_color_description = valid_color_description + """ + - A list or array of any of the above""" + + return valid_color_description + + def validate_coerce(self, v): + if v is None: + # Pass None through + pass + elif self.array_ok and is_array(v): + v_array = copy_to_contiguous_readonly_numpy_array(v) + if self.numbers_allowed() and v_array.dtype.kind in ['u', 'i', 'f']: # (un)signed int or float + # All good + v = v_array + else: + validated_v = [ColorValidator.perform_validate_coerce(e, allow_number=self.numbers_allowed()) + for e in v] + + invalid_els = [el for el, validated_el in zip(v, validated_v) if validated_el is None] + if invalid_els: + self.raise_invalid_elements(invalid_els) + + # ### Check that elements have valid colors types ### + if self.numbers_allowed(): + v = copy_to_contiguous_readonly_numpy_array(validated_v, dtype='object') + else: + v = copy_to_contiguous_readonly_numpy_array(validated_v, dtype='unicode') + + else: + # Validate scalar color + validated_v = ColorValidator.perform_validate_coerce(v, allow_number=self.numbers_allowed()) + if validated_v is None: + self.raise_invalid_val(v) + + v = validated_v + + return v + + @staticmethod + def perform_validate_coerce(v, allow_number=None): + + if isinstance(v, numbers.Number) and allow_number: + # If allow_numbers then any number is ok + return v + elif not isinstance(v, str): + return None + else: + # Remove spaces so regexes don't need to bother with them. + v = v.replace(' ', '') + v = v.lower() + + if ColorValidator.re_hex.fullmatch(v): + # valid hex color (e.g. #f34ab3) + return v + elif ColorValidator.re_rgb_etc.fullmatch(v): + # Valid rgb(a), hsl(a), hsv(a) color (e.g. rgba(10, 234, 200, 50%) + return v + elif v in ColorValidator.named_colors: + # Valid named color (e.g. 'coral') + return v + else: + # Not a valid color + return None + + +class ColorlistValidator(BaseValidator): + """ + "colorlist": { + "description": "A list of colors. Must be an {array} containing valid colors.", + "requiredOpts": [], + "otherOpts": [ + "dflt" + ] + } + """ + def __init__(self, plotly_name, parent_name, **_): + super().__init__(plotly_name=plotly_name, parent_name=parent_name) + + def description(self): + return ("""\ + The '{plotly_name}' property is a colorlist that may be specified as a tuple, list, + or one-dimensional numpy array of valid color strings""".format(plotly_name=self.plotly_name)) + + def validate_coerce(self, v): + + if v is None: + # Pass None through + pass + elif is_array(v): + validated_v = [ColorValidator.perform_validate_coerce(e, allow_number=False) for e in v] + + invalid_els = [el for el, validated_el in zip(v, validated_v) if validated_el is None] + if invalid_els: + self.raise_invalid_elements(invalid_els) + + v = copy_to_contiguous_readonly_numpy_array(validated_v, dtype='unicode') + else: + self.raise_invalid_val(v) + return v + + +class ColorscaleValidator(BaseValidator): + """ + "colorscale": { + "description": "A Plotly colorscale either picked by a name: (any of Greys, YlGnBu, Greens, YlOrRd, Bluered, RdBu, Reds, Blues, Picnic, Rainbow, Portland, Jet, Hot, Blackbody, Earth, Electric, Viridis ) customized as an {array} of 2-element {arrays} where the first element is the normalized color level value (starting at *0* and ending at *1*), and the second item is a valid color string.", + "requiredOpts": [], + "otherOpts": [ + "dflt" + ] + }, + """ + + named_colorscales = ['Greys', 'YlGnBu', 'Greens', 'YlOrRd', 'Bluered', 'RdBu', 'Reds', 'Blues', 'Picnic', + 'Rainbow', 'Portland', 'Jet', 'Hot', 'Blackbody', 'Earth', 'Electric', 'Viridis'] + + def __init__(self, plotly_name, parent_name, **_): + super().__init__(plotly_name=plotly_name, parent_name=parent_name) + + def description(self): + desc = """\ + The '{plotly_name}' property is a colorscale and may be specified as: + - A list of 2-element lists where the first element is the normalized color level value + (starting at 0 and ending at 1), and the second item is a valid color string. + (e.g. [[0.5, 'red'], [1.0, 'rgb(0, 0, 255)']]) + - One of the following named colorscales: + ['Greys', 'YlGnBu', 'Greens', 'YlOrRd', 'Bluered', 'RdBu', 'Reds', 'Blues', 'Picnic', + 'Rainbow', 'Portland', 'Jet', 'Hot', 'Blackbody', 'Earth', 'Electric', 'Viridis'] + """.format(plotly_name=self.plotly_name) + + return desc + + def validate_coerce(self, v): + v_valid = False + + if v is None: + # Pass None through + pass + if v is None: + v_valid = True + elif isinstance(v, str): + v_match = [el for el in ColorscaleValidator.named_colorscales if el.lower() == v.lower()] + if v_match: + v_valid = True + v = v_match[0] + + elif is_array(v) and len(v) > 0: + invalid_els = [e for e in v + if not is_array(e) or + len(e) != 2 or + not isinstance(e[0], numbers.Number) or + not (0 <= e[0] <= 1) or + not isinstance(e[1], str) or + ColorValidator.perform_validate_coerce(e[1]) is None] + if len(invalid_els) == 0: + v_valid = True + + # Convert to tuple of tuples so colorscale is immutable + v = tuple([tuple([e[0], ColorValidator.perform_validate_coerce(e[1])]) for e in v]) + + if not v_valid: + self.raise_invalid_val(v) + return v + + +class AngleValidator(BaseValidator): + """ + "angle": { + "description": "A number (in degree) between -180 and 180.", + "requiredOpts": [], + "otherOpts": [ + "dflt" + ] + }, + """ + def __init__(self, plotly_name, parent_name, **_): + super().__init__(plotly_name=plotly_name, parent_name=parent_name) + + def description(self): + desc = """\ + The '{plotly_name}' property is a angle (in degrees) that may be specified as a number between -180 and 180. + Numeric values outside this range are converted to the equivalent value (e.g. 270 is converted to -90). + """.format(plotly_name=self.plotly_name) + + return desc + + def validate_coerce(self, v): + if v is None: + # Pass None through + pass + elif not isinstance(v, numbers.Number): + self.raise_invalid_val(v) + else: + # Normalize v onto the interval [-180, 180) + v = (v + 180) % 360 - 180 + + return v + + +class SubplotidValidator(BaseValidator): + """ + "subplotid": { + "description": "An id string of a subplot type (given by dflt), optionally followed by an integer >1. e.g. if dflt='geo', we can have 'geo', 'geo2', 'geo3', ...", + "requiredOpts": [ + "dflt" + ], + "otherOpts": [] + }, + """ + def __init__(self, plotly_name, parent_name, dflt, **_): + super().__init__(plotly_name=plotly_name, parent_name=parent_name) + self.base = dflt + self.regex = dflt + "(\d*)" + + def description(self): + + desc = """\ + The '{plotly_name}' property is an identifier of a particular subplot, of type '{base}', that + may be specified as the string '{base}' optionally followed by an integer > 1 + (e.g. '{base}', '{base}2', '{base}3', etc.) + """.format(plotly_name=self.plotly_name, base=self.base) + return desc + + def validate_coerce(self, v): + if v is None: + v = self.base + elif not isinstance(v, str): + self.raise_invalid_val(v) + else: + if not re.fullmatch(self.regex, v): + is_valid = False + else: + digit_str = re.fullmatch(self.regex, v).group(1) + if len(digit_str) > 0 and int(digit_str) in [0, 1]: + is_valid = False + else: + is_valid = True + + if not is_valid: + self.raise_invalid_val(v) + return v + + +class FlaglistValidator(BaseValidator): + """ + "flaglist": { + "description": "A string representing a combination of flags (order does not matter here). Combine any of the available `flags` with *+*. (e.g. ('lines+markers')). Values in `extras` cannot be combined.", + "requiredOpts": [ + "flags" + ], + "otherOpts": [ + "dflt", + "extras", + "arrayOk" + ] + }, + """ + def __init__(self, plotly_name, parent_name, flags, extras=None, array_ok=False, **_): + super().__init__(plotly_name=plotly_name, parent_name=parent_name) + self.flags = flags + self.extras = extras if extras is not None else [] + self.array_ok = array_ok + + self.all_flags = self.flags + self.extras + + def description(self): + + desc = ("""\ + The '{plotly_name}' property is a flaglist and may be specified as a string containing:""" + ).format(plotly_name=self.plotly_name) + + # Flags + desc = desc + (""" + - Any combination of {flags} joined with '+' characters (e.g. '{eg_flag}')""" + ).format(flags=self.flags, + eg_flag='+'.join(self.flags[:2])) + + # Extras + if self.extras: + desc = desc + (""" + OR exactly one of {extras} (e.g. '{eg_extra}')""" + ).format(extras=self.extras, + eg_extra=self.extras[-1]) + + if self.array_ok: + desc = desc + """ + - A list or array of the above""" + + return desc + + def perform_validate_coerce(self, v): + if not isinstance(v, str): + return None + + split_vals = [e.strip() for e in re.split('[,+]', v)] + + all_flags_valid = [f for f in split_vals if f not in self.all_flags] == [] + has_extras = [f for f in split_vals if f in self.extras] != [] + + is_valid = all_flags_valid and (not has_extras or len(split_vals) == 1) + if is_valid: + return '+'.join(split_vals) + else: + return None + + def validate_coerce(self, v): + if v is None: + # Pass None through + pass + elif self.array_ok and is_array(v): + + validated_v = [self.perform_validate_coerce(e) for e in v] # Coerce individual strings + + invalid_els = [el for el, validated_el in zip(v, validated_v) if validated_el is None] + if invalid_els: + self.raise_invalid_elements(invalid_els) + + v = copy_to_contiguous_readonly_numpy_array(validated_v, dtype='unicode') + else: + + validated_v = self.perform_validate_coerce(v) + if validated_v is None: + self.raise_invalid_val(v) + + v = validated_v + + return v + + +class AnyValidator(BaseValidator): + """ + "any": { + "description": "Any type.", + "requiredOpts": [], + "otherOpts": [ + "dflt", + "values", + "arrayOk" + ] + }, + """ + def __init__(self, plotly_name, parent_name, values=None, array_ok=False, **_): + super().__init__(plotly_name=plotly_name, parent_name=parent_name) + self.values = values + self.array_ok = array_ok + + def description(self): + + desc = """\ + The '{plotly_name}' property accepts values of any type + """.format(plotly_name=self.plotly_name) + return desc + + def validate_coerce(self, v): + if v is None: + # Pass None through + pass + elif self.array_ok and is_array(v): + v = copy_to_contiguous_readonly_numpy_array(v, dtype='object') + + return v + + +class InfoArrayValidator(BaseValidator): + """ + "info_array": { + "description": "An {array} of plot information.", + "requiredOpts": [ + "items" + ], + "otherOpts": [ + "dflt", + "freeLength" + ] + } + """ + def __init__(self, plotly_name, parent_name, items, free_length=None, **_): + super().__init__(plotly_name=plotly_name, parent_name=parent_name) + self.items = items + + self.item_validators = [] + for i, item in enumerate(self.items): + item_validator = InfoArrayValidator.build_validator(item, '{plotly_name}[{i}]'.format(plotly_name=plotly_name, i=i), parent_name) + self.item_validators.append(item_validator) + + self.free_length = free_length + + def description(self): + upto = ' up to' if self.free_length else '' + desc = """\ + The '{plotly_name}' property is an info array that may be specified as a list or tuple of{upto} + {N} elements such that: + """.format(plotly_name=self.plotly_name, upto=upto, N=len(self.item_validators)) + + for i, item_validator in enumerate(self.item_validators): + el_desc = ('\n' + ' ' * 12).join([line.strip() for line in item_validator.description().split('\n')]) + desc = desc + """ + ({i}) {el_desc} + """.format(i=i, el_desc=el_desc) + + return desc + + @staticmethod + def build_validator(validator_info, plotly_name, parent_name): + datatype = validator_info['valType'] # type: str + validator_classname = datatype.title().replace('_', '') + 'Validator' + validator_class = eval(validator_classname) + + kwargs = {k: validator_info[k] for k in validator_info + if k not in ['valType', 'description', 'role']} + + return validator_class(plotly_name=plotly_name, parent_name=parent_name, **kwargs) + + def validate_coerce(self, v): + if v is None: + # Pass None through + pass + elif not isinstance(v, (list, tuple)): + self.raise_invalid_val(v) + elif not self.free_length and len(v) != len(self.item_validators): + self.raise_invalid_val(v) + elif self.free_length and len(v) > len(self.item_validators): + self.raise_invalid_val(v) + else: + # We have a list or tuple of the correct length + v = list(v) + for i, (el, validator) in enumerate(zip(v, self.item_validators)): + # Validate coerce elements + v[i] = validator.validate_coerce(el) + + return v + + +class ImageUriValidator(BaseValidator): + _PIL = None + + try: + _PIL = import_module('PIL') + except ModuleNotFoundError: + pass + + def __init__(self, plotly_name, parent_name, **_): + super().__init__(plotly_name=plotly_name, parent_name=parent_name) + + def description(self): + + desc = """\ + The '{plotly_name}' property is an image URI that may be specified as: + - A remote image URI string (e.g. 'http://www.somewhere.com/image.png') + - A local image URI string (e.g. 'file:////somewhere/image.png') + - A data URI image string (e.g. 'data:image/png;base64,iVBORw0KGgoAAAANSU') + - A PIL.Image.Image object which will be immediately converted to a data URI image string + See http://pillow.readthedocs.io/en/latest/reference/Image.html + """.format(plotly_name=self.plotly_name) + return desc + + def validate_coerce(self, v): + if v is None: + pass + elif isinstance(v, str): + # Future possibilities: + # - Detect filesystem system paths and convert to URI + # - Validate either url or data uri + pass + elif self._PIL and isinstance(v, self._PIL.Image.Image): + # Convert PIL image to png data uri string + in_mem_file = io.BytesIO() + v.save(in_mem_file, format="PNG") + in_mem_file.seek(0) + img_bytes = in_mem_file.read() + base64_encoded_result_bytes = base64.b64encode(img_bytes) + base64_encoded_result_str = base64_encoded_result_bytes.decode('ascii') + v = 'data:image/png;base64,{base64_encoded_result_str}'.format( + base64_encoded_result_str=base64_encoded_result_str) + else: + self.raise_invalid_val(v) + + return v + + +class CompoundValidator(BaseValidator): + def __init__(self, plotly_name, parent_name, data_class, data_docs): + super().__init__(plotly_name=plotly_name, parent_name=parent_name) + self.data_class = data_class + self.data_docs = data_docs + + @staticmethod + def get_constructor_params_str(data_class): + params_match = re.search("Parameters\n\W*-+\n\W*(.*?)(Returns|$)", + str(data_class.__init__.__doc__), + flags=re.DOTALL) + + if params_match is not None: + param_descs = params_match.groups()[0] + + # Increase indent by 4 spaces + param_descs_indented = ('\n' + ' ' * 4).join(param_descs.split('\n')) + + return param_descs_indented + else: + return '' + + def description(self): + + desc = ("""\ + The '{plotly_name}' property is an instance of {data_class} + that may be specified as: + - An instance of {data_class} + - A dict of string/value properties that will be passed to the + {data_class} constructor + + Supported dict properties: + {constructor_params_str}""" + ).format(plotly_name=self.plotly_name, + data_class=type_str(self.data_class), + constructor_params_str=self.data_docs) + + return desc + + def validate_coerce(self, v): + if isinstance(self.data_class, str): + raise ValueError("Invalid data_class of type 'string': {data_class}" + .format(data_class = self.data_class)) + + if v is None: + v = self.data_class() + + elif isinstance(v, dict): + v = self.data_class(**v) + + elif isinstance(v, self.data_class): + # Copy object + v = self.data_class(**v._props) + else: + self.raise_invalid_val(v) + + v._prop_name = self.plotly_name + return v + + +class CompoundArrayValidator(BaseValidator): + def __init__(self, plotly_name, parent_name, element_class, element_docs): + super().__init__(plotly_name=plotly_name, parent_name=parent_name) + self.data_class = element_class + self.data_docs = element_docs + + def description(self): + + desc = ("""\ + The '{plotly_name}' property is a tuple of instances of {data_class} that may be specified as: + - A list or tuple of instances of {data_class} + - A list or tuple of dicts of string/value properties that will be passed to the {data_class} constructor + + Supported dict properties: + {constructor_params_str}""" + ).format(plotly_name=self.plotly_name, + data_class=type_str(self.data_class), + constructor_params_str=self.data_docs) + + return desc + + def validate_coerce(self, v): + + if isinstance(self.data_class, str): + raise ValueError("Invalid data_class of type 'string': {data_class}" + .format(data_class = self.data_class)) + + if v is None: + v = () + + elif isinstance(v, (list, tuple)): + res = [] + invalid_els = [] + for v_el in v: + if isinstance(v_el, self.data_class): + res.append(v_el) + elif isinstance(v_el, dict): + res.append(self.data_class(**v_el)) + else: + res.append(None) + invalid_els.append(v_el) + + if invalid_els: + self.raise_invalid_elements(invalid_els) + + v = tuple(res) + + elif not isinstance(v, str): + self.raise_invalid_val(v) + + return v + + +class BaseDataValidator(BaseValidator): + def __init__(self, class_map, plotly_name, parent_name): + super().__init__(plotly_name=plotly_name, parent_name=parent_name) + self.class_map = class_map + + def description(self): + + trace_types = str(list(self.class_map.keys())) + + trace_types_wrapped = '\n'.join(textwrap.wrap(trace_types, + subsequent_indent=' ' * 21, + width=80 - 8)) + + desc = ("""\ + The '{plotly_name}' property is a tuple of trace instances that may be specified as: + - A list or tuple of trace instances + (e.g. [Scatter(...), Bar(...)]) + - A list or tuple of dicts of string/value properties where: + - The 'type' property specifies the trace type + One of: {trace_types} + + - All remaining properties are passed to the constructor of the specified trace type + + (e.g. [{{'type': 'scatter', ...}}, {{'type': 'bar, ...}}])""" + ).format(plotly_name=self.plotly_name, trace_types=trace_types_wrapped) + + return desc + + def validate_coerce(self, v): + + if v is None: + v = () + elif isinstance(v, (list, tuple)): + trace_classes = tuple(self.class_map.values()) + + res = [] + invalid_els = [] + for v_el in v: + if isinstance(v_el, trace_classes): + res.append(v_el) + elif isinstance(v_el, dict): + v_copy = deepcopy(v_el) + + if 'type' in v_copy: + trace_type = v_copy.pop('type') + else: + trace_type = 'scatter' + + if trace_type not in self.class_map: + res.append(None) + invalid_els.append(v_el) + else: + trace = self.class_map[trace_type](**v_copy) + res.append(trace) + else: + res.append(None) + invalid_els.append(v_el) + + if invalid_els: + self.raise_invalid_elements(invalid_els) + + v = tuple(res) + + # Add UIDs if not set. + # If UID is set then it's the users responsibility to make sure UIDs are unique + for trace in v: + if trace.uid is None: + trace.uid = str(uuid.uuid1()) + + else: + self.raise_invalid_val(v) + + return v diff --git a/ipyplotly/ipyplotly/basewidget.py b/ipyplotly/ipyplotly/basewidget.py new file mode 100644 index 00000000000..fc7b03f603a --- /dev/null +++ b/ipyplotly/ipyplotly/basewidget.py @@ -0,0 +1,282 @@ +import ipywidgets as widgets +from traitlets import List, Unicode, Dict, observe, Integer, Undefined +from ipyplotly.basedatatypes import BaseFigure +from ipyplotly.callbacks import BoxSelector, LassoSelector, InputState, Points +from ipyplotly.serializers import custom_serializers + + +@widgets.register +class BaseFigureWidget(BaseFigure, widgets.DOMWidget): + + # Widget Traits + # ------------- + _view_name = Unicode('FigureView').tag(sync=True) + _view_module = Unicode('ipyplotly').tag(sync=True) + _model_name = Unicode('FigureModel').tag(sync=True) + _model_module = Unicode('ipyplotly').tag(sync=True) + + # Data properties for front end + # Note: These are only automatically synced on full assignment, not on mutation + _layout = Dict().tag(sync=True, **custom_serializers) + _data = List().tag(sync=True, **custom_serializers) + + # Python -> JS message properties + _py2js_addTraces = List(trait=Dict(), + allow_none=True).tag(sync=True, **custom_serializers) + + _py2js_restyle = List(allow_none=True).tag(sync=True, **custom_serializers) + _py2js_relayout = Dict(allow_none=True).tag(sync=True, **custom_serializers) + _py2js_update = List(allow_none=True).tag(sync=True, **custom_serializers) + _py2js_animate = List(allow_none=True).tag(sync=True, **custom_serializers) + + _py2js_deleteTraces = Dict(allow_none=True).tag(sync=True, **custom_serializers) + _py2js_moveTraces = List(allow_none=True).tag(sync=True, **custom_serializers) + + _py2js_removeLayoutProps = List(allow_none=True).tag(sync=True, **custom_serializers) + _py2js_removeStyleProps = List(allow_none=True).tag(sync=True, **custom_serializers) + _py2js_requestSvg = Unicode(allow_none=True).tag(sync=True) + + # JS -> Python message properties + _js2py_styleDelta = List(allow_none=True).tag(sync=True, **custom_serializers) + _js2py_layoutDelta = Dict(allow_none=True).tag(sync=True, **custom_serializers) + _js2py_restyle = List(allow_none=True).tag(sync=True, **custom_serializers) + _js2py_relayout = Dict(allow_none=True).tag(sync=True, **custom_serializers) + _js2py_update = Dict(allow_none=True).tag(sync=True, **custom_serializers) + + # For plotly_select/hover/unhover/click + _js2py_pointsCallback = Dict(allow_none=True).tag(sync=True, **custom_serializers) + + # Message tracking + _last_relayout_msg_id = Integer(0).tag(sync=True) + _last_restyle_msg_id = Integer(0).tag(sync=True) + + # Constructor + # ----------- + def __init__(self, data=None, layout=None, frames=None): + # TODO: error if frames is not None + # Validate Frames + # --------------- + if frames: + BaseFigureWidget._display_frames_error() + + self._frame_objs = None + + # Call superclass constructors + # ---------------------------- + # Note: We rename layout to layout_plotly because ipywidget also accepts a layout parameter + # We map a layout_ipywidget property to the layout property of the ipywidget + super().__init__(data=data, layout_plotly=layout) + + # Messages + # -------- + self.on_msg(self._handler_messages) + + # ### Trait methods ### + @observe('_js2py_styleDelta') + def handler_plotly_styleDelta(self, change): + deltas = change['new'] + self._js2py_styleDelta = None + + if not deltas: + return + + msg_id = deltas[0].get('_restyle_msg_id', None) + # print(f'styleDelta: {msg_id} == {self._last_restyle_msg_id}') + if msg_id == self._last_restyle_msg_id: + for delta in deltas: + trace_uid = delta['uid'] + + # Remove message id + # pprint(delta) + # print('Processing styleDelta') + + trace_uids = [trace.uid for trace in self.data] + trace_index = trace_uids.index(trace_uid) + uid_trace = self.data[trace_index] + delta_transform = BaseFigure.transform_data(uid_trace._prop_defaults, delta) + + removed_props = self._remove_overlapping_props(uid_trace._props, uid_trace._prop_defaults) + + if removed_props: + # print(f'Removed_props: {removed_props}') + self._py2js_removeStyleProps = [removed_props, trace_index] + self._py2js_removeStyleProps = None + + # print(delta_transform) + self._dispatch_change_callbacks_restyle(delta_transform, [trace_index]) + + self._restyle_in_process = False + while self._waiting_restyle_callbacks: + # Call callbacks + self._waiting_restyle_callbacks.pop()() + + @observe('_js2py_restyle') + def handler_js2py_restyle(self, change): + restyle_msg = change['new'] + self._js2py_restyle = None + + if not restyle_msg: + return + + self.restyle(*restyle_msg) + + @observe('_js2py_update') + def handler_js2py_update(self, change): + update_msg = change['new'] + self._js2py_update = None + + if not update_msg: + return + + # print('Update (JS->Py):') + # pprint(update_msg) + + style = update_msg['data'][0] + trace_indexes = update_msg['data'][1] + layout = update_msg['layout'] + + self.update(style=style, layout=layout, trace_indexes=trace_indexes) + + @observe('_js2py_layoutDelta') + def handler_plotly_layoutDelta(self, change): + delta = change['new'] + self._js2py_layoutDelta = None + + if not delta: + return + + msg_id = delta.get('_relayout_msg_id') + # print(f'layoutDelta: {msg_id} == {self._last_relayout_msg_id}') + if msg_id == self._last_relayout_msg_id: + + # print('Processing layoutDelta') + # print('layoutDelta: {deltas}'.format(deltas=delta)) + delta_transform = self.transform_data(self._layout_defaults, delta) + # print(f'delta_transform: {delta_transform}') + + # No relayout messages in process. Handle removing overlapping properties + removed_props = self._remove_overlapping_props(self._layout, self._layout_defaults) + if removed_props: + # print(f'Removed_props: {removed_props}') + self._py2js_removeLayoutProps = removed_props + self._py2js_removeLayoutProps = None + + self._dispatch_change_callbacks_relayout(delta_transform) + self._relayout_in_process = False + while self._waiting_relayout_callbacks: + # Call callbacks + self._waiting_relayout_callbacks.pop()() + + @observe('_js2py_relayout') + def handler_js2py_relayout(self, change): + relayout_data = change['new'] + # print('Relayout (JS->Py):') + # pprint(relayout_data) + + self._js2py_relayout = None + + if not relayout_data: + return + + if 'lastInputTime' in relayout_data: + # Remove 'lastInputTime'. Seems to be an internal plotly property that is introduced for some plot types + relayout_data.pop('lastInputTime') + + self.relayout(relayout_data) + + @observe('_js2py_pointsCallback') + def handler_plotly_pointsCallback(self, change): + callback_data = change['new'] + self._js2py_pointsCallback = None + + if not callback_data: + return + + # Get event type + # -------------- + event_type = callback_data['event_type'] + + # Build Selector Object + # --------------------- + if callback_data.get('selector', None): + selector_data = callback_data['selector'] + selector_type = selector_data['type'] + if selector_type == 'box': + selector = BoxSelector(**selector_data) + elif selector_type == 'lasso': + selector = LassoSelector(**selector_data) + else: + raise ValueError('Unsupported selector type: %s' % selector_type) + else: + selector = None + + # Build State Object + # ------------------ + if callback_data.get('state', None): + state_data = callback_data['state'] + state = InputState(**state_data) + else: + state = None + + # Build Trace Points Dictionary + # ----------------------------- + points_data = callback_data['points'] + trace_points = {trace_ind: {'point_inds': [], + 'xs': [], + 'ys': [], + 'trace_name': self._data_objs[trace_ind].plotly_name, + 'trace_index': trace_ind} + for trace_ind in range(len(self._data_objs))} + + for x, y, point_ind, trace_ind in zip(points_data['xs'], + points_data['ys'], + points_data['pointNumbers'], + points_data['curveNumbers']): + + trace_dict = trace_points[trace_ind] + trace_dict['xs'].append(x) + trace_dict['ys'].append(y) + trace_dict['point_inds'].append(point_ind) + + # Dispatch callbacks + # ------------------ + for trace_ind, trace_points_data in trace_points.items(): + points = Points(**trace_points_data) + trace = self.data[trace_ind] # type: BaseTraceType + + if event_type == 'plotly_click': + trace._dispatch_on_click(points, state) + elif event_type == 'plotly_hover': + trace._dispatch_on_hover(points, state) + elif event_type == 'plotly_unhover': + trace._dispatch_on_unhover(points, state) + elif event_type == 'plotly_selected': + trace._dispatch_on_selected(points, selector) + + # Custom Messages + # --------------- + def _handler_messages(self, widget, content, buffers): + """Handle a msg from the front-end. + """ + if content.get('event', '') == 'svg': + req_id = content['req_id'] + svg_uri = content['svg_uri'] + self._do_save_image(req_id, svg_uri) + + # Validate No Frames + # ------------------ + @property + def frames(self): + return self._frame_objs + + @frames.setter + def frames(self, new_frames): + if new_frames: + BaseFigureWidget._display_frames_error() + + @staticmethod + def _display_frames_error(): + msg = ("Frames are not supported by the datatypes.FigureWidget class.\n" + "Note: Frames are supported by the datatypes.Figure class") + + raise ValueError(msg) diff --git a/ipyplotly/ipyplotly/callbacks.py b/ipyplotly/ipyplotly/callbacks.py new file mode 100644 index 00000000000..1f3653cde1a --- /dev/null +++ b/ipyplotly/ipyplotly/callbacks.py @@ -0,0 +1,171 @@ +import typing as typ + + +class InputState: + def __init__(self, ctrl=None, alt=None, shift=None, meta=None, button=None, buttons=None, **_): + self._ctrl = ctrl + self._alt = alt + self._meta = meta + self._shift = shift + self._button = button + self._buttons = buttons + + def __repr__(self): + return """\ +InputState(ctrl={ctrl}, + alt={alt}, + shift={shift}, + meta={meta}, + button={button}, + buttons={buttons})""" + + @property + def alt(self) -> bool: + """ + Whether alt key pressed + + Returns + ------- + bool + """ + return self._alt + + @property + def ctrl(self) -> bool: + """ + Whether ctrl key pressed + + Returns + ------- + bool + """ + return self._ctrl + + @property + def shift(self) -> bool: + """ + Whether shift key pressed + + Returns + ------- + bool + """ + return self._shift + + @property + def meta(self) -> bool: + """ + Whether meta key pressed + + Returns + ------- + bool + """ + return self._meta + + @property + def button(self) -> int: + """ + Integer code for the button that was pressed on the mouse to trigger the event + + - 0: Main button pressed, usually the left button or the un-initialized state + - 1: Auxiliary button pressed, usually the wheel button or the middle button (if present) + - 2: Secondary button pressed, usually the right button + - 3: Fourth button, typically the Browser Back button + - 4: Fifth button, typically the Browser Forward button + + Returns + ------- + int + """ + return self._button + + @property + def buttons(self) -> int: + """ + Integer code for which combination of buttons are pressed on the mouse when the event is triggered. + + - 0: No button or un-initialized + - 1: Primary button (usually left) + - 2: Secondary button (usually right) + - 4: Auxilary button (usually middle or mouse wheel button) + - 8: 4th button (typically the "Browser Back" button) + - 16: 5th button (typically the "Browser Forward" button) + + Combinations of buttons are represented as the decimal form of the bitmask of the values above. + + For example, pressing both the primary (1) and auxilary (4) buttons will result in a code of 5 + + Returns + ------- + int + """ + return self._buttons + + +class Points: + + def __init__(self, point_inds=None, xs=None, ys=None, trace_name=None, trace_index=None): + self._point_inds = point_inds + self._xs = xs + self._ys = ys + self._trace_name = trace_name + self._trace_index = trace_index + + @property + def point_inds(self) -> typ.List[int]: + return self._point_inds + + @property + def xs(self) -> typ.List: + return self._xs + + @property + def ys(self) -> typ.List: + return self._ys + + @property + def trace_name(self) -> str: + return self._trace_name + + @property + def trace_index(self) -> int: + return self._trace_index + + +class BoxSelector: + def __init__(self, xrange=None, yrange=None, **_): + self._type = 'box' + self._xrange = xrange + self._yrange = yrange + + @property + def type(self) -> str: + return self._type + + @property + def xrange(self) -> typ.Tuple[float, float]: + return self._xrange + + @property + def yrange(self) -> typ.Tuple[float, float]: + return self._yrange + + +class LassoSelector: + def __init__(self, xs=None, ys=None, **_): + self._type = 'lasso' + self._xs = xs + self._ys = ys + + @property + def type(self) -> str: + return self._type + + @property + def xs(self) -> typ.List[float]: + return self._xs + + @property + def ys(self) -> typ.List[float]: + return self._ys diff --git a/ipyplotly/ipyplotly/serializers.py b/ipyplotly/ipyplotly/serializers.py new file mode 100644 index 00000000000..97651a44abe --- /dev/null +++ b/ipyplotly/ipyplotly/serializers.py @@ -0,0 +1,41 @@ + +# Create sentinal Undefined object +from traitlets import Undefined +import numpy as np + +def _py_to_js(v, widget_manager): + # print('_py_to_js') + # print(v) + if isinstance(v, dict): + return {k: _py_to_js(v, widget_manager) for k, v in v.items()} + elif isinstance(v, (list, tuple)): + return [_py_to_js(v, widget_manager) for v in v] + elif isinstance(v, np.ndarray): + if v.ndim == 1 and v.dtype.kind in ['u', 'i', 'f']: # (un)signed integer or float + return {'buffer': memoryview(v), 'dtype': str(v.dtype), 'shape': v.shape} + else: + return v.tolist() + else: + if v is Undefined: + return '_undefined_' + else: + return v + + +def _js_to_py(v, widget_manager): + # print('_js_to_py') + # print(v) + if isinstance(v, dict): + return {k: _js_to_py(v, widget_manager) for k, v in v.items()} + elif isinstance(v, (list, tuple)): + return [_js_to_py(v, widget_manager) for v in v] + elif isinstance(v, str) and v == '_undefined_': + return Undefined + else: + return v + + +custom_serializers = { + 'from_json': _js_to_py, + 'to_json': _py_to_js +} diff --git a/ipyplotly/js/README.md b/ipyplotly/js/README.md new file mode 100644 index 00000000000..92d5c28bd55 --- /dev/null +++ b/ipyplotly/js/README.md @@ -0,0 +1,11 @@ +pythonic plotly API for use in Jupyter + +Package Install +--------------- + +**Prerequisites** +- [node](http://nodejs.org/) + +```bash +npm install --save ipyplotly +``` diff --git a/ipyplotly/js/package-lock.json b/ipyplotly/js/package-lock.json new file mode 100644 index 00000000000..821c6ff5058 --- /dev/null +++ b/ipyplotly/js/package-lock.json @@ -0,0 +1,8331 @@ +{ + "name": "ipyplotly", + "version": "0.1.0", + "lockfileVersion": 1, + "requires": true, + "dependencies": { + "3d-view": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/3d-view/-/3d-view-2.0.0.tgz", + "integrity": "sha1-gxrpQtdQjFCAHj4G+v4ejFdOF74=", + "requires": { + "matrix-camera-controller": "2.1.3", + "orbit-camera-controller": "4.0.0", + "turntable-camera-controller": "3.0.1" + } + }, + "3d-view-controls": { + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/3d-view-controls/-/3d-view-controls-2.2.2.tgz", + "integrity": "sha512-WL0u3PN41lEx/4qvKqV6bJlweUYoW18FXMshW/qHb41AVdZxDReLoJNGYsI7x6jf9bYelEF62BJPQmO7yEnG2w==", + "requires": { + "3d-view": "2.0.0", + "has-passive-events": "1.0.0", + "mouse-change": "1.4.0", + "mouse-event-offset": "3.0.2", + "mouse-wheel": "1.2.0", + "right-now": "1.0.0" + } + }, + "@jupyter-widgets/base": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/@jupyter-widgets/base/-/base-1.1.5.tgz", + "integrity": "sha512-stYIv2jKk6XIc26JUITY4r8KoLLU+eG6PSU7dJb6JA4lAhntuezjN4hPvOapA6BWUFzJhZgA0oHcNZi2wKDYKA==", + "requires": { + "@jupyterlab/services": "0.52.0", + "@phosphor/coreutils": "1.3.0", + "@phosphor/messaging": "1.2.2", + "@phosphor/widgets": "1.5.0", + "@types/backbone": "1.3.42", + "@types/lodash": "4.14.91", + "backbone": "1.2.3", + "base64-js": "1.2.1", + "jquery": "3.2.1", + "lodash": "4.17.4" + } + }, + "@jupyterlab/coreutils": { + "version": "0.13.0", + "resolved": "https://registry.npmjs.org/@jupyterlab/coreutils/-/coreutils-0.13.0.tgz", + "integrity": "sha512-ezJgU+SLPX2z8jK3qD83/RAJRacQEVBIP5dqFXPVCfNkdwHeKWrgOvMQqiUJfDLAz7ZV42NRkWe+URk0PNkR0A==", + "requires": { + "@phosphor/algorithm": "1.1.2", + "@phosphor/coreutils": "1.3.0", + "@phosphor/disposable": "1.1.2", + "@phosphor/signaling": "1.2.2", + "ajv": "5.1.6", + "comment-json": "1.1.3", + "minimist": "1.2.0", + "moment": "2.17.1", + "path-posix": "1.0.0", + "url-parse": "1.1.9" + } + }, + "@jupyterlab/observables": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/@jupyterlab/observables/-/observables-0.2.0.tgz", + "integrity": "sha512-p88Ubrb+1VghJkZhq5qhuPa13y3zSwjFPnJ0Q1MRf6/wE49AKjWP49bON/vw3SBGeH22UGwvoU7i8h2yhPO7wg==", + "requires": { + "@phosphor/algorithm": "1.1.2", + "@phosphor/coreutils": "1.3.0", + "@phosphor/disposable": "1.1.2", + "@phosphor/messaging": "1.2.2", + "@phosphor/signaling": "1.2.2" + } + }, + "@jupyterlab/services": { + "version": "0.52.0", + "resolved": "https://registry.npmjs.org/@jupyterlab/services/-/services-0.52.0.tgz", + "integrity": "sha512-b+Qnf+O9Fh8cFWg9FN5z8rpSiEKx/ZHDkKhvENYKxkdwwtqA5I69/Xzi/gG5AV89I67ru3DP0yPByuR2s5X/OQ==", + "requires": { + "@jupyterlab/coreutils": "0.13.0", + "@jupyterlab/observables": "0.2.0", + "@phosphor/algorithm": "1.1.2", + "@phosphor/coreutils": "1.3.0", + "@phosphor/disposable": "1.1.2", + "@phosphor/signaling": "1.2.2" + } + }, + "@phosphor/algorithm": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@phosphor/algorithm/-/algorithm-1.1.2.tgz", + "integrity": "sha1-/R3pEEyafzTpKGRYbd8ufy53eeg=" + }, + "@phosphor/collections": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@phosphor/collections/-/collections-1.1.2.tgz", + "integrity": "sha1-xMC4uREpkF+zap8kPy273kYtq40=", + "requires": { + "@phosphor/algorithm": "1.1.2" + } + }, + "@phosphor/commands": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/@phosphor/commands/-/commands-1.4.0.tgz", + "integrity": "sha1-fiNqTAFdrzepWG/eKRiMPawgFi8=", + "requires": { + "@phosphor/algorithm": "1.1.2", + "@phosphor/coreutils": "1.3.0", + "@phosphor/disposable": "1.1.2", + "@phosphor/domutils": "1.1.2", + "@phosphor/keyboard": "1.1.2", + "@phosphor/signaling": "1.2.2" + } + }, + "@phosphor/coreutils": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/@phosphor/coreutils/-/coreutils-1.3.0.tgz", + "integrity": "sha1-YyktOBwBLFqw0Blug87YKbfgSkI=" + }, + "@phosphor/disposable": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@phosphor/disposable/-/disposable-1.1.2.tgz", + "integrity": "sha1-oZLdai5sadXQnTns8zTauTd4Bg4=", + "requires": { + "@phosphor/algorithm": "1.1.2" + } + }, + "@phosphor/domutils": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@phosphor/domutils/-/domutils-1.1.2.tgz", + "integrity": "sha1-4u/rBS85jEK5O4npurJq8VzABRQ=" + }, + "@phosphor/dragdrop": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/@phosphor/dragdrop/-/dragdrop-1.3.0.tgz", + "integrity": "sha1-fOatOdbKIW1ipW94EE0Cp3rmcwc=", + "requires": { + "@phosphor/coreutils": "1.3.0", + "@phosphor/disposable": "1.1.2" + } + }, + "@phosphor/keyboard": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@phosphor/keyboard/-/keyboard-1.1.2.tgz", + "integrity": "sha1-PjIjRFF2QkCpjhSANNWoeXQi3R8=" + }, + "@phosphor/messaging": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/@phosphor/messaging/-/messaging-1.2.2.tgz", + "integrity": "sha1-fYlt3TeXuUo0dwje0T2leD23XBQ=", + "requires": { + "@phosphor/algorithm": "1.1.2", + "@phosphor/collections": "1.1.2" + } + }, + "@phosphor/properties": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@phosphor/properties/-/properties-1.1.2.tgz", + "integrity": "sha1-eMx37/RSg52gIlXeSOgUlGzAmig=" + }, + "@phosphor/signaling": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/@phosphor/signaling/-/signaling-1.2.2.tgz", + "integrity": "sha1-P8+Xyojji/s1f+j+a/dRM0elFKk=", + "requires": { + "@phosphor/algorithm": "1.1.2" + } + }, + "@phosphor/virtualdom": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@phosphor/virtualdom/-/virtualdom-1.1.2.tgz", + "integrity": "sha1-zlXIbu8x5dDiax3JbqMr1oRFj0E=", + "requires": { + "@phosphor/algorithm": "1.1.2" + } + }, + "@phosphor/widgets": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/@phosphor/widgets/-/widgets-1.5.0.tgz", + "integrity": "sha1-X5mOhvX9542KpE19wUdobKZhaB4=", + "requires": { + "@phosphor/algorithm": "1.1.2", + "@phosphor/commands": "1.4.0", + "@phosphor/coreutils": "1.3.0", + "@phosphor/disposable": "1.1.2", + "@phosphor/domutils": "1.1.2", + "@phosphor/dragdrop": "1.3.0", + "@phosphor/keyboard": "1.1.2", + "@phosphor/messaging": "1.2.2", + "@phosphor/properties": "1.1.2", + "@phosphor/signaling": "1.2.2", + "@phosphor/virtualdom": "1.1.2" + } + }, + "@plotly/d3-sankey": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/@plotly/d3-sankey/-/d3-sankey-0.5.0.tgz", + "integrity": "sha1-si+up0LlglEzXuXZ+6JIdyYHgA8=", + "requires": { + "d3-array": "1.2.1", + "d3-collection": "1.0.4", + "d3-interpolate": "1.1.6" + } + }, + "@types/backbone": { + "version": "1.3.42", + "resolved": "https://registry.npmjs.org/@types/backbone/-/backbone-1.3.42.tgz", + "integrity": "sha512-sg6WhUW1RorO/Yc0yKqVhekBlweLbQqJciHr70FYL4Z8IFhcZngyXaYdfq8MCv/Rf/Nry5Sbsl9jWGzUN+2Zbg==", + "requires": { + "@types/jquery": "3.2.17", + "@types/underscore": "1.8.6" + } + }, + "@types/jquery": { + "version": "3.2.17", + "resolved": "https://registry.npmjs.org/@types/jquery/-/jquery-3.2.17.tgz", + "integrity": "sha512-lt8i2ZqymxxN1JnWSOTPU7Xc3ze32lhASkVdsMd6/SZnb/jtBsmFEoYCBSa0tzGDSyO7ZB+4r4aihj+KTlDs5w==" + }, + "@types/lodash": { + "version": "4.14.91", + "resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.14.91.tgz", + "integrity": "sha512-k+nc3moSlAaXacyvz4/c6D9lnUeI6AKsLvkXFuNzUEEqMw7sjDnLW2GqlJ4nyFgMX/p+QzvVG6zRoDo4lJIV5g==" + }, + "@types/underscore": { + "version": "1.8.6", + "resolved": "https://registry.npmjs.org/@types/underscore/-/underscore-1.8.6.tgz", + "integrity": "sha512-9r3G/aelGEmiGT6DKmvPvMxPQG387pQpS6gDuylq/oUZ7n1XkyRe/I+Kiln6Up9pjtIreusWJ8OjbczGX5g6Qg==" + }, + "JSV": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/JSV/-/JSV-4.0.2.tgz", + "integrity": "sha1-0Hf2glVx+CEy+d/67Vh7QCn+/1c=" + }, + "a-big-triangle": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/a-big-triangle/-/a-big-triangle-1.0.3.tgz", + "integrity": "sha1-7v0wsCqPUl6LH3K7a7GwwWdRx5Q=", + "requires": { + "gl-buffer": "2.1.2", + "gl-vao": "1.3.0", + "weak-map": "1.0.5" + } + }, + "abs-svg-path": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/abs-svg-path/-/abs-svg-path-0.1.1.tgz", + "integrity": "sha1-32Acjo0roQ1KdtYl4japo5wnI78=" + }, + "acorn": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-5.2.1.tgz", + "integrity": "sha512-jG0u7c4Ly+3QkkW18V+NRDN+4bWHdln30NL1ZL2AvFZZmQe/BfopYCtghCKKVBUSetZ4QKcyA0pY6/4Gw8Pv8w==" + }, + "acorn-dynamic-import": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/acorn-dynamic-import/-/acorn-dynamic-import-2.0.2.tgz", + "integrity": "sha1-x1K9IQvvZ5UBtsbLf8hPj0cVjMQ=", + "dev": true, + "requires": { + "acorn": "4.0.13" + }, + "dependencies": { + "acorn": { + "version": "4.0.13", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-4.0.13.tgz", + "integrity": "sha1-EFSVrlNh1pe9GVyCUZLhrX8lN4c=", + "dev": true + } + } + }, + "acorn-jsx": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-3.0.1.tgz", + "integrity": "sha1-r9+UiPsezvyDSPb7IvRk4ypYs2s=", + "requires": { + "acorn": "3.3.0" + }, + "dependencies": { + "acorn": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-3.3.0.tgz", + "integrity": "sha1-ReN/s56No/JbruP/U2niu18iAXo=" + } + } + }, + "acorn5-object-spread": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/acorn5-object-spread/-/acorn5-object-spread-4.0.0.tgz", + "integrity": "sha1-1XWAge7ZcSGrC+R+Mcqu8qo5lpc=", + "requires": { + "acorn": "5.2.1" + } + }, + "add-line-numbers": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/add-line-numbers/-/add-line-numbers-1.0.1.tgz", + "integrity": "sha1-SNu96kfb0jTer+rGyTzqb3C0t+M=", + "requires": { + "pad-left": "1.0.2" + } + }, + "affine-hull": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/affine-hull/-/affine-hull-1.0.0.tgz", + "integrity": "sha1-dj/x040GPOt+Jy8X7k17vK+QXF0=", + "requires": { + "robust-orientation": "1.1.3" + } + }, + "ajv": { + "version": "5.1.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-5.1.6.tgz", + "integrity": "sha1-Sy8aGd7Ok9V6whYDfj6XkcfdFWQ=", + "requires": { + "co": "4.6.0", + "json-schema-traverse": "0.3.1", + "json-stable-stringify": "1.0.1" + } + }, + "ajv-keywords": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-2.1.1.tgz", + "integrity": "sha1-YXmX/F9gV2iUxDX5QNgZ4TW4B2I=", + "dev": true + }, + "align-text": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/align-text/-/align-text-0.1.4.tgz", + "integrity": "sha1-DNkKVhCT810KmSVsIrcGlDP60Rc=", + "requires": { + "kind-of": "3.2.2", + "longest": "1.0.1", + "repeat-string": "1.6.1" + } + }, + "almost-equal": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/almost-equal/-/almost-equal-1.1.0.tgz", + "integrity": "sha1-+FHGMROHV5lCdqou++jfowZszN0=" + }, + "alpha-complex": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/alpha-complex/-/alpha-complex-1.0.0.tgz", + "integrity": "sha1-kIZYcNawVCrnPAwTHU75iWabctI=", + "requires": { + "circumradius": "1.0.0", + "delaunay-triangulate": "1.1.6" + } + }, + "alpha-shape": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/alpha-shape/-/alpha-shape-1.0.0.tgz", + "integrity": "sha1-yDEJkj7P2mZ9IWP+Tyb+JHJvZKk=", + "requires": { + "alpha-complex": "1.0.0", + "simplicial-complex-boundary": "1.0.1" + } + }, + "amdefine": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/amdefine/-/amdefine-1.0.1.tgz", + "integrity": "sha1-SlKCrBZHKek2Gbz9OtFR+BfOkfU=" + }, + "ansi-regex": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", + "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", + "dev": true + }, + "ansi-styles": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.0.tgz", + "integrity": "sha512-NnSOmMEYtVR2JVMIGTzynRkkaxtiq1xnFBcdQD/DnNCYPoEPsVJhM98BDyaoNOQIi7p4okdi3E27eN7GQbsUug==", + "requires": { + "color-convert": "1.9.1" + } + }, + "anymatch": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-1.3.2.tgz", + "integrity": "sha512-0XNayC8lTHQ2OI8aljNCN3sSx6hsr/1+rlcDAotXJR7C1oZZHCNsfpbKwMjRA3Uqb5tF1Rae2oloTr4xpq+WjA==", + "dev": true, + "requires": { + "micromatch": "2.3.11", + "normalize-path": "2.1.1" + } + }, + "arr-diff": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-2.0.0.tgz", + "integrity": "sha1-jzuCf5Vai9ZpaX5KQlasPOrjVs8=", + "dev": true, + "requires": { + "arr-flatten": "1.1.0" + } + }, + "arr-flatten": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/arr-flatten/-/arr-flatten-1.1.0.tgz", + "integrity": "sha512-L3hKV5R/p5o81R7O02IGnwpDmkp6E982XhtbuwSe3O4qOtMMMtodicASA1Cny2U+aCXcNpml+m4dPsvsJ3jatg==", + "dev": true + }, + "array-bounds": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/array-bounds/-/array-bounds-1.0.1.tgz", + "integrity": "sha512-8wdW3ZGk6UjMPJx/glyEt0sLzzwAE1bhToPsO1W2pbpR2gULyxe3BjSiuJFheP50T/GgODVPz2fuMUmIywt8cQ==" + }, + "array-normalize": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/array-normalize/-/array-normalize-1.1.3.tgz", + "integrity": "sha1-c/uDf0gW7BkVHTxejYU6RZDOAb0=", + "requires": { + "array-bounds": "1.0.1" + } + }, + "array-pack-2d": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/array-pack-2d/-/array-pack-2d-0.1.1.tgz", + "integrity": "sha1-vb3PL3+xm/uOBvvwHYvIxmS0aT0=", + "requires": { + "dtype": "1.0.0" + }, + "dependencies": { + "dtype": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/dtype/-/dtype-1.0.0.tgz", + "integrity": "sha1-rjT/ooJnNxUgNYLWG73QqtPLo+c=" + } + } + }, + "array-range": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/array-range/-/array-range-1.0.1.tgz", + "integrity": "sha1-9W5GWRhDYRxqVvd+8C7afFAIm/w=" + }, + "array-unique": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.2.1.tgz", + "integrity": "sha1-odl8yvy8JiXMcPrc6zalDFiwGlM=", + "dev": true + }, + "asn1": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.3.tgz", + "integrity": "sha1-2sh4dxPJlmhJ/IGAd36+nB3fO4Y=" + }, + "asn1.js": { + "version": "4.9.2", + "resolved": "https://registry.npmjs.org/asn1.js/-/asn1.js-4.9.2.tgz", + "integrity": "sha512-b/OsSjvWEo8Pi8H0zsDd2P6Uqo2TK2pH8gNLSJtNLM2Db0v2QaAZ0pBQJXVjAn4gBuugeVDr7s63ZogpUIwWDg==", + "dev": true, + "requires": { + "bn.js": "4.11.8", + "inherits": "2.0.3", + "minimalistic-assert": "1.0.0" + } + }, + "assert": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/assert/-/assert-1.4.1.tgz", + "integrity": "sha1-mZEtWRg2tab1s0XA8H7vwI/GXZE=", + "dev": true, + "requires": { + "util": "0.10.3" + } + }, + "assert-plus": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", + "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=" + }, + "async": { + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/async/-/async-2.6.0.tgz", + "integrity": "sha512-xAfGg1/NTLBBKlHFmnd7PlmUW9KhVQIUuSrYem9xzFUZy13ScvtyGGejaae9iAVRiRq9+Cx7DPFaAAhCpyxyPw==", + "dev": true, + "requires": { + "lodash": "4.17.4" + } + }, + "async-each": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/async-each/-/async-each-1.0.1.tgz", + "integrity": "sha1-GdOGodntxufByF04iu28xW0zYC0=", + "dev": true + }, + "asynckit": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", + "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=" + }, + "atob-lite": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/atob-lite/-/atob-lite-1.0.0.tgz", + "integrity": "sha1-uI3KYAaSK5YglPdVaCa6sxxKKWs=" + }, + "aws-sign2": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.7.0.tgz", + "integrity": "sha1-tG6JCTSpWR8tL2+G1+ap8bP+dqg=" + }, + "aws4": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.6.0.tgz", + "integrity": "sha1-g+9cqGCysy5KDe7e6MdxudtXRx4=" + }, + "backbone": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/backbone/-/backbone-1.2.3.tgz", + "integrity": "sha1-wiz9B/yG676uYdGJKe0RXpmdZbk=", + "requires": { + "underscore": "1.8.3" + } + }, + "balanced-match": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", + "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=" + }, + "barycentric": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/barycentric/-/barycentric-1.0.1.tgz", + "integrity": "sha1-8VYruJGyb0/sRjqC7to2V4AOxog=", + "requires": { + "robust-linear-solve": "1.0.0" + } + }, + "base64-js": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.2.1.tgz", + "integrity": "sha512-dwVUVIXsBZXwTuwnXI9RK8sBmgq09NDHzyR9SAph9eqk76gKK2JSQmZARC2zRC81JC2QTtxD0ARU5qTS25gIGw==" + }, + "bcrypt-pbkdf": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.1.tgz", + "integrity": "sha1-Y7xdy2EzG5K8Bf1SiVPDNGKgb40=", + "optional": true, + "requires": { + "tweetnacl": "0.14.5" + } + }, + "big-rat": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/big-rat/-/big-rat-1.0.4.tgz", + "integrity": "sha1-do0JO7V5MN0Y7Vdcf8on3FORreo=", + "requires": { + "bit-twiddle": "1.0.2", + "bn.js": "4.11.8", + "double-bits": "1.1.1" + } + }, + "big.js": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/big.js/-/big.js-3.2.0.tgz", + "integrity": "sha512-+hN/Zh2D08Mx65pZ/4g5bsmNiZUuChDiQfTUQ7qJr4/kuopCr88xZsAXv6mBoZEsUI4OuGHlX59qE94K2mMW8Q==", + "dev": true + }, + "binary-extensions": { + "version": "1.11.0", + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-1.11.0.tgz", + "integrity": "sha1-RqoXUftqL5PuXmibsQh9SxTGwgU=", + "dev": true + }, + "binary-search-bounds": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/binary-search-bounds/-/binary-search-bounds-1.0.0.tgz", + "integrity": "sha1-MjyjF+PypA9CRMclX1OEpbIHu2k=" + }, + "bit-twiddle": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/bit-twiddle/-/bit-twiddle-1.0.2.tgz", + "integrity": "sha1-DGwfq+KyPRcXPZpht7cJPrnhdp4=" + }, + "bitmap-sdf": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/bitmap-sdf/-/bitmap-sdf-1.0.3.tgz", + "integrity": "sha512-ojYySSvWTx21cbgntR942zgEgqj38wHctN64vr4vYRFf3GKVmI23YlA94meWGkFslidwLwGCsMy2laJ3g/94Sg==", + "requires": { + "clamp": "1.0.1" + } + }, + "bl": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/bl/-/bl-1.2.1.tgz", + "integrity": "sha1-ysMo977kVzDUBLaSID/LWQ4XLV4=", + "requires": { + "readable-stream": "2.3.3" + }, + "dependencies": { + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=" + }, + "readable-stream": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.3.tgz", + "integrity": "sha512-m+qzzcn7KUxEmd1gMbchF+Y2eIUbieUaxkWtptyHywrX0rE8QEYqPC07Vuy4Wm32/xE16NcdBctb8S0Xe/5IeQ==", + "requires": { + "core-util-is": "1.0.2", + "inherits": "2.0.3", + "isarray": "1.0.0", + "process-nextick-args": "1.0.7", + "safe-buffer": "5.1.1", + "string_decoder": "1.0.3", + "util-deprecate": "1.0.2" + } + }, + "string_decoder": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.0.3.tgz", + "integrity": "sha512-4AH6Z5fzNNBcH+6XDMfA/BTt87skxqJlO0lAh3Dker5zThcAxG6mKz+iGu308UKoPPQ8Dcqx/4JhujzltRa+hQ==", + "requires": { + "safe-buffer": "5.1.1" + } + } + } + }, + "bn.js": { + "version": "4.11.8", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.8.tgz", + "integrity": "sha512-ItfYfPLkWHUjckQCk8xC+LwxgK8NYcXywGigJgSwOP8Y2iyWT4f2vsZnoOXTTbo+o5yXmIUJ4gn5538SO5S3gA==" + }, + "boom": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/boom/-/boom-4.3.1.tgz", + "integrity": "sha1-T4owBctKfjiJ90kDD9JbluAdLjE=", + "requires": { + "hoek": "4.2.0" + } + }, + "bops": { + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/bops/-/bops-0.0.6.tgz", + "integrity": "sha1-CC0dVfoB5g29wuvC26N/ZZVUzzo=", + "requires": { + "base64-js": "0.0.2", + "to-utf8": "0.0.1" + }, + "dependencies": { + "base64-js": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-0.0.2.tgz", + "integrity": "sha1-Ak8Pcq+iW3X5wO5zzU9V7Bvtl4Q=" + } + } + }, + "boundary-cells": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/boundary-cells/-/boundary-cells-2.0.1.tgz", + "integrity": "sha1-6QWo0UGc9Hyza+Pb9SXbXiTeAEI=", + "requires": { + "tape": "4.8.0" + } + }, + "box-intersect": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/box-intersect/-/box-intersect-1.0.1.tgz", + "integrity": "sha1-tyilnj8aPHPCJJM8JmC5J6oTeQI=", + "requires": { + "bit-twiddle": "1.0.2", + "typedarray-pool": "1.1.0" + } + }, + "brace-expansion": { + "version": "1.1.8", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.8.tgz", + "integrity": "sha1-wHshHHyVLsH479Uad+8NHTmQopI=", + "requires": { + "balanced-match": "1.0.0", + "concat-map": "0.0.1" + } + }, + "braces": { + "version": "1.8.5", + "resolved": "https://registry.npmjs.org/braces/-/braces-1.8.5.tgz", + "integrity": "sha1-uneWLhLf+WnWt2cR6RS3N4V79qc=", + "dev": true, + "requires": { + "expand-range": "1.8.2", + "preserve": "0.2.0", + "repeat-element": "1.1.2" + } + }, + "brfs": { + "version": "1.4.4", + "resolved": "https://registry.npmjs.org/brfs/-/brfs-1.4.4.tgz", + "integrity": "sha512-rX2qc9hkpLPiwdu1HkLY642rwwo3X6N+ZPyEPdNn3OUKV/B2BRP7dHdnkhGantOJLVoTluNYBi4VecHb2Kq2hw==", + "requires": { + "quote-stream": "1.0.2", + "resolve": "1.4.0", + "static-module": "2.1.1", + "through2": "2.0.3" + }, + "dependencies": { + "duplexer2": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/duplexer2/-/duplexer2-0.1.4.tgz", + "integrity": "sha1-ixLauHjA1p4+eJEFFmKjL8a93ME=", + "requires": { + "readable-stream": "2.3.3" + } + }, + "escodegen": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/escodegen/-/escodegen-1.9.0.tgz", + "integrity": "sha512-v0MYvNQ32bzwoG2OSFzWAkuahDQHK92JBN0pTAALJ4RIxEZe766QJPDR8Hqy7XNUy5K3fnVL76OqYAdc4TZEIw==", + "requires": { + "esprima": "3.1.3", + "estraverse": "4.2.0", + "esutils": "2.0.2", + "optionator": "0.8.2", + "source-map": "0.5.7" + } + }, + "esprima": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-3.1.3.tgz", + "integrity": "sha1-/cpRzuYTOJXjyI1TXOSdv/YqRjM=" + }, + "estraverse": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.2.0.tgz", + "integrity": "sha1-De4/7TH81GlhjOc0IJn8GvoL2xM=" + }, + "esutils": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.2.tgz", + "integrity": "sha1-Cr9PHKpbyx96nYrMbepPqqBLrJs=" + }, + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=" + }, + "object-inspect": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.4.1.tgz", + "integrity": "sha512-wqdhLpfCUbEsoEwl3FXwGyv8ief1k/1aUdIPCqVnupM6e8l63BEJdiF/0swtn04/8p05tG/T0FrpTlfwvljOdw==" + }, + "quote-stream": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/quote-stream/-/quote-stream-1.0.2.tgz", + "integrity": "sha1-hJY/jJwmuULhU/7rU6rnRlK34LI=", + "requires": { + "buffer-equal": "0.0.1", + "minimist": "1.2.0", + "through2": "2.0.3" + } + }, + "readable-stream": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.3.tgz", + "integrity": "sha512-m+qzzcn7KUxEmd1gMbchF+Y2eIUbieUaxkWtptyHywrX0rE8QEYqPC07Vuy4Wm32/xE16NcdBctb8S0Xe/5IeQ==", + "requires": { + "core-util-is": "1.0.2", + "inherits": "2.0.3", + "isarray": "1.0.0", + "process-nextick-args": "1.0.7", + "safe-buffer": "5.1.1", + "string_decoder": "1.0.3", + "util-deprecate": "1.0.2" + } + }, + "source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", + "optional": true + }, + "static-eval": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/static-eval/-/static-eval-2.0.0.tgz", + "integrity": "sha512-6flshd3F1Gwm+Ksxq463LtFd1liC77N/PX1FVVc3OzL3hAmo2fwHFbuArkcfi7s9rTNsLEhcRmXGFZhlgy40uw==", + "requires": { + "escodegen": "1.9.0" + } + }, + "static-module": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/static-module/-/static-module-2.1.1.tgz", + "integrity": "sha512-PPLCnxRl74wV38rG1T0rH8Fl2wIktTXFo7/varrZjtSGb/vndZIGkpe4HJVd8hoBYXRkRHW6hlCRAHvmDgrYQQ==", + "requires": { + "concat-stream": "1.6.0", + "duplexer2": "0.1.4", + "escodegen": "1.9.0", + "falafel": "2.1.0", + "has": "1.0.1", + "object-inspect": "1.4.1", + "quote-stream": "1.0.2", + "readable-stream": "2.3.3", + "shallow-copy": "0.0.1", + "static-eval": "2.0.0", + "through2": "2.0.3" + } + }, + "string_decoder": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.0.3.tgz", + "integrity": "sha512-4AH6Z5fzNNBcH+6XDMfA/BTt87skxqJlO0lAh3Dker5zThcAxG6mKz+iGu308UKoPPQ8Dcqx/4JhujzltRa+hQ==", + "requires": { + "safe-buffer": "5.1.1" + } + }, + "through2": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.3.tgz", + "integrity": "sha1-AARWmzfHx0ujnEPzzteNGtlBQL4=", + "requires": { + "readable-stream": "2.3.3", + "xtend": "4.0.1" + } + } + } + }, + "brorand": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/brorand/-/brorand-1.1.0.tgz", + "integrity": "sha1-EsJe/kCkXjwyPrhnWgoM5XsiNx8=", + "dev": true + }, + "browserify-aes": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/browserify-aes/-/browserify-aes-1.1.1.tgz", + "integrity": "sha512-UGnTYAnB2a3YuYKIRy1/4FB2HdM866E0qC46JXvVTYKlBlZlnvfpSfY6OKfXZAkv70eJ2a1SqzpAo5CRhZGDFg==", + "dev": true, + "requires": { + "buffer-xor": "1.0.3", + "cipher-base": "1.0.4", + "create-hash": "1.1.3", + "evp_bytestokey": "1.0.3", + "inherits": "2.0.3", + "safe-buffer": "5.1.1" + } + }, + "browserify-cipher": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/browserify-cipher/-/browserify-cipher-1.0.0.tgz", + "integrity": "sha1-mYgkSHS/XtTijalWZtzWasj8Njo=", + "dev": true, + "requires": { + "browserify-aes": "1.1.1", + "browserify-des": "1.0.0", + "evp_bytestokey": "1.0.3" + } + }, + "browserify-des": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/browserify-des/-/browserify-des-1.0.0.tgz", + "integrity": "sha1-2qJ3cXRwki7S/hhZQRihdUOXId0=", + "dev": true, + "requires": { + "cipher-base": "1.0.4", + "des.js": "1.0.0", + "inherits": "2.0.3" + } + }, + "browserify-rsa": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/browserify-rsa/-/browserify-rsa-4.0.1.tgz", + "integrity": "sha1-IeCr+vbyApzy+vsTNWenAdQTVSQ=", + "dev": true, + "requires": { + "bn.js": "4.11.8", + "randombytes": "2.0.5" + } + }, + "browserify-sign": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/browserify-sign/-/browserify-sign-4.0.4.tgz", + "integrity": "sha1-qk62jl17ZYuqa/alfmMMvXqT0pg=", + "dev": true, + "requires": { + "bn.js": "4.11.8", + "browserify-rsa": "4.0.1", + "create-hash": "1.1.3", + "create-hmac": "1.1.6", + "elliptic": "6.4.0", + "inherits": "2.0.3", + "parse-asn1": "5.1.0" + } + }, + "browserify-zlib": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/browserify-zlib/-/browserify-zlib-0.2.0.tgz", + "integrity": "sha512-Z942RysHXmJrhqk88FmKBVq/v5tqmSkDz7p54G/MGyjMnCFFnC79XWNbg+Vta8W6Wb2qtSZTSxIGkJrRpCFEiA==", + "dev": true, + "requires": { + "pako": "1.0.6" + } + }, + "buble": { + "version": "0.18.0", + "resolved": "https://registry.npmjs.org/buble/-/buble-0.18.0.tgz", + "integrity": "sha512-U3NJxUiSz0H1EB54PEHAuBTxdXgQH4DaQkvkINFXf9kEKCDWSn67EgQfFKbkTzsok4xRrIPsoxWDl2czCHR65g==", + "requires": { + "acorn": "5.2.1", + "acorn-jsx": "3.0.1", + "acorn5-object-spread": "4.0.0", + "chalk": "2.3.0", + "magic-string": "0.22.4", + "minimist": "1.2.0", + "os-homedir": "1.0.2", + "vlq": "0.2.3" + } + }, + "bubleify": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/bubleify/-/bubleify-1.1.0.tgz", + "integrity": "sha512-9FtUiQong0qiDuN/iOtDwqovyDXENTpcvQH9Szyc/wzALPt0tDdP1moIjJqeT5LMwLzvLkMHaL+RohWEeHY6XQ==", + "requires": { + "buble": "0.18.0" + } + }, + "buffer": { + "version": "4.9.1", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-4.9.1.tgz", + "integrity": "sha1-bRu2AbB6TvztlwlBMgkwJ8lbwpg=", + "dev": true, + "requires": { + "base64-js": "1.2.1", + "ieee754": "1.1.8", + "isarray": "1.0.0" + }, + "dependencies": { + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", + "dev": true + } + } + }, + "buffer-equal": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/buffer-equal/-/buffer-equal-0.0.1.tgz", + "integrity": "sha1-kbx0sR6kBbyRa8aqkI+q+ltKrEs=" + }, + "buffer-xor": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/buffer-xor/-/buffer-xor-1.0.3.tgz", + "integrity": "sha1-JuYe0UIvtw3ULm42cp7VHYVf6Nk=", + "dev": true + }, + "builtin-modules": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/builtin-modules/-/builtin-modules-1.1.1.tgz", + "integrity": "sha1-Jw8HbFpywC9bZaR9+Uxf46J4iS8=", + "dev": true + }, + "builtin-status-codes": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/builtin-status-codes/-/builtin-status-codes-3.0.0.tgz", + "integrity": "sha1-hZgoeOIbmOHGZCXgPQF0eI9Wnug=", + "dev": true + }, + "call-matcher": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/call-matcher/-/call-matcher-1.0.1.tgz", + "integrity": "sha1-UTTQd5hPcSpU2tPL9i3ijc5BbKg=", + "requires": { + "core-js": "2.5.3", + "deep-equal": "1.0.1", + "espurify": "1.7.0", + "estraverse": "4.2.0" + }, + "dependencies": { + "estraverse": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.2.0.tgz", + "integrity": "sha1-De4/7TH81GlhjOc0IJn8GvoL2xM=" + } + } + }, + "camelcase": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-1.2.1.tgz", + "integrity": "sha1-m7UwTS4LVmmLLHWLCKPqqdqlijk=" + }, + "canvas-fit": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/canvas-fit/-/canvas-fit-1.5.0.tgz", + "integrity": "sha1-rhO+Zq3kL1vg5IfjRfzjCl5bXl8=", + "requires": { + "element-size": "1.1.1" + } + }, + "caseless": { + "version": "0.12.0", + "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz", + "integrity": "sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw=" + }, + "cdt2d": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/cdt2d/-/cdt2d-1.0.0.tgz", + "integrity": "sha1-TyEkNLzWe9s9aLj+9KzcLFRBUUE=", + "requires": { + "binary-search-bounds": "2.0.4", + "robust-in-sphere": "1.1.3", + "robust-orientation": "1.1.3" + }, + "dependencies": { + "binary-search-bounds": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/binary-search-bounds/-/binary-search-bounds-2.0.4.tgz", + "integrity": "sha512-2hg5kgdKql5ClF2ErBcSx0U5bnl5hgS4v7wMnLFodyR47yMtj2w+UAZB+0CiqyHct2q543i7Bi4/aMIegorCCg==" + } + } + }, + "cell-orientation": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/cell-orientation/-/cell-orientation-1.0.1.tgz", + "integrity": "sha1-tQStlqZq0obZ7dmFoiU9A7gNKFA=" + }, + "center-align": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/center-align/-/center-align-0.1.3.tgz", + "integrity": "sha1-qg0yYptu6XIgBBHL1EYckHvCt60=", + "requires": { + "align-text": "0.1.4", + "lazy-cache": "1.0.4" + } + }, + "chalk": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.3.0.tgz", + "integrity": "sha512-Az5zJR2CBujap2rqXGaJKaPHyJ0IrUimvYNX+ncCy8PJP4ltOGTrHUIo097ZaL2zMeKYpiCdqDvS6zdrTFok3Q==", + "requires": { + "ansi-styles": "3.2.0", + "escape-string-regexp": "1.0.5", + "supports-color": "4.5.0" + } + }, + "chokidar": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-1.7.0.tgz", + "integrity": "sha1-eY5ol3gVHIB2tLNg5e3SjNortGg=", + "dev": true, + "requires": { + "anymatch": "1.3.2", + "async-each": "1.0.1", + "fsevents": "1.1.3", + "glob-parent": "2.0.0", + "inherits": "2.0.3", + "is-binary-path": "1.0.1", + "is-glob": "2.0.1", + "path-is-absolute": "1.0.1", + "readdirp": "2.1.0" + } + }, + "cipher-base": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/cipher-base/-/cipher-base-1.0.4.tgz", + "integrity": "sha512-Kkht5ye6ZGmwv40uUDZztayT2ThLQGfnj/T71N/XzeZeo3nf8foyW7zGTsPYkEya3m5f3cAypH+qe7YOrM1U2Q==", + "dev": true, + "requires": { + "inherits": "2.0.3", + "safe-buffer": "5.1.1" + } + }, + "circumcenter": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/circumcenter/-/circumcenter-1.0.0.tgz", + "integrity": "sha1-INeqE7F/usUvUtpPVMasi5Bu5Sk=", + "requires": { + "dup": "1.0.0", + "robust-linear-solve": "1.0.0" + } + }, + "circumradius": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/circumradius/-/circumradius-1.0.0.tgz", + "integrity": "sha1-cGxEfj5VzR7T0RvRM+N8JSzDBbU=", + "requires": { + "circumcenter": "1.0.0" + } + }, + "clamp": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/clamp/-/clamp-1.0.1.tgz", + "integrity": "sha1-ZqDmQBGBbjcZaCj9yMjBRzEshjQ=" + }, + "clean-pslg": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/clean-pslg/-/clean-pslg-1.1.2.tgz", + "integrity": "sha1-vTXHRgt+irWp92Gl7VF5aqPIbBE=", + "requires": { + "big-rat": "1.0.4", + "box-intersect": "1.0.1", + "nextafter": "1.0.0", + "rat-vec": "1.1.1", + "robust-segment-intersect": "1.0.1", + "union-find": "1.0.2", + "uniq": "1.0.1" + } + }, + "cliui": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-2.1.0.tgz", + "integrity": "sha1-S0dXYP+AJkx2LDoXGQMukcf+oNE=", + "requires": { + "center-align": "0.1.3", + "right-align": "0.1.3", + "wordwrap": "0.0.2" + }, + "dependencies": { + "wordwrap": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-0.0.2.tgz", + "integrity": "sha1-t5Zpu0LstAn4PVg8rVLKF+qhZD8=" + } + } + }, + "co": { + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz", + "integrity": "sha1-bqa989hTrlTMuOR7+gvz+QMfsYQ=" + }, + "code-point-at": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz", + "integrity": "sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c=", + "dev": true + }, + "color-convert": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.1.tgz", + "integrity": "sha512-mjGanIiwQJskCC18rPR6OmrZ6fm2Lc7PeGFYwCmy5J34wC6F1PzdGL6xeMfmgicfYcNLGuVFA3WzXtIDCQSZxQ==", + "requires": { + "color-name": "1.1.3" + } + }, + "color-id": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/color-id/-/color-id-1.1.0.tgz", + "integrity": "sha512-2iRtAn6dC/6/G7bBIo0uupVrIne1NsQJvJxZOBCzQOfk7jRq97feaDZ3RdzuHakRXXnHGNwglto3pqtRx1sX0g==", + "requires": { + "clamp": "1.0.1" + } + }, + "color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=" + }, + "color-normalize": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/color-normalize/-/color-normalize-1.0.3.tgz", + "integrity": "sha512-bUyyoiyeJSm24u+y5ePwVssNg9zACjHKHUS0thYZEmCafrTg4RX1b43V6M141V2EdlaBoS5OV3VvyAXxdup+YA==", + "requires": { + "clamp": "1.0.1", + "color-rgba": "2.0.0", + "dtype": "2.0.0" + } + }, + "color-parse": { + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/color-parse/-/color-parse-1.3.5.tgz", + "integrity": "sha1-TIEPcugI5Pc7Y/cqzXjaU4pRVWQ=", + "requires": { + "color-name": "1.1.3", + "defined": "1.0.0", + "is-plain-obj": "1.1.0" + } + }, + "color-rgba": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/color-rgba/-/color-rgba-2.0.0.tgz", + "integrity": "sha1-0BURTOPoQ2h5XJ1t3+9Vb5gXOcU=", + "requires": { + "clamp": "1.0.1", + "color-parse": "1.3.5", + "color-space": "1.15.0" + } + }, + "color-space": { + "version": "1.15.0", + "resolved": "https://registry.npmjs.org/color-space/-/color-space-1.15.0.tgz", + "integrity": "sha1-JiP1TBGB4P5uHP8Nh+JOsQQPWw4=", + "requires": { + "husl": "5.0.3", + "mumath": "3.3.4" + } + }, + "colormap": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/colormap/-/colormap-2.3.0.tgz", + "integrity": "sha512-Mkk6mQUMbCleXEeStFm2xLwv5zbRakZMUFB1T1+iNEv58VKBByfPwYIjMQDwSRmXNM1gvo5y3WTYAhmdMn/rbg==", + "requires": { + "lerp": "1.0.3" + } + }, + "colors": { + "version": "0.6.2", + "resolved": "https://registry.npmjs.org/colors/-/colors-0.6.2.tgz", + "integrity": "sha1-JCP+ZnisDF2uiFLl0OW+CMmXq8w=" + }, + "combined-stream": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.5.tgz", + "integrity": "sha1-k4NwpXtKUd6ix3wV1cX9+JUWQAk=", + "requires": { + "delayed-stream": "1.0.0" + } + }, + "commander": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.1.0.tgz", + "integrity": "sha1-0SG7roYNmZKj1Re6lvVliOR8Z4E=" + }, + "comment-json": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/comment-json/-/comment-json-1.1.3.tgz", + "integrity": "sha1-aYbDMw/uDEyeAMI5jNYa+l2PI54=", + "requires": { + "json-parser": "1.1.5" + } + }, + "compare-angle": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/compare-angle/-/compare-angle-1.0.1.tgz", + "integrity": "sha1-pOtjQW6jx0f8a9bItjZotN5PoSk=", + "requires": { + "robust-orientation": "1.1.3", + "robust-product": "1.0.0", + "robust-sum": "1.0.0", + "signum": "0.0.0", + "two-sum": "1.0.0" + } + }, + "compare-cell": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/compare-cell/-/compare-cell-1.0.0.tgz", + "integrity": "sha1-qetwj24OQa73qlZrEw8ZaNyeGqo=" + }, + "compare-oriented-cell": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/compare-oriented-cell/-/compare-oriented-cell-1.0.1.tgz", + "integrity": "sha1-ahSf7vnfxPj8YjWOUd1C7/u9w54=", + "requires": { + "cell-orientation": "1.0.1", + "compare-cell": "1.0.0" + } + }, + "concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=" + }, + "concat-stream": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.6.0.tgz", + "integrity": "sha1-CqxmL9Ur54lk1VMvaUeE5wEQrPc=", + "requires": { + "inherits": "2.0.3", + "readable-stream": "2.3.3", + "typedarray": "0.0.6" + }, + "dependencies": { + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=" + }, + "readable-stream": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.3.tgz", + "integrity": "sha512-m+qzzcn7KUxEmd1gMbchF+Y2eIUbieUaxkWtptyHywrX0rE8QEYqPC07Vuy4Wm32/xE16NcdBctb8S0Xe/5IeQ==", + "requires": { + "core-util-is": "1.0.2", + "inherits": "2.0.3", + "isarray": "1.0.0", + "process-nextick-args": "1.0.7", + "safe-buffer": "5.1.1", + "string_decoder": "1.0.3", + "util-deprecate": "1.0.2" + } + }, + "string_decoder": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.0.3.tgz", + "integrity": "sha512-4AH6Z5fzNNBcH+6XDMfA/BTt87skxqJlO0lAh3Dker5zThcAxG6mKz+iGu308UKoPPQ8Dcqx/4JhujzltRa+hQ==", + "requires": { + "safe-buffer": "5.1.1" + } + } + } + }, + "console-browserify": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/console-browserify/-/console-browserify-1.1.0.tgz", + "integrity": "sha1-8CQcRXMKn8YyOyBtvzjtx0HQuxA=", + "dev": true, + "requires": { + "date-now": "0.1.4" + } + }, + "constants-browserify": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/constants-browserify/-/constants-browserify-1.0.0.tgz", + "integrity": "sha1-wguW2MYXdIqvHBYCF2DNJ/y4y3U=", + "dev": true + }, + "convert-source-map": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.5.1.tgz", + "integrity": "sha1-uCeAl7m8IpNl3lxiz1/K7YtVmeU=" + }, + "convex-hull": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/convex-hull/-/convex-hull-1.0.3.tgz", + "integrity": "sha1-IKOqbOh/St6i/30XlxyfwcZ+H/8=", + "requires": { + "affine-hull": "1.0.0", + "incremental-convex-hull": "1.0.1", + "monotone-convex-hull-2d": "1.0.1" + } + }, + "core-js": { + "version": "2.5.3", + "resolved": "https://registry.npmjs.org/core-js/-/core-js-2.5.3.tgz", + "integrity": "sha1-isw4NFgk8W2DZbfJtCWRaOjtYD4=" + }, + "core-util-is": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", + "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=" + }, + "country-regex": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/country-regex/-/country-regex-1.1.0.tgz", + "integrity": "sha1-UcMz3N8Sknt+XuucEKyBEqYSCJY=" + }, + "create-ecdh": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/create-ecdh/-/create-ecdh-4.0.0.tgz", + "integrity": "sha1-iIxyNZbN92EvZJgjPuvXo1MBc30=", + "dev": true, + "requires": { + "bn.js": "4.11.8", + "elliptic": "6.4.0" + } + }, + "create-hash": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/create-hash/-/create-hash-1.1.3.tgz", + "integrity": "sha1-YGBCrIuSYnUPSDyt2rD1gZFy2P0=", + "dev": true, + "requires": { + "cipher-base": "1.0.4", + "inherits": "2.0.3", + "ripemd160": "2.0.1", + "sha.js": "2.4.9" + } + }, + "create-hmac": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/create-hmac/-/create-hmac-1.1.6.tgz", + "integrity": "sha1-rLniIaThe9sHbpBlfEK5PjcmzwY=", + "dev": true, + "requires": { + "cipher-base": "1.0.4", + "create-hash": "1.1.3", + "inherits": "2.0.3", + "ripemd160": "2.0.1", + "safe-buffer": "5.1.1", + "sha.js": "2.4.9" + } + }, + "cross-spawn": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-5.1.0.tgz", + "integrity": "sha1-6L0O/uWPz/b4+UUQoKVUu/ojVEk=", + "dev": true, + "requires": { + "lru-cache": "4.1.1", + "shebang-command": "1.2.0", + "which": "1.3.0" + } + }, + "cryptiles": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/cryptiles/-/cryptiles-3.1.2.tgz", + "integrity": "sha1-qJ+7Ig9c4l7FboxKqKT9e1sNKf4=", + "requires": { + "boom": "5.2.0" + }, + "dependencies": { + "boom": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/boom/-/boom-5.2.0.tgz", + "integrity": "sha512-Z5BTk6ZRe4tXXQlkqftmsAUANpXmuwlsF5Oov8ThoMbQRzdGTA1ngYRW160GexgOgjsFOKJz0LYhoNi+2AMBUw==", + "requires": { + "hoek": "4.2.0" + } + } + } + }, + "crypto-browserify": { + "version": "3.12.0", + "resolved": "https://registry.npmjs.org/crypto-browserify/-/crypto-browserify-3.12.0.tgz", + "integrity": "sha512-fz4spIh+znjO2VjL+IdhEpRJ3YN6sMzITSBijk6FK2UvTqruSQW+/cCZTSNsMiZNvUeq0CqurF+dAbyiGOY6Wg==", + "dev": true, + "requires": { + "browserify-cipher": "1.0.0", + "browserify-sign": "4.0.4", + "create-ecdh": "4.0.0", + "create-hash": "1.1.3", + "create-hmac": "1.1.6", + "diffie-hellman": "5.0.2", + "inherits": "2.0.3", + "pbkdf2": "3.0.14", + "public-encrypt": "4.0.0", + "randombytes": "2.0.5", + "randomfill": "1.0.3" + } + }, + "csscolorparser": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/csscolorparser/-/csscolorparser-1.0.3.tgz", + "integrity": "sha1-s085HupNqPPpgjHizNjfnAQfFxs=" + }, + "cubic-hermite": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/cubic-hermite/-/cubic-hermite-1.0.0.tgz", + "integrity": "sha1-hOOy8nKzFFToOTuZu2rtRRaMFOU=" + }, + "cwise": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/cwise/-/cwise-1.0.10.tgz", + "integrity": "sha1-JO7mBy69/WuMb12tsXCQtkmxK+8=", + "requires": { + "cwise-compiler": "1.1.3", + "cwise-parser": "1.0.3", + "static-module": "1.5.0", + "uglify-js": "2.8.29" + } + }, + "cwise-compiler": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/cwise-compiler/-/cwise-compiler-1.1.3.tgz", + "integrity": "sha1-9NZnQQ6FDToxOn0tt7HlBbsDTMU=", + "requires": { + "uniq": "1.0.1" + } + }, + "cwise-parser": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/cwise-parser/-/cwise-parser-1.0.3.tgz", + "integrity": "sha1-jkk8F9VPl8sDCp6YVLyGyd+zVP4=", + "requires": { + "esprima": "1.2.5", + "uniq": "1.0.1" + }, + "dependencies": { + "esprima": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-1.2.5.tgz", + "integrity": "sha1-CZNQL+r2aBODJXVvMPmlH+7sEek=" + } + } + }, + "d": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/d/-/d-1.0.0.tgz", + "integrity": "sha1-dUu1v+VUUdpppYuU1F9MWwRi1Y8=", + "dev": true, + "requires": { + "es5-ext": "0.10.37" + } + }, + "d3": { + "version": "3.5.17", + "resolved": "https://registry.npmjs.org/d3/-/d3-3.5.17.tgz", + "integrity": "sha1-vEZ0gAQ3iyGjYMn8fPUjF5B2L7g=" + }, + "d3-array": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/d3-array/-/d3-array-1.2.1.tgz", + "integrity": "sha512-CyINJQ0SOUHojDdFDH4JEM0552vCR1utGyLHegJHyYH0JyCpSeTPxi4OBqHMA2jJZq4NH782LtaJWBImqI/HBw==" + }, + "d3-collection": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/d3-collection/-/d3-collection-1.0.4.tgz", + "integrity": "sha1-NC39EoN8kJdPM/HMCnha6lcNzcI=" + }, + "d3-color": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/d3-color/-/d3-color-1.0.3.tgz", + "integrity": "sha1-vHZD/KjlOoNH4vva/6I2eWtYUJs=" + }, + "d3-dispatch": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/d3-dispatch/-/d3-dispatch-1.0.3.tgz", + "integrity": "sha1-RuFJHqqbWMNY/OW+TovtYm54cfg=" + }, + "d3-force": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/d3-force/-/d3-force-1.1.0.tgz", + "integrity": "sha512-2HVQz3/VCQs0QeRNZTYb7GxoUCeb6bOzMp/cGcLa87awY9ZsPvXOGeZm0iaGBjXic6I1ysKwMn+g+5jSAdzwcg==", + "requires": { + "d3-collection": "1.0.4", + "d3-dispatch": "1.0.3", + "d3-quadtree": "1.0.3", + "d3-timer": "1.0.7" + } + }, + "d3-interpolate": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/d3-interpolate/-/d3-interpolate-1.1.6.tgz", + "integrity": "sha512-mOnv5a+pZzkNIHtw/V6I+w9Lqm9L5bG3OTXPM5A+QO0yyVMQ4W1uZhR+VOJmazaOZXri2ppbiZ5BUNWT0pFM9A==", + "requires": { + "d3-color": "1.0.3" + } + }, + "d3-quadtree": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/d3-quadtree/-/d3-quadtree-1.0.3.tgz", + "integrity": "sha1-rHmH4+I/6AWpkPKOG1DTj8uCJDg=" + }, + "d3-timer": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/d3-timer/-/d3-timer-1.0.7.tgz", + "integrity": "sha512-vMZXR88XujmG/L5oB96NNKH5lCWwiLM/S2HyyAQLcjWJCloK5shxta4CwOFYLZoY3AWX73v8Lgv4cCAdWtRmOA==" + }, + "dashdash": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz", + "integrity": "sha1-hTz6D3y+L+1d4gMmuN1YEDX24vA=", + "requires": { + "assert-plus": "1.0.0" + } + }, + "date-now": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/date-now/-/date-now-0.1.4.tgz", + "integrity": "sha1-6vQ5/U1ISK105cx9vvIAZyueNFs=", + "dev": true + }, + "decamelize": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", + "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=" + }, + "deep-equal": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/deep-equal/-/deep-equal-1.0.1.tgz", + "integrity": "sha1-9dJgKStmDghO/0zbyfCK0yR0SLU=" + }, + "deep-is": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.3.tgz", + "integrity": "sha1-s2nW+128E+7PUk+RsHD+7cNXzzQ=" + }, + "define-properties": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.2.tgz", + "integrity": "sha1-g6c/L+pWmJj7c3GTyPhzyvbUXJQ=", + "requires": { + "foreach": "2.0.5", + "object-keys": "1.0.11" + } + }, + "defined": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/defined/-/defined-1.0.0.tgz", + "integrity": "sha1-yY2bzvdWdBiOEQlpFRGZ45sfppM=" + }, + "delaunay-triangulate": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/delaunay-triangulate/-/delaunay-triangulate-1.1.6.tgz", + "integrity": "sha1-W7yiGweBmNS8PHV5ajXLuYwllUw=", + "requires": { + "incremental-convex-hull": "1.0.1", + "uniq": "1.0.1" + } + }, + "delayed-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", + "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=" + }, + "des.js": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/des.js/-/des.js-1.0.0.tgz", + "integrity": "sha1-wHTS4qpqipoH29YfmhXCzYPsjsw=", + "dev": true, + "requires": { + "inherits": "2.0.3", + "minimalistic-assert": "1.0.0" + } + }, + "diffie-hellman": { + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/diffie-hellman/-/diffie-hellman-5.0.2.tgz", + "integrity": "sha1-tYNXOScM/ias9jIJn97SoH8gnl4=", + "dev": true, + "requires": { + "bn.js": "4.11.8", + "miller-rabin": "4.0.1", + "randombytes": "2.0.5" + } + }, + "domain-browser": { + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/domain-browser/-/domain-browser-1.1.7.tgz", + "integrity": "sha1-hnqksJP6oF8d4IwG9NeyH9+GmLw=", + "dev": true + }, + "double-bits": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/double-bits/-/double-bits-1.1.1.tgz", + "integrity": "sha1-WKu6RUlNpND6Nrc60RoobJGEscY=" + }, + "draw-svg-path": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/draw-svg-path/-/draw-svg-path-1.0.0.tgz", + "integrity": "sha1-bxFtli3TFLmepTTW9Y3WbNvWk3k=", + "requires": { + "abs-svg-path": "0.1.1", + "normalize-svg-path": "0.1.0" + } + }, + "dtype": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/dtype/-/dtype-2.0.0.tgz", + "integrity": "sha1-zQUjI84GFETs0uj1dI9popvihDQ=" + }, + "dup": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/dup/-/dup-1.0.0.tgz", + "integrity": "sha1-UfxaxoX4GWRp3wuQXpNLIK9bQCk=" + }, + "duplexer2": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/duplexer2/-/duplexer2-0.0.2.tgz", + "integrity": "sha1-xhTc9n4vsUmVqRcR5aYX6KYKMds=", + "requires": { + "readable-stream": "1.1.14" + }, + "dependencies": { + "readable-stream": { + "version": "1.1.14", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz", + "integrity": "sha1-fPTFTvZI44EwhMY23SB54WbAgdk=", + "requires": { + "core-util-is": "1.0.2", + "inherits": "2.0.3", + "isarray": "0.0.1", + "string_decoder": "0.10.31" + } + } + } + }, + "duplexify": { + "version": "3.5.3", + "resolved": "https://registry.npmjs.org/duplexify/-/duplexify-3.5.3.tgz", + "integrity": "sha512-g8ID9OroF9hKt2POf8YLayy+9594PzmM3scI00/uBXocX3TWNgoB67hjzkFe9ITAbQOne/lLdBxHXvYUM4ZgGA==", + "requires": { + "end-of-stream": "1.4.1", + "inherits": "2.0.3", + "readable-stream": "2.3.3", + "stream-shift": "1.0.0" + }, + "dependencies": { + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=" + }, + "readable-stream": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.3.tgz", + "integrity": "sha512-m+qzzcn7KUxEmd1gMbchF+Y2eIUbieUaxkWtptyHywrX0rE8QEYqPC07Vuy4Wm32/xE16NcdBctb8S0Xe/5IeQ==", + "requires": { + "core-util-is": "1.0.2", + "inherits": "2.0.3", + "isarray": "1.0.0", + "process-nextick-args": "1.0.7", + "safe-buffer": "5.1.1", + "string_decoder": "1.0.3", + "util-deprecate": "1.0.2" + } + }, + "string_decoder": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.0.3.tgz", + "integrity": "sha512-4AH6Z5fzNNBcH+6XDMfA/BTt87skxqJlO0lAh3Dker5zThcAxG6mKz+iGu308UKoPPQ8Dcqx/4JhujzltRa+hQ==", + "requires": { + "safe-buffer": "5.1.1" + } + } + } + }, + "earcut": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/earcut/-/earcut-2.1.3.tgz", + "integrity": "sha512-AxdCdWUk1zzK/NuZ7e1ljj6IGC+VAdC3Qb7QQDsXpfNrc5IM8tL9nNXUmEGE6jRHTfZ10zhzRhtDmWVsR5pd3A==" + }, + "ecc-jsbn": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.1.tgz", + "integrity": "sha1-D8c6ntXw1Tw4GTOYUj735UN3dQU=", + "optional": true, + "requires": { + "jsbn": "0.1.1" + } + }, + "edges-to-adjacency-list": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/edges-to-adjacency-list/-/edges-to-adjacency-list-1.0.0.tgz", + "integrity": "sha1-wUbS4ISt37p0pRKTxuAZmkn3V/E=", + "requires": { + "uniq": "1.0.1" + } + }, + "element-size": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/element-size/-/element-size-1.1.1.tgz", + "integrity": "sha1-ZOXxWdlxIWMYRby67K8nnDm1404=" + }, + "elliptic": { + "version": "6.4.0", + "resolved": "https://registry.npmjs.org/elliptic/-/elliptic-6.4.0.tgz", + "integrity": "sha1-ysmvh2LIWDYYcAPI3+GT5eLq5d8=", + "dev": true, + "requires": { + "bn.js": "4.11.8", + "brorand": "1.1.0", + "hash.js": "1.1.3", + "hmac-drbg": "1.0.1", + "inherits": "2.0.3", + "minimalistic-assert": "1.0.0", + "minimalistic-crypto-utils": "1.0.1" + } + }, + "emojis-list": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/emojis-list/-/emojis-list-2.1.0.tgz", + "integrity": "sha1-TapNnbAPmBmIDHn6RXrlsJof04k=", + "dev": true + }, + "end-of-stream": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.1.tgz", + "integrity": "sha512-1MkrZNvWTKCaigbn+W15elq2BB/L22nqrSY5DKlo3X6+vclJm8Bb5djXJBmEX6fS3+zCh/F4VBK5Z2KxJt4s2Q==", + "requires": { + "once": "1.4.0" + } + }, + "enhanced-resolve": { + "version": "3.4.1", + "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-3.4.1.tgz", + "integrity": "sha1-BCHjOf1xQZs9oT0Smzl5BAIwR24=", + "dev": true, + "requires": { + "graceful-fs": "4.1.11", + "memory-fs": "0.4.1", + "object-assign": "4.1.1", + "tapable": "0.2.8" + } + }, + "errno": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/errno/-/errno-0.1.6.tgz", + "integrity": "sha512-IsORQDpaaSwcDP4ZZnHxgE85werpo34VYn1Ud3mq+eUsF593faR8oCZNXrROVkpFu2TsbrNhHin0aUrTsQ9vNw==", + "dev": true, + "requires": { + "prr": "1.0.1" + } + }, + "error-ex": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.1.tgz", + "integrity": "sha1-+FWobOYa3E6GIcPNoh56dhLDqNw=", + "dev": true, + "requires": { + "is-arrayish": "0.2.1" + } + }, + "es-abstract": { + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.10.0.tgz", + "integrity": "sha512-/uh/DhdqIOSkAWifU+8nG78vlQxdLckUdI/sPgy0VhuXi2qJ7T8czBmqIYtLQVpCIFYafChnsRsB5pyb1JdmCQ==", + "requires": { + "es-to-primitive": "1.1.1", + "function-bind": "1.1.1", + "has": "1.0.1", + "is-callable": "1.1.3", + "is-regex": "1.0.4" + } + }, + "es-to-primitive": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.1.1.tgz", + "integrity": "sha1-RTVSSKiJeQNLZ5Lhm7gfK3l13Q0=", + "requires": { + "is-callable": "1.1.3", + "is-date-object": "1.0.1", + "is-symbol": "1.0.1" + } + }, + "es5-ext": { + "version": "0.10.37", + "resolved": "https://registry.npmjs.org/es5-ext/-/es5-ext-0.10.37.tgz", + "integrity": "sha1-DudB0Ui4AGm6J9AgOTdWryV978M=", + "dev": true, + "requires": { + "es6-iterator": "2.0.3", + "es6-symbol": "3.1.1" + } + }, + "es6-iterator": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/es6-iterator/-/es6-iterator-2.0.3.tgz", + "integrity": "sha1-p96IkUGgWpSwhUQDstCg+/qY87c=", + "dev": true, + "requires": { + "d": "1.0.0", + "es5-ext": "0.10.37", + "es6-symbol": "3.1.1" + } + }, + "es6-map": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/es6-map/-/es6-map-0.1.5.tgz", + "integrity": "sha1-kTbgUD3MBqMBaQ8LsU/042TpSfA=", + "dev": true, + "requires": { + "d": "1.0.0", + "es5-ext": "0.10.37", + "es6-iterator": "2.0.3", + "es6-set": "0.1.5", + "es6-symbol": "3.1.1", + "event-emitter": "0.3.5" + } + }, + "es6-promise": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/es6-promise/-/es6-promise-3.3.1.tgz", + "integrity": "sha1-oIzd6EzNvzTQJ6FFG8kdS80ophM=" + }, + "es6-set": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/es6-set/-/es6-set-0.1.5.tgz", + "integrity": "sha1-0rPsXU2ADO2BjbU40ol02wpzzLE=", + "dev": true, + "requires": { + "d": "1.0.0", + "es5-ext": "0.10.37", + "es6-iterator": "2.0.3", + "es6-symbol": "3.1.1", + "event-emitter": "0.3.5" + } + }, + "es6-symbol": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/es6-symbol/-/es6-symbol-3.1.1.tgz", + "integrity": "sha1-vwDvT9q2uhtG7Le2KbTH7VcVzHc=", + "dev": true, + "requires": { + "d": "1.0.0", + "es5-ext": "0.10.37" + } + }, + "es6-weak-map": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/es6-weak-map/-/es6-weak-map-2.0.2.tgz", + "integrity": "sha1-XjqzIlH/0VOKH45f+hNXdy+S2W8=", + "dev": true, + "requires": { + "d": "1.0.0", + "es5-ext": "0.10.37", + "es6-iterator": "2.0.3", + "es6-symbol": "3.1.1" + } + }, + "escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=" + }, + "escodegen": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/escodegen/-/escodegen-1.3.3.tgz", + "integrity": "sha1-8CQBb1qI4Eb9EgBQVek5gC5sXyM=", + "requires": { + "esprima": "1.1.1", + "estraverse": "1.5.1", + "esutils": "1.0.0", + "source-map": "0.1.43" + }, + "dependencies": { + "esprima": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-1.1.1.tgz", + "integrity": "sha1-W28VR/TRAuZw4UDFCb5ncdautUk=" + } + } + }, + "escope": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/escope/-/escope-3.6.0.tgz", + "integrity": "sha1-4Bl16BJ4GhY6ba392AOY3GTIicM=", + "dev": true, + "requires": { + "es6-map": "0.1.5", + "es6-weak-map": "2.0.2", + "esrecurse": "4.2.0", + "estraverse": "4.2.0" + }, + "dependencies": { + "estraverse": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.2.0.tgz", + "integrity": "sha1-De4/7TH81GlhjOc0IJn8GvoL2xM=", + "dev": true + } + } + }, + "esprima": { + "version": "2.7.3", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-2.7.3.tgz", + "integrity": "sha1-luO3DVd59q1JzQMmc9HDEnZ7pYE=" + }, + "espurify": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/espurify/-/espurify-1.7.0.tgz", + "integrity": "sha1-HFz2y8zDLm9jk4C9T5kfq5up0iY=", + "requires": { + "core-js": "2.5.3" + } + }, + "esrecurse": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.2.0.tgz", + "integrity": "sha1-+pVo2Y04I/mkHZHpAtyrnqblsWM=", + "dev": true, + "requires": { + "estraverse": "4.2.0", + "object-assign": "4.1.1" + }, + "dependencies": { + "estraverse": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.2.0.tgz", + "integrity": "sha1-De4/7TH81GlhjOc0IJn8GvoL2xM=", + "dev": true + } + } + }, + "estraverse": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-1.5.1.tgz", + "integrity": "sha1-hno+jlip+EYYr7bC3bzZFrfLr3E=" + }, + "esutils": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/esutils/-/esutils-1.0.0.tgz", + "integrity": "sha1-gVHTWOIMisx/t0XnRywAJf5JZXA=" + }, + "event-emitter": { + "version": "0.3.5", + "resolved": "https://registry.npmjs.org/event-emitter/-/event-emitter-0.3.5.tgz", + "integrity": "sha1-34xp7vFkeSPHFXuc6DhAYQsCzDk=", + "dev": true, + "requires": { + "d": "1.0.0", + "es5-ext": "0.10.37" + } + }, + "events": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/events/-/events-1.1.1.tgz", + "integrity": "sha1-nr23Y1rQmccNzEwqH1AEKI6L2SQ=" + }, + "evp_bytestokey": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/evp_bytestokey/-/evp_bytestokey-1.0.3.tgz", + "integrity": "sha512-/f2Go4TognH/KvCISP7OUsHn85hT9nUkxxA9BEWxFn+Oj9o8ZNLm/40hdlgSLyuOimsrTKLUMEorQexp/aPQeA==", + "dev": true, + "requires": { + "md5.js": "1.3.4", + "safe-buffer": "5.1.1" + } + }, + "execa": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/execa/-/execa-0.7.0.tgz", + "integrity": "sha1-lEvs00zEHuMqY6n68nrVpl/Fl3c=", + "dev": true, + "requires": { + "cross-spawn": "5.1.0", + "get-stream": "3.0.0", + "is-stream": "1.1.0", + "npm-run-path": "2.0.2", + "p-finally": "1.0.0", + "signal-exit": "3.0.2", + "strip-eof": "1.0.0" + } + }, + "expand-brackets": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-0.1.5.tgz", + "integrity": "sha1-3wcoTjQqgHzXM6xa9yQR5YHRF3s=", + "dev": true, + "requires": { + "is-posix-bracket": "0.1.1" + } + }, + "expand-range": { + "version": "1.8.2", + "resolved": "https://registry.npmjs.org/expand-range/-/expand-range-1.8.2.tgz", + "integrity": "sha1-opnv/TNf4nIeuujiV+x5ZE/IUzc=", + "dev": true, + "requires": { + "fill-range": "2.2.3" + } + }, + "extend": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.1.tgz", + "integrity": "sha1-p1Xqe8Gt/MWjHOfnYtuq3F5jZEQ=" + }, + "extglob": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/extglob/-/extglob-0.3.2.tgz", + "integrity": "sha1-Lhj/PS9JqydlzskCPwEdqo2DSaE=", + "dev": true, + "requires": { + "is-extglob": "1.0.0" + } + }, + "extract-frustum-planes": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/extract-frustum-planes/-/extract-frustum-planes-1.0.0.tgz", + "integrity": "sha1-l9VwP/BWTIw8aDjKxF+ee8UsnvU=" + }, + "extsprintf": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz", + "integrity": "sha1-lpGEQOMEGnpBT4xS48V06zw+HgU=" + }, + "falafel": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/falafel/-/falafel-2.1.0.tgz", + "integrity": "sha1-lrsXdh2rqU9G0AFzizzt86Z/4Gw=", + "requires": { + "acorn": "5.2.1", + "foreach": "2.0.5", + "isarray": "0.0.1", + "object-keys": "1.0.11" + } + }, + "fast-isnumeric": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/fast-isnumeric/-/fast-isnumeric-1.1.1.tgz", + "integrity": "sha1-V7gcB6PAnLnsO++cFhgYmS2JNkM=" + }, + "fast-levenshtein": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", + "integrity": "sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc=" + }, + "feature-filter": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/feature-filter/-/feature-filter-2.2.0.tgz", + "integrity": "sha1-PMNWAV6WjDYq+99/8bt0Td9/wuA=" + }, + "filename-regex": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/filename-regex/-/filename-regex-2.0.1.tgz", + "integrity": "sha1-wcS5vuPglyXdsQa3XB4wH+LxiyY=", + "dev": true + }, + "fill-range": { + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-2.2.3.tgz", + "integrity": "sha1-ULd9/X5Gm8dJJHCWNpn+eoSFpyM=", + "dev": true, + "requires": { + "is-number": "2.1.0", + "isobject": "2.1.0", + "randomatic": "1.1.7", + "repeat-element": "1.1.2", + "repeat-string": "1.6.1" + } + }, + "filtered-vector": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/filtered-vector/-/filtered-vector-1.2.4.tgz", + "integrity": "sha1-VkU8A030MC0pPKjs3qw/kKvGeNM=", + "requires": { + "binary-search-bounds": "1.0.0", + "cubic-hermite": "1.0.0" + } + }, + "find-up": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-2.1.0.tgz", + "integrity": "sha1-RdG35QbHF93UgndaK3eSCjwMV6c=", + "dev": true, + "requires": { + "locate-path": "2.0.0" + } + }, + "findup": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/findup/-/findup-0.1.5.tgz", + "integrity": "sha1-itkpozk7rGJ5V6fl3kYjsGsOLOs=", + "requires": { + "colors": "0.6.2", + "commander": "2.1.0" + } + }, + "flatten-vertex-data": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/flatten-vertex-data/-/flatten-vertex-data-1.0.0.tgz", + "integrity": "sha1-1hyU8qZWTzAdZni3JhYWrwAEcIw=", + "requires": { + "array-pack-2d": "0.1.1", + "dtype": "2.0.0", + "is-typedarray": "1.0.0" + } + }, + "font-atlas-sdf": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/font-atlas-sdf/-/font-atlas-sdf-1.3.3.tgz", + "integrity": "sha512-GxUpcdkdoHgC3UrpMuA7JmG1Ty/MY0BhfmV8r7ZSv3bkqBY5vmRIjcj7Pg8iqj20B03vlU6fUhdpyIgEo/Z35w==", + "requires": { + "optical-properties": "1.0.0", + "tiny-sdf": "1.0.2" + } + }, + "for-each": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.2.tgz", + "integrity": "sha1-LEBFC5NI6X8oEyJZO6lnBLmr1NQ=", + "requires": { + "is-function": "1.0.1" + } + }, + "for-in": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/for-in/-/for-in-1.0.2.tgz", + "integrity": "sha1-gQaNKVqBQuwKxybG4iAMMPttXoA=", + "dev": true + }, + "for-own": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/for-own/-/for-own-0.1.5.tgz", + "integrity": "sha1-UmXGgaTylNq78XyVCbZ2OqhFEM4=", + "dev": true, + "requires": { + "for-in": "1.0.2" + } + }, + "foreach": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/foreach/-/foreach-2.0.5.tgz", + "integrity": "sha1-C+4AUBiusmDQo6865ljdATbsG5k=" + }, + "forever-agent": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz", + "integrity": "sha1-+8cfDEGt6zf5bFd60e1C2P2sypE=" + }, + "form-data": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.3.1.tgz", + "integrity": "sha1-b7lPvXGIUwbXPRXMSX/kzE7NRL8=", + "requires": { + "asynckit": "0.4.0", + "combined-stream": "1.0.5", + "mime-types": "2.1.17" + } + }, + "from2": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/from2/-/from2-2.3.0.tgz", + "integrity": "sha1-i/tVAr3kpNNs/e6gB/zKIdfjgq8=", + "requires": { + "inherits": "2.0.3", + "readable-stream": "2.3.3" + }, + "dependencies": { + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=" + }, + "readable-stream": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.3.tgz", + "integrity": "sha512-m+qzzcn7KUxEmd1gMbchF+Y2eIUbieUaxkWtptyHywrX0rE8QEYqPC07Vuy4Wm32/xE16NcdBctb8S0Xe/5IeQ==", + "requires": { + "core-util-is": "1.0.2", + "inherits": "2.0.3", + "isarray": "1.0.0", + "process-nextick-args": "1.0.7", + "safe-buffer": "5.1.1", + "string_decoder": "1.0.3", + "util-deprecate": "1.0.2" + } + }, + "string_decoder": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.0.3.tgz", + "integrity": "sha512-4AH6Z5fzNNBcH+6XDMfA/BTt87skxqJlO0lAh3Dker5zThcAxG6mKz+iGu308UKoPPQ8Dcqx/4JhujzltRa+hQ==", + "requires": { + "safe-buffer": "5.1.1" + } + } + } + }, + "from2-array": { + "version": "0.0.4", + "resolved": "https://registry.npmjs.org/from2-array/-/from2-array-0.0.4.tgz", + "integrity": "sha1-6vwWtl9uJxm81X/cGGkAWsEzLNY=", + "dev": true, + "requires": { + "from2": "2.3.0" + } + }, + "from2-string": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/from2-string/-/from2-string-1.1.0.tgz", + "integrity": "sha1-GCgrJ9CKJnyzAwzSuLSw8hKvdSo=", + "requires": { + "from2": "2.3.0" + } + }, + "fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=" + }, + "fsevents": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-1.1.3.tgz", + "integrity": "sha512-WIr7iDkdmdbxu/Gh6eKEZJL6KPE74/5MEsf2whTOFNxbIoIixogroLdKYqB6FDav4Wavh/lZdzzd3b2KxIXC5Q==", + "dev": true, + "optional": true, + "requires": { + "nan": "2.8.0", + "node-pre-gyp": "0.6.39" + }, + "dependencies": { + "abbrev": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.0.tgz", + "integrity": "sha1-0FVMIlZjbi9W58LlrRg/hZQo2B8=", + "dev": true, + "optional": true + }, + "ajv": { + "version": "4.11.8", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-4.11.8.tgz", + "integrity": "sha1-gv+wKynmYq5TvcIK8VlHcGc5xTY=", + "dev": true, + "optional": true, + "requires": { + "co": "4.6.0", + "json-stable-stringify": "1.0.1" + } + }, + "ansi-regex": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", + "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", + "dev": true + }, + "aproba": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/aproba/-/aproba-1.1.1.tgz", + "integrity": "sha1-ldNgDwdxCqDpKYxyatXs8urLq6s=", + "dev": true, + "optional": true + }, + "are-we-there-yet": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-1.1.4.tgz", + "integrity": "sha1-u13KOCu5TwXhUZQ3PRb9O6HKEQ0=", + "dev": true, + "optional": true, + "requires": { + "delegates": "1.0.0", + "readable-stream": "2.2.9" + } + }, + "asn1": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.3.tgz", + "integrity": "sha1-2sh4dxPJlmhJ/IGAd36+nB3fO4Y=", + "dev": true, + "optional": true + }, + "assert-plus": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-0.2.0.tgz", + "integrity": "sha1-104bh+ev/A24qttwIfP+SBAasjQ=", + "dev": true, + "optional": true + }, + "asynckit": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", + "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=", + "dev": true, + "optional": true + }, + "aws-sign2": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.6.0.tgz", + "integrity": "sha1-FDQt0428yU0OW4fXY81jYSwOeU8=", + "dev": true, + "optional": true + }, + "aws4": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.6.0.tgz", + "integrity": "sha1-g+9cqGCysy5KDe7e6MdxudtXRx4=", + "dev": true, + "optional": true + }, + "balanced-match": { + "version": "0.4.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-0.4.2.tgz", + "integrity": "sha1-yz8+PHMtwPAe5wtAPzAuYddwmDg=", + "dev": true + }, + "bcrypt-pbkdf": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.1.tgz", + "integrity": "sha1-Y7xdy2EzG5K8Bf1SiVPDNGKgb40=", + "dev": true, + "optional": true, + "requires": { + "tweetnacl": "0.14.5" + } + }, + "block-stream": { + "version": "0.0.9", + "resolved": "https://registry.npmjs.org/block-stream/-/block-stream-0.0.9.tgz", + "integrity": "sha1-E+v+d4oDIFz+A3UUgeu0szAMEmo=", + "dev": true, + "requires": { + "inherits": "2.0.3" + } + }, + "boom": { + "version": "2.10.1", + "resolved": "https://registry.npmjs.org/boom/-/boom-2.10.1.tgz", + "integrity": "sha1-OciRjO/1eZ+D+UkqhI9iWt0Mdm8=", + "dev": true, + "requires": { + "hoek": "2.16.3" + } + }, + "brace-expansion": { + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.7.tgz", + "integrity": "sha1-Pv/DxQ4ABTH7cg6v+A8K6O8jz1k=", + "dev": true, + "requires": { + "balanced-match": "0.4.2", + "concat-map": "0.0.1" + } + }, + "buffer-shims": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/buffer-shims/-/buffer-shims-1.0.0.tgz", + "integrity": "sha1-mXjOMXOIxkmth5MCjDR37wRKi1E=", + "dev": true + }, + "caseless": { + "version": "0.12.0", + "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz", + "integrity": "sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw=", + "dev": true, + "optional": true + }, + "co": { + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz", + "integrity": "sha1-bqa989hTrlTMuOR7+gvz+QMfsYQ=", + "dev": true, + "optional": true + }, + "code-point-at": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz", + "integrity": "sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c=", + "dev": true + }, + "combined-stream": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.5.tgz", + "integrity": "sha1-k4NwpXtKUd6ix3wV1cX9+JUWQAk=", + "dev": true, + "requires": { + "delayed-stream": "1.0.0" + } + }, + "concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=", + "dev": true + }, + "console-control-strings": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz", + "integrity": "sha1-PXz0Rk22RG6mRL9LOVB/mFEAjo4=", + "dev": true + }, + "core-util-is": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", + "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=", + "dev": true + }, + "cryptiles": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/cryptiles/-/cryptiles-2.0.5.tgz", + "integrity": "sha1-O9/s3GCBR8HGcgL6KR59ylnqo7g=", + "dev": true, + "requires": { + "boom": "2.10.1" + } + }, + "dashdash": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz", + "integrity": "sha1-hTz6D3y+L+1d4gMmuN1YEDX24vA=", + "dev": true, + "optional": true, + "requires": { + "assert-plus": "1.0.0" + }, + "dependencies": { + "assert-plus": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", + "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=", + "dev": true, + "optional": true + } + } + }, + "debug": { + "version": "2.6.8", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.8.tgz", + "integrity": "sha1-5zFTHKLt4n0YgiJCfaF4IdaP9Pw=", + "dev": true, + "optional": true, + "requires": { + "ms": "2.0.0" + } + }, + "deep-extend": { + "version": "0.4.2", + "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.4.2.tgz", + "integrity": "sha1-SLaZwn4zS/ifEIkr5DL25MfTSn8=", + "dev": true, + "optional": true + }, + "delayed-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", + "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=", + "dev": true + }, + "delegates": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz", + "integrity": "sha1-hMbhWbgZBP3KWaDvRM2HDTElD5o=", + "dev": true, + "optional": true + }, + "detect-libc": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-1.0.2.tgz", + "integrity": "sha1-ca1dIEvxempsqPRQxhRUBm70YeE=", + "dev": true, + "optional": true + }, + "ecc-jsbn": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.1.tgz", + "integrity": "sha1-D8c6ntXw1Tw4GTOYUj735UN3dQU=", + "dev": true, + "optional": true, + "requires": { + "jsbn": "0.1.1" + } + }, + "extend": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.1.tgz", + "integrity": "sha1-p1Xqe8Gt/MWjHOfnYtuq3F5jZEQ=", + "dev": true, + "optional": true + }, + "extsprintf": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.0.2.tgz", + "integrity": "sha1-4QgOBljjALBilJkMxw4VAiNf1VA=", + "dev": true + }, + "forever-agent": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz", + "integrity": "sha1-+8cfDEGt6zf5bFd60e1C2P2sypE=", + "dev": true, + "optional": true + }, + "form-data": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.1.4.tgz", + "integrity": "sha1-M8GDrPGTJ27KqYFDpp6Uv+4XUNE=", + "dev": true, + "optional": true, + "requires": { + "asynckit": "0.4.0", + "combined-stream": "1.0.5", + "mime-types": "2.1.15" + } + }, + "fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", + "dev": true + }, + "fstream": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/fstream/-/fstream-1.0.11.tgz", + "integrity": "sha1-XB+x8RdHcRTwYyoOtLcbPLD9MXE=", + "dev": true, + "requires": { + "graceful-fs": "4.1.11", + "inherits": "2.0.3", + "mkdirp": "0.5.1", + "rimraf": "2.6.1" + } + }, + "fstream-ignore": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/fstream-ignore/-/fstream-ignore-1.0.5.tgz", + "integrity": "sha1-nDHa40dnAY/h0kmyTa2mfQktoQU=", + "dev": true, + "optional": true, + "requires": { + "fstream": "1.0.11", + "inherits": "2.0.3", + "minimatch": "3.0.4" + } + }, + "gauge": { + "version": "2.7.4", + "resolved": "https://registry.npmjs.org/gauge/-/gauge-2.7.4.tgz", + "integrity": "sha1-LANAXHU4w51+s3sxcCLjJfsBi/c=", + "dev": true, + "optional": true, + "requires": { + "aproba": "1.1.1", + "console-control-strings": "1.1.0", + "has-unicode": "2.0.1", + "object-assign": "4.1.1", + "signal-exit": "3.0.2", + "string-width": "1.0.2", + "strip-ansi": "3.0.1", + "wide-align": "1.1.2" + } + }, + "getpass": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz", + "integrity": "sha1-Xv+OPmhNVprkyysSgmBOi6YhSfo=", + "dev": true, + "optional": true, + "requires": { + "assert-plus": "1.0.0" + }, + "dependencies": { + "assert-plus": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", + "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=", + "dev": true, + "optional": true + } + } + }, + "glob": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.2.tgz", + "integrity": "sha512-MJTUg1kjuLeQCJ+ccE4Vpa6kKVXkPYJ2mOCQyUuKLcLQsdrMCpBPUi8qVE6+YuaJkozeA9NusTAw3hLr8Xe5EQ==", + "dev": true, + "requires": { + "fs.realpath": "1.0.0", + "inflight": "1.0.6", + "inherits": "2.0.3", + "minimatch": "3.0.4", + "once": "1.4.0", + "path-is-absolute": "1.0.1" + } + }, + "graceful-fs": { + "version": "4.1.11", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.11.tgz", + "integrity": "sha1-Dovf5NHduIVNZOBOp8AOKgJuVlg=", + "dev": true + }, + "har-schema": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/har-schema/-/har-schema-1.0.5.tgz", + "integrity": "sha1-0mMTX0MwfALGAq/I/pWXDAFRNp4=", + "dev": true, + "optional": true + }, + "har-validator": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-4.2.1.tgz", + "integrity": "sha1-M0gdDxu/9gDdID11gSpqX7oALio=", + "dev": true, + "optional": true, + "requires": { + "ajv": "4.11.8", + "har-schema": "1.0.5" + } + }, + "has-unicode": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz", + "integrity": "sha1-4Ob+aijPUROIVeCG0Wkedx3iqLk=", + "dev": true, + "optional": true + }, + "hawk": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/hawk/-/hawk-3.1.3.tgz", + "integrity": "sha1-B4REvXwWQLD+VA0sm3PVlnjo4cQ=", + "dev": true, + "requires": { + "boom": "2.10.1", + "cryptiles": "2.0.5", + "hoek": "2.16.3", + "sntp": "1.0.9" + } + }, + "hoek": { + "version": "2.16.3", + "resolved": "https://registry.npmjs.org/hoek/-/hoek-2.16.3.tgz", + "integrity": "sha1-ILt0A9POo5jpHcRxCo/xuCdKJe0=", + "dev": true + }, + "http-signature": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.1.1.tgz", + "integrity": "sha1-33LiZwZs0Kxn+3at+OE0qPvPkb8=", + "dev": true, + "optional": true, + "requires": { + "assert-plus": "0.2.0", + "jsprim": "1.4.0", + "sshpk": "1.13.0" + } + }, + "inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", + "dev": true, + "requires": { + "once": "1.4.0", + "wrappy": "1.0.2" + } + }, + "inherits": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", + "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=", + "dev": true + }, + "ini": { + "version": "1.3.4", + "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.4.tgz", + "integrity": "sha1-BTfLedr1m1mhpRff9wbIbsA5Fi4=", + "dev": true, + "optional": true + }, + "is-fullwidth-code-point": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", + "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", + "dev": true, + "requires": { + "number-is-nan": "1.0.1" + } + }, + "is-typedarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", + "integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=", + "dev": true, + "optional": true + }, + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", + "dev": true + }, + "isstream": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz", + "integrity": "sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo=", + "dev": true, + "optional": true + }, + "jodid25519": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/jodid25519/-/jodid25519-1.0.2.tgz", + "integrity": "sha1-BtSRIlUJNBlHfUJWM2BuDpB4KWc=", + "dev": true, + "optional": true, + "requires": { + "jsbn": "0.1.1" + } + }, + "jsbn": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz", + "integrity": "sha1-peZUwuWi3rXyAdls77yoDA7y9RM=", + "dev": true, + "optional": true + }, + "json-schema": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.2.3.tgz", + "integrity": "sha1-tIDIkuWaLwWVTOcnvT8qTogvnhM=", + "dev": true, + "optional": true + }, + "json-stable-stringify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json-stable-stringify/-/json-stable-stringify-1.0.1.tgz", + "integrity": "sha1-mnWdOcXy/1A/1TAGRu1EX4jE+a8=", + "dev": true, + "optional": true, + "requires": { + "jsonify": "0.0.0" + } + }, + "json-stringify-safe": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", + "integrity": "sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus=", + "dev": true, + "optional": true + }, + "jsonify": { + "version": "0.0.0", + "resolved": "https://registry.npmjs.org/jsonify/-/jsonify-0.0.0.tgz", + "integrity": "sha1-LHS27kHZPKUbe1qu6PUDYx0lKnM=", + "dev": true, + "optional": true + }, + "jsprim": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.0.tgz", + "integrity": "sha1-o7h+QCmNjDgFUtjMdiigu5WiKRg=", + "dev": true, + "optional": true, + "requires": { + "assert-plus": "1.0.0", + "extsprintf": "1.0.2", + "json-schema": "0.2.3", + "verror": "1.3.6" + }, + "dependencies": { + "assert-plus": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", + "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=", + "dev": true, + "optional": true + } + } + }, + "mime-db": { + "version": "1.27.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.27.0.tgz", + "integrity": "sha1-gg9XIpa70g7CXtVeW13oaeVDbrE=", + "dev": true + }, + "mime-types": { + "version": "2.1.15", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.15.tgz", + "integrity": "sha1-pOv1BkCUVpI3uM9wBGd20J/JKu0=", + "dev": true, + "requires": { + "mime-db": "1.27.0" + } + }, + "minimatch": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", + "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", + "dev": true, + "requires": { + "brace-expansion": "1.1.7" + } + }, + "minimist": { + "version": "0.0.8", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz", + "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=", + "dev": true + }, + "mkdirp": { + "version": "0.5.1", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz", + "integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=", + "dev": true, + "requires": { + "minimist": "0.0.8" + } + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", + "dev": true, + "optional": true + }, + "node-pre-gyp": { + "version": "0.6.39", + "resolved": "https://registry.npmjs.org/node-pre-gyp/-/node-pre-gyp-0.6.39.tgz", + "integrity": "sha512-OsJV74qxnvz/AMGgcfZoDaeDXKD3oY3QVIbBmwszTFkRisTSXbMQyn4UWzUMOtA5SVhrBZOTp0wcoSBgfMfMmQ==", + "dev": true, + "optional": true, + "requires": { + "detect-libc": "1.0.2", + "hawk": "3.1.3", + "mkdirp": "0.5.1", + "nopt": "4.0.1", + "npmlog": "4.1.0", + "rc": "1.2.1", + "request": "2.81.0", + "rimraf": "2.6.1", + "semver": "5.3.0", + "tar": "2.2.1", + "tar-pack": "3.4.0" + } + }, + "nopt": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/nopt/-/nopt-4.0.1.tgz", + "integrity": "sha1-0NRoWv1UFRk8jHUFYC0NF81kR00=", + "dev": true, + "optional": true, + "requires": { + "abbrev": "1.1.0", + "osenv": "0.1.4" + } + }, + "npmlog": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-4.1.0.tgz", + "integrity": "sha512-ocolIkZYZt8UveuiDS0yAkkIjid1o7lPG8cYm05yNYzBn8ykQtaiPMEGp8fY9tKdDgm8okpdKzkvu1y9hUYugA==", + "dev": true, + "optional": true, + "requires": { + "are-we-there-yet": "1.1.4", + "console-control-strings": "1.1.0", + "gauge": "2.7.4", + "set-blocking": "2.0.0" + } + }, + "number-is-nan": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz", + "integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=", + "dev": true + }, + "oauth-sign": { + "version": "0.8.2", + "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.8.2.tgz", + "integrity": "sha1-Rqarfwrq2N6unsBWV4C31O/rnUM=", + "dev": true, + "optional": true + }, + "object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=", + "dev": true, + "optional": true + }, + "once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", + "dev": true, + "requires": { + "wrappy": "1.0.2" + } + }, + "os-homedir": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/os-homedir/-/os-homedir-1.0.2.tgz", + "integrity": "sha1-/7xJiDNuDoM94MFox+8VISGqf7M=", + "dev": true, + "optional": true + }, + "os-tmpdir": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz", + "integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=", + "dev": true, + "optional": true + }, + "osenv": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/osenv/-/osenv-0.1.4.tgz", + "integrity": "sha1-Qv5tWVPfBsgGS+bxdsPQWqqjRkQ=", + "dev": true, + "optional": true, + "requires": { + "os-homedir": "1.0.2", + "os-tmpdir": "1.0.2" + } + }, + "path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", + "dev": true + }, + "performance-now": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-0.2.0.tgz", + "integrity": "sha1-M+8wxcd9TqIcWlOGnZG1bY8lVeU=", + "dev": true, + "optional": true + }, + "process-nextick-args": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-1.0.7.tgz", + "integrity": "sha1-FQ4gt1ZZCtP5EJPyWk8q2L/zC6M=", + "dev": true + }, + "punycode": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz", + "integrity": "sha1-wNWmOycYgArY4esPpSachN1BhF4=", + "dev": true, + "optional": true + }, + "qs": { + "version": "6.4.0", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.4.0.tgz", + "integrity": "sha1-E+JtKK1rD/qpExLNO/cI7TUecjM=", + "dev": true, + "optional": true + }, + "rc": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/rc/-/rc-1.2.1.tgz", + "integrity": "sha1-LgPo5C7kULjLPc5lvhv4l04d/ZU=", + "dev": true, + "optional": true, + "requires": { + "deep-extend": "0.4.2", + "ini": "1.3.4", + "minimist": "1.2.0", + "strip-json-comments": "2.0.1" + }, + "dependencies": { + "minimist": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", + "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", + "dev": true, + "optional": true + } + } + }, + "readable-stream": { + "version": "2.2.9", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.2.9.tgz", + "integrity": "sha1-z3jsb0ptHrQ9JkiMrJfwQudLf8g=", + "dev": true, + "requires": { + "buffer-shims": "1.0.0", + "core-util-is": "1.0.2", + "inherits": "2.0.3", + "isarray": "1.0.0", + "process-nextick-args": "1.0.7", + "string_decoder": "1.0.1", + "util-deprecate": "1.0.2" + } + }, + "request": { + "version": "2.81.0", + "resolved": "https://registry.npmjs.org/request/-/request-2.81.0.tgz", + "integrity": "sha1-xpKJRqDgbF+Nb4qTM0af/aRimKA=", + "dev": true, + "optional": true, + "requires": { + "aws-sign2": "0.6.0", + "aws4": "1.6.0", + "caseless": "0.12.0", + "combined-stream": "1.0.5", + "extend": "3.0.1", + "forever-agent": "0.6.1", + "form-data": "2.1.4", + "har-validator": "4.2.1", + "hawk": "3.1.3", + "http-signature": "1.1.1", + "is-typedarray": "1.0.0", + "isstream": "0.1.2", + "json-stringify-safe": "5.0.1", + "mime-types": "2.1.15", + "oauth-sign": "0.8.2", + "performance-now": "0.2.0", + "qs": "6.4.0", + "safe-buffer": "5.0.1", + "stringstream": "0.0.5", + "tough-cookie": "2.3.2", + "tunnel-agent": "0.6.0", + "uuid": "3.0.1" + } + }, + "rimraf": { + "version": "2.6.1", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.1.tgz", + "integrity": "sha1-wjOOxkPfeht/5cVPqG9XQopV8z0=", + "dev": true, + "requires": { + "glob": "7.1.2" + } + }, + "safe-buffer": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.0.1.tgz", + "integrity": "sha1-0mPKVGls2KMGtcplUekt5XkY++c=", + "dev": true + }, + "semver": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.3.0.tgz", + "integrity": "sha1-myzl094C0XxgEq0yaqa00M9U+U8=", + "dev": true, + "optional": true + }, + "set-blocking": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", + "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=", + "dev": true, + "optional": true + }, + "signal-exit": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.2.tgz", + "integrity": "sha1-tf3AjxKH6hF4Yo5BXiUTK3NkbG0=", + "dev": true, + "optional": true + }, + "sntp": { + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/sntp/-/sntp-1.0.9.tgz", + "integrity": "sha1-ZUEYTMkK7qbG57NeJlkIJEPGYZg=", + "dev": true, + "requires": { + "hoek": "2.16.3" + } + }, + "sshpk": { + "version": "1.13.0", + "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.13.0.tgz", + "integrity": "sha1-/yo+T9BEl1Vf7Zezmg/YL6+zozw=", + "dev": true, + "optional": true, + "requires": { + "asn1": "0.2.3", + "assert-plus": "1.0.0", + "bcrypt-pbkdf": "1.0.1", + "dashdash": "1.14.1", + "ecc-jsbn": "0.1.1", + "getpass": "0.1.7", + "jodid25519": "1.0.2", + "jsbn": "0.1.1", + "tweetnacl": "0.14.5" + }, + "dependencies": { + "assert-plus": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", + "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=", + "dev": true, + "optional": true + } + } + }, + "string-width": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", + "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", + "dev": true, + "requires": { + "code-point-at": "1.1.0", + "is-fullwidth-code-point": "1.0.0", + "strip-ansi": "3.0.1" + } + }, + "string_decoder": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.0.1.tgz", + "integrity": "sha1-YuIA8DmVWmgQ2N8KM//A8BNmLZg=", + "dev": true, + "requires": { + "safe-buffer": "5.0.1" + } + }, + "stringstream": { + "version": "0.0.5", + "resolved": "https://registry.npmjs.org/stringstream/-/stringstream-0.0.5.tgz", + "integrity": "sha1-TkhM1N5aC7vuGORjB3EKioFiGHg=", + "dev": true, + "optional": true + }, + "strip-ansi": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", + "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", + "dev": true, + "requires": { + "ansi-regex": "2.1.1" + } + }, + "strip-json-comments": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", + "integrity": "sha1-PFMZQukIwml8DsNEhYwobHygpgo=", + "dev": true, + "optional": true + }, + "tar": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/tar/-/tar-2.2.1.tgz", + "integrity": "sha1-jk0qJWwOIYXGsYrWlK7JaLg8sdE=", + "dev": true, + "requires": { + "block-stream": "0.0.9", + "fstream": "1.0.11", + "inherits": "2.0.3" + } + }, + "tar-pack": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/tar-pack/-/tar-pack-3.4.0.tgz", + "integrity": "sha1-I74tf2cagzk3bL2wuP4/3r8xeYQ=", + "dev": true, + "optional": true, + "requires": { + "debug": "2.6.8", + "fstream": "1.0.11", + "fstream-ignore": "1.0.5", + "once": "1.4.0", + "readable-stream": "2.2.9", + "rimraf": "2.6.1", + "tar": "2.2.1", + "uid-number": "0.0.6" + } + }, + "tough-cookie": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.3.2.tgz", + "integrity": "sha1-8IH3bkyFcg5sN6X6ztc3FQ2EByo=", + "dev": true, + "optional": true, + "requires": { + "punycode": "1.4.1" + } + }, + "tunnel-agent": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", + "integrity": "sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0=", + "dev": true, + "optional": true, + "requires": { + "safe-buffer": "5.0.1" + } + }, + "tweetnacl": { + "version": "0.14.5", + "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz", + "integrity": "sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q=", + "dev": true, + "optional": true + }, + "uid-number": { + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/uid-number/-/uid-number-0.0.6.tgz", + "integrity": "sha1-DqEOgDXo61uOREnwbaHHMGY7qoE=", + "dev": true, + "optional": true + }, + "util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=", + "dev": true + }, + "uuid": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.0.1.tgz", + "integrity": "sha1-ZUS7ot/ajBzxfmKaOjBeK7H+5sE=", + "dev": true, + "optional": true + }, + "verror": { + "version": "1.3.6", + "resolved": "https://registry.npmjs.org/verror/-/verror-1.3.6.tgz", + "integrity": "sha1-z/XfEpRtKX0rqu+qJoniW+AcAFw=", + "dev": true, + "optional": true, + "requires": { + "extsprintf": "1.0.2" + } + }, + "wide-align": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.2.tgz", + "integrity": "sha512-ijDLlyQ7s6x1JgCLur53osjm/UXUYD9+0PbYKrBsYisYXzCxN+HC3mYDNy/dWdmf3AwqwU3CXwDCvsNgGK1S0w==", + "dev": true, + "optional": true, + "requires": { + "string-width": "1.0.2" + } + }, + "wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", + "dev": true + } + } + }, + "function-bind": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", + "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==" + }, + "functional-red-black-tree": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz", + "integrity": "sha1-GwqzvVU7Kg1jmdKcDj6gslIHgyc=" + }, + "gamma": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/gamma/-/gamma-0.1.0.tgz", + "integrity": "sha1-MxVkNAO/J5BsqAqzfDbs6UQO8zA=" + }, + "geojson-area": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/geojson-area/-/geojson-area-0.1.0.tgz", + "integrity": "sha1-1I2AcILPrfSnjfE0m+UPOL8YlK4=", + "requires": { + "wgs84": "0.0.0" + } + }, + "geojson-rewind": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/geojson-rewind/-/geojson-rewind-0.1.0.tgz", + "integrity": "sha1-VwIqBUsZZmDXVTVP5dJmhNkM0Bk=", + "requires": { + "concat-stream": "1.2.1", + "geojson-area": "0.1.0", + "minimist": "0.0.5" + }, + "dependencies": { + "concat-stream": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.2.1.tgz", + "integrity": "sha1-81EAtsRjeL+6i2uA+fDQzN8T3GA=", + "requires": { + "bops": "0.0.6" + } + }, + "minimist": { + "version": "0.0.5", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.5.tgz", + "integrity": "sha1-16oye87PUY+RBqxrjwA/o7zqhWY=" + } + } + }, + "geojson-vt": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/geojson-vt/-/geojson-vt-2.4.0.tgz", + "integrity": "sha1-PBz0RJPzXrTSxwyV2mVQ3mYHLAU=" + }, + "get-caller-file": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-1.0.2.tgz", + "integrity": "sha1-9wLmMSfn4jHBYKgMFVSstw1QR+U=", + "dev": true + }, + "get-canvas-context": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/get-canvas-context/-/get-canvas-context-1.0.2.tgz", + "integrity": "sha1-1ue1C8TkyGNXzTnyJkeoS3NgHpM=" + }, + "get-stream": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-3.0.0.tgz", + "integrity": "sha1-jpQ9E1jcN1VQVOy+LtsFqhdO3hQ=", + "dev": true + }, + "getpass": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz", + "integrity": "sha1-Xv+OPmhNVprkyysSgmBOi6YhSfo=", + "requires": { + "assert-plus": "1.0.0" + } + }, + "gl-axes3d": { + "version": "1.2.6", + "resolved": "https://registry.npmjs.org/gl-axes3d/-/gl-axes3d-1.2.6.tgz", + "integrity": "sha512-WBqCTrVjspOa7MmBeYiKtQSGufqgY3IXeKsKIFcwitteJNmerXxJSXOyQdZdXZwJsfz1I0b2/CKQsW68TRHFiQ==", + "requires": { + "bit-twiddle": "1.0.2", + "dup": "1.0.0", + "extract-frustum-planes": "1.0.0", + "gl-buffer": "2.1.2", + "gl-mat4": "1.1.4", + "gl-shader": "4.2.0", + "gl-state": "1.0.0", + "gl-vao": "1.3.0", + "gl-vec4": "1.0.1", + "glslify": "2.3.1", + "robust-orientation": "1.1.3", + "split-polygon": "1.0.0", + "vectorize-text": "3.0.2" + }, + "dependencies": { + "bl": { + "version": "0.9.5", + "resolved": "https://registry.npmjs.org/bl/-/bl-0.9.5.tgz", + "integrity": "sha1-wGt5evCF6gC8Unr8jvzxHeIjIFQ=", + "requires": { + "readable-stream": "1.0.34" + } + }, + "glslify": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/glslify/-/glslify-2.3.1.tgz", + "integrity": "sha1-R6jOW/CGCVVqp+x2xqfTQwd23UY=", + "requires": { + "bl": "0.9.5", + "glsl-resolve": "0.0.1", + "glslify-bundle": "2.0.4", + "glslify-deps": "1.3.0", + "minimist": "1.2.0", + "resolve": "1.4.0", + "static-module": "1.5.0", + "through2": "0.6.5", + "xtend": "4.0.1" + } + }, + "glslify-bundle": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/glslify-bundle/-/glslify-bundle-2.0.4.tgz", + "integrity": "sha1-eV3xGYGAeIYaoZiaDHXVnCDs/dY=", + "requires": { + "glsl-inject-defines": "1.0.3", + "glsl-token-defines": "1.0.0", + "glsl-token-depth": "1.1.2", + "glsl-token-descope": "1.0.2", + "glsl-token-scope": "1.1.2", + "glsl-token-string": "1.0.1", + "glsl-tokenizer": "2.1.2" + } + } + } + }, + "gl-buffer": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/gl-buffer/-/gl-buffer-2.1.2.tgz", + "integrity": "sha1-LbjZwaVSf7oM25EonCBuiCuInNs=", + "requires": { + "ndarray": "1.0.18", + "ndarray-ops": "1.2.2", + "typedarray-pool": "1.1.0" + } + }, + "gl-constants": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/gl-constants/-/gl-constants-1.0.0.tgz", + "integrity": "sha1-WXpQTjZHUP9QJTqjX43qevSl0jM=" + }, + "gl-contour2d": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/gl-contour2d/-/gl-contour2d-1.1.3.tgz", + "integrity": "sha1-hidVZs6sG263bACtcpcieDXM02Q=", + "requires": { + "binary-search-bounds": "2.0.4", + "cdt2d": "1.0.0", + "clean-pslg": "1.1.2", + "gl-buffer": "2.1.2", + "gl-shader": "4.2.0", + "glslify": "4.0.0", + "iota-array": "1.0.0", + "ndarray": "1.0.18", + "surface-nets": "1.0.2" + }, + "dependencies": { + "binary-search-bounds": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/binary-search-bounds/-/binary-search-bounds-2.0.4.tgz", + "integrity": "sha512-2hg5kgdKql5ClF2ErBcSx0U5bnl5hgS4v7wMnLFodyR47yMtj2w+UAZB+0CiqyHct2q543i7Bi4/aMIegorCCg==" + } + } + }, + "gl-error3d": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/gl-error3d/-/gl-error3d-1.0.7.tgz", + "integrity": "sha512-otIih1SAh7Fo8DaaGQXOrg307cVpOjtTOwgiJzmmHAglD2EaKVSzNHONI5RVVVP+bBaObZz+wW18Mpeasij9pA==", + "requires": { + "gl-buffer": "2.1.2", + "gl-shader": "4.2.1", + "gl-vao": "1.3.0", + "glslify": "6.1.0" + }, + "dependencies": { + "escodegen": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/escodegen/-/escodegen-1.9.0.tgz", + "integrity": "sha512-v0MYvNQ32bzwoG2OSFzWAkuahDQHK92JBN0pTAALJ4RIxEZe766QJPDR8Hqy7XNUy5K3fnVL76OqYAdc4TZEIw==", + "requires": { + "esprima": "3.1.3", + "estraverse": "4.2.0", + "esutils": "2.0.2", + "optionator": "0.8.2", + "source-map": "0.5.7" + } + }, + "esprima": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-3.1.3.tgz", + "integrity": "sha1-/cpRzuYTOJXjyI1TXOSdv/YqRjM=" + }, + "estraverse": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.2.0.tgz", + "integrity": "sha1-De4/7TH81GlhjOc0IJn8GvoL2xM=" + }, + "esutils": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.2.tgz", + "integrity": "sha1-Cr9PHKpbyx96nYrMbepPqqBLrJs=" + }, + "gl-shader": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/gl-shader/-/gl-shader-4.2.1.tgz", + "integrity": "sha1-vJuAjpKTxRtmjojeYVsMETcI3C8=", + "requires": { + "gl-format-compiler-error": "1.0.3", + "weakmap-shim": "1.1.1" + } + }, + "glslify": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/glslify/-/glslify-6.1.0.tgz", + "integrity": "sha1-zf/P0qZXFyISjT0TNWwTbebOl0I=", + "requires": { + "bl": "1.2.1", + "concat-stream": "1.6.0", + "duplexify": "3.5.3", + "falafel": "2.1.0", + "from2": "2.3.0", + "glsl-resolve": "0.0.1", + "glsl-token-whitespace-trim": "1.0.0", + "glslify-bundle": "5.0.0", + "glslify-deps": "1.3.0", + "minimist": "1.2.0", + "resolve": "1.4.0", + "stack-trace": "0.0.9", + "static-eval": "1.1.1", + "tape": "4.8.0", + "through2": "2.0.3", + "xtend": "4.0.1" + } + }, + "glslify-bundle": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/glslify-bundle/-/glslify-bundle-5.0.0.tgz", + "integrity": "sha1-AlKtoe+d8wtmAAbguyH9EwtIbkI=", + "requires": { + "glsl-inject-defines": "1.0.3", + "glsl-token-defines": "1.0.0", + "glsl-token-depth": "1.1.2", + "glsl-token-descope": "1.0.2", + "glsl-token-scope": "1.1.2", + "glsl-token-string": "1.0.1", + "glsl-token-whitespace-trim": "1.0.0", + "glsl-tokenizer": "2.1.2", + "murmurhash-js": "1.0.0", + "shallow-copy": "0.0.1" + } + }, + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=" + }, + "readable-stream": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.3.tgz", + "integrity": "sha512-m+qzzcn7KUxEmd1gMbchF+Y2eIUbieUaxkWtptyHywrX0rE8QEYqPC07Vuy4Wm32/xE16NcdBctb8S0Xe/5IeQ==", + "requires": { + "core-util-is": "1.0.2", + "inherits": "2.0.3", + "isarray": "1.0.0", + "process-nextick-args": "1.0.7", + "safe-buffer": "5.1.1", + "string_decoder": "1.0.3", + "util-deprecate": "1.0.2" + } + }, + "source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", + "optional": true + }, + "static-eval": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/static-eval/-/static-eval-1.1.1.tgz", + "integrity": "sha1-yoEwIQNUzxPZpyK8fpI3eEV7sZI=", + "requires": { + "escodegen": "1.9.0" + } + }, + "string_decoder": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.0.3.tgz", + "integrity": "sha512-4AH6Z5fzNNBcH+6XDMfA/BTt87skxqJlO0lAh3Dker5zThcAxG6mKz+iGu308UKoPPQ8Dcqx/4JhujzltRa+hQ==", + "requires": { + "safe-buffer": "5.1.1" + } + }, + "through2": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.3.tgz", + "integrity": "sha1-AARWmzfHx0ujnEPzzteNGtlBQL4=", + "requires": { + "readable-stream": "2.3.3", + "xtend": "4.0.1" + } + } + } + }, + "gl-fbo": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/gl-fbo/-/gl-fbo-2.0.5.tgz", + "integrity": "sha1-D6daSXz3h2lVMGkcjwSrtvtV+iI=", + "requires": { + "gl-texture2d": "2.1.0" + } + }, + "gl-format-compiler-error": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/gl-format-compiler-error/-/gl-format-compiler-error-1.0.3.tgz", + "integrity": "sha1-DHmxdRiZzpcy6GJA8JCqQemEcag=", + "requires": { + "add-line-numbers": "1.0.1", + "gl-constants": "1.0.0", + "glsl-shader-name": "1.0.0", + "sprintf-js": "1.1.1" + } + }, + "gl-heatmap2d": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/gl-heatmap2d/-/gl-heatmap2d-1.0.3.tgz", + "integrity": "sha1-acthUS4xGF6ovSbwJfXBrx8rChg=", + "requires": { + "binary-search-bounds": "2.0.4", + "gl-buffer": "2.1.2", + "gl-shader": "4.2.0", + "glslify": "4.0.0", + "iota-array": "1.0.0", + "typedarray-pool": "1.1.0" + }, + "dependencies": { + "binary-search-bounds": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/binary-search-bounds/-/binary-search-bounds-2.0.4.tgz", + "integrity": "sha512-2hg5kgdKql5ClF2ErBcSx0U5bnl5hgS4v7wMnLFodyR47yMtj2w+UAZB+0CiqyHct2q543i7Bi4/aMIegorCCg==" + } + } + }, + "gl-line3d": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/gl-line3d/-/gl-line3d-1.1.1.tgz", + "integrity": "sha512-WyXWb6LWHJt6IcEjZyiJN17d8TXfCdR7O8XAF9BOyzZ3bosX/yNbVr4JbA4OJfKRoU4Eo2xPQPMsfFVQG3Y3JA==", + "requires": { + "binary-search-bounds": "1.0.0", + "gl-buffer": "2.1.2", + "gl-shader": "4.2.1", + "gl-texture2d": "2.1.0", + "gl-vao": "1.3.0", + "glsl-read-float": "1.1.0", + "glslify": "2.3.1", + "ndarray": "1.0.18" + }, + "dependencies": { + "bl": { + "version": "0.9.5", + "resolved": "https://registry.npmjs.org/bl/-/bl-0.9.5.tgz", + "integrity": "sha1-wGt5evCF6gC8Unr8jvzxHeIjIFQ=", + "requires": { + "readable-stream": "1.0.34" + } + }, + "gl-shader": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/gl-shader/-/gl-shader-4.2.1.tgz", + "integrity": "sha1-vJuAjpKTxRtmjojeYVsMETcI3C8=", + "requires": { + "gl-format-compiler-error": "1.0.3", + "weakmap-shim": "1.1.1" + } + }, + "glslify": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/glslify/-/glslify-2.3.1.tgz", + "integrity": "sha1-R6jOW/CGCVVqp+x2xqfTQwd23UY=", + "requires": { + "bl": "0.9.5", + "glsl-resolve": "0.0.1", + "glslify-bundle": "2.0.4", + "glslify-deps": "1.3.0", + "minimist": "1.2.0", + "resolve": "1.4.0", + "static-module": "1.5.0", + "through2": "0.6.5", + "xtend": "4.0.1" + } + }, + "glslify-bundle": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/glslify-bundle/-/glslify-bundle-2.0.4.tgz", + "integrity": "sha1-eV3xGYGAeIYaoZiaDHXVnCDs/dY=", + "requires": { + "glsl-inject-defines": "1.0.3", + "glsl-token-defines": "1.0.0", + "glsl-token-depth": "1.1.2", + "glsl-token-descope": "1.0.2", + "glsl-token-scope": "1.1.2", + "glsl-token-string": "1.0.1", + "glsl-tokenizer": "2.1.2" + } + } + } + }, + "gl-mat2": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/gl-mat2/-/gl-mat2-1.0.1.tgz", + "integrity": "sha1-FCUFcwpcL+Hp8l2ezj0NbMJxCjA=" + }, + "gl-mat3": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/gl-mat3/-/gl-mat3-1.0.0.tgz", + "integrity": "sha1-iWMyGcpCk3mha5GF2V1BcTRTuRI=" + }, + "gl-mat4": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/gl-mat4/-/gl-mat4-1.1.4.tgz", + "integrity": "sha1-HolbVYkuVqiWhnq9g30483oXgIY=" + }, + "gl-matrix": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/gl-matrix/-/gl-matrix-2.4.0.tgz", + "integrity": "sha1-IImxMwGinuyCLZ2Z3/wfeO6aPFA=" + }, + "gl-matrix-invert": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/gl-matrix-invert/-/gl-matrix-invert-1.0.0.tgz", + "integrity": "sha1-o2173jZUxFkKEn7nxo9uE/6oxj0=", + "requires": { + "gl-mat2": "1.0.1", + "gl-mat3": "1.0.0", + "gl-mat4": "1.1.4" + } + }, + "gl-mesh3d": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/gl-mesh3d/-/gl-mesh3d-1.3.1.tgz", + "integrity": "sha512-juFplPeRIWj1t5PmW51O93f3hC4bTBJtPdsUp7H2mDh1s/t29GjBV31wZysWzy/7stdsKNsyfNFhol+8vNP4tg==", + "requires": { + "barycentric": "1.0.1", + "colormap": "2.3.0", + "gl-buffer": "2.1.2", + "gl-mat4": "1.1.4", + "gl-shader": "4.2.1", + "gl-texture2d": "2.1.0", + "gl-vao": "1.3.0", + "glsl-specular-cook-torrance": "2.0.1", + "glslify": "2.3.1", + "ndarray": "1.0.18", + "normals": "1.1.0", + "polytope-closest-point": "1.0.0", + "simplicial-complex-contour": "1.0.2", + "typedarray-pool": "1.1.0" + }, + "dependencies": { + "bl": { + "version": "0.9.5", + "resolved": "https://registry.npmjs.org/bl/-/bl-0.9.5.tgz", + "integrity": "sha1-wGt5evCF6gC8Unr8jvzxHeIjIFQ=", + "requires": { + "readable-stream": "1.0.34" + } + }, + "gl-shader": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/gl-shader/-/gl-shader-4.2.1.tgz", + "integrity": "sha1-vJuAjpKTxRtmjojeYVsMETcI3C8=", + "requires": { + "gl-format-compiler-error": "1.0.3", + "weakmap-shim": "1.1.1" + } + }, + "glslify": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/glslify/-/glslify-2.3.1.tgz", + "integrity": "sha1-R6jOW/CGCVVqp+x2xqfTQwd23UY=", + "requires": { + "bl": "0.9.5", + "glsl-resolve": "0.0.1", + "glslify-bundle": "2.0.4", + "glslify-deps": "1.3.0", + "minimist": "1.2.0", + "resolve": "1.4.0", + "static-module": "1.5.0", + "through2": "0.6.5", + "xtend": "4.0.1" + } + }, + "glslify-bundle": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/glslify-bundle/-/glslify-bundle-2.0.4.tgz", + "integrity": "sha1-eV3xGYGAeIYaoZiaDHXVnCDs/dY=", + "requires": { + "glsl-inject-defines": "1.0.3", + "glsl-token-defines": "1.0.0", + "glsl-token-depth": "1.1.2", + "glsl-token-descope": "1.0.2", + "glsl-token-scope": "1.1.2", + "glsl-token-string": "1.0.1", + "glsl-tokenizer": "2.1.2" + } + } + } + }, + "gl-plot2d": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/gl-plot2d/-/gl-plot2d-1.3.0.tgz", + "integrity": "sha512-rnjwbuxbXKUvUNQXCuicED6soUuaiXdd9cnylT7MpJZ1+2cGkjMpQ6KoW0J96NoEen0PjuiijyKRZP+ogSBhTg==", + "requires": { + "binary-search-bounds": "2.0.4", + "gl-buffer": "2.1.2", + "gl-select-static": "2.0.2", + "gl-shader": "4.2.1", + "glsl-inverse": "1.0.0", + "glslify": "2.3.1", + "text-cache": "4.1.0" + }, + "dependencies": { + "binary-search-bounds": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/binary-search-bounds/-/binary-search-bounds-2.0.4.tgz", + "integrity": "sha512-2hg5kgdKql5ClF2ErBcSx0U5bnl5hgS4v7wMnLFodyR47yMtj2w+UAZB+0CiqyHct2q543i7Bi4/aMIegorCCg==" + }, + "bl": { + "version": "0.9.5", + "resolved": "https://registry.npmjs.org/bl/-/bl-0.9.5.tgz", + "integrity": "sha1-wGt5evCF6gC8Unr8jvzxHeIjIFQ=", + "requires": { + "readable-stream": "1.0.34" + } + }, + "gl-shader": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/gl-shader/-/gl-shader-4.2.1.tgz", + "integrity": "sha1-vJuAjpKTxRtmjojeYVsMETcI3C8=", + "requires": { + "gl-format-compiler-error": "1.0.3", + "weakmap-shim": "1.1.1" + } + }, + "glslify": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/glslify/-/glslify-2.3.1.tgz", + "integrity": "sha1-R6jOW/CGCVVqp+x2xqfTQwd23UY=", + "requires": { + "bl": "0.9.5", + "glsl-resolve": "0.0.1", + "glslify-bundle": "2.0.4", + "glslify-deps": "1.3.0", + "minimist": "1.2.0", + "resolve": "1.4.0", + "static-module": "1.5.0", + "through2": "0.6.5", + "xtend": "4.0.1" + } + }, + "glslify-bundle": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/glslify-bundle/-/glslify-bundle-2.0.4.tgz", + "integrity": "sha1-eV3xGYGAeIYaoZiaDHXVnCDs/dY=", + "requires": { + "glsl-inject-defines": "1.0.3", + "glsl-token-defines": "1.0.0", + "glsl-token-depth": "1.1.2", + "glsl-token-descope": "1.0.2", + "glsl-token-scope": "1.1.2", + "glsl-token-string": "1.0.1", + "glsl-tokenizer": "2.1.2" + } + } + } + }, + "gl-plot3d": { + "version": "1.5.4", + "resolved": "https://registry.npmjs.org/gl-plot3d/-/gl-plot3d-1.5.4.tgz", + "integrity": "sha1-vpwYaMgppH0KKrA8cNUor4aPnoY=", + "requires": { + "3d-view-controls": "2.2.2", + "a-big-triangle": "1.0.3", + "gl-axes3d": "1.2.6", + "gl-fbo": "2.0.5", + "gl-mat4": "1.1.4", + "gl-select-static": "2.0.2", + "gl-shader": "4.2.0", + "gl-spikes3d": "1.0.5", + "glslify": "2.3.1", + "is-mobile": "0.2.2", + "mouse-change": "1.4.0", + "ndarray": "1.0.18" + }, + "dependencies": { + "bl": { + "version": "0.9.5", + "resolved": "https://registry.npmjs.org/bl/-/bl-0.9.5.tgz", + "integrity": "sha1-wGt5evCF6gC8Unr8jvzxHeIjIFQ=", + "requires": { + "readable-stream": "1.0.34" + } + }, + "glslify": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/glslify/-/glslify-2.3.1.tgz", + "integrity": "sha1-R6jOW/CGCVVqp+x2xqfTQwd23UY=", + "requires": { + "bl": "0.9.5", + "glsl-resolve": "0.0.1", + "glslify-bundle": "2.0.4", + "glslify-deps": "1.3.0", + "minimist": "1.2.0", + "resolve": "1.4.0", + "static-module": "1.5.0", + "through2": "0.6.5", + "xtend": "4.0.1" + } + }, + "glslify-bundle": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/glslify-bundle/-/glslify-bundle-2.0.4.tgz", + "integrity": "sha1-eV3xGYGAeIYaoZiaDHXVnCDs/dY=", + "requires": { + "glsl-inject-defines": "1.0.3", + "glsl-token-defines": "1.0.0", + "glsl-token-depth": "1.1.2", + "glsl-token-descope": "1.0.2", + "glsl-token-scope": "1.1.2", + "glsl-token-string": "1.0.1", + "glsl-tokenizer": "2.1.2" + } + } + } + }, + "gl-pointcloud2d": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/gl-pointcloud2d/-/gl-pointcloud2d-1.0.0.tgz", + "integrity": "sha1-QbrpluBJ4PHf2Pn44V/5A/xPv90=", + "requires": { + "gl-buffer": "2.1.2", + "gl-shader": "4.2.1", + "glslify": "2.3.1", + "typedarray-pool": "1.1.0" + }, + "dependencies": { + "bl": { + "version": "0.9.5", + "resolved": "https://registry.npmjs.org/bl/-/bl-0.9.5.tgz", + "integrity": "sha1-wGt5evCF6gC8Unr8jvzxHeIjIFQ=", + "requires": { + "readable-stream": "1.0.34" + } + }, + "gl-shader": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/gl-shader/-/gl-shader-4.2.1.tgz", + "integrity": "sha1-vJuAjpKTxRtmjojeYVsMETcI3C8=", + "requires": { + "gl-format-compiler-error": "1.0.3", + "weakmap-shim": "1.1.1" + } + }, + "glslify": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/glslify/-/glslify-2.3.1.tgz", + "integrity": "sha1-R6jOW/CGCVVqp+x2xqfTQwd23UY=", + "requires": { + "bl": "0.9.5", + "glsl-resolve": "0.0.1", + "glslify-bundle": "2.0.4", + "glslify-deps": "1.3.0", + "minimist": "1.2.0", + "resolve": "1.4.0", + "static-module": "1.5.0", + "through2": "0.6.5", + "xtend": "4.0.1" + } + }, + "glslify-bundle": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/glslify-bundle/-/glslify-bundle-2.0.4.tgz", + "integrity": "sha1-eV3xGYGAeIYaoZiaDHXVnCDs/dY=", + "requires": { + "glsl-inject-defines": "1.0.3", + "glsl-token-defines": "1.0.0", + "glsl-token-depth": "1.1.2", + "glsl-token-descope": "1.0.2", + "glsl-token-scope": "1.1.2", + "glsl-token-string": "1.0.1", + "glsl-tokenizer": "2.1.2" + } + } + } + }, + "gl-quat": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/gl-quat/-/gl-quat-1.0.0.tgz", + "integrity": "sha1-CUXskjOG9FMpvl3DV7HIwtR1hsU=", + "requires": { + "gl-mat3": "1.0.0", + "gl-vec3": "1.0.3", + "gl-vec4": "1.0.1" + } + }, + "gl-scatter3d": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/gl-scatter3d/-/gl-scatter3d-1.0.10.tgz", + "integrity": "sha1-ScV/MxCMO1azWBVBkoqP7rLTfp4=", + "requires": { + "gl-buffer": "2.1.2", + "gl-mat4": "1.1.4", + "gl-shader": "4.2.0", + "gl-vao": "1.3.0", + "glslify": "2.3.1", + "typedarray-pool": "1.1.0", + "vectorize-text": "3.0.2" + }, + "dependencies": { + "bl": { + "version": "0.9.5", + "resolved": "https://registry.npmjs.org/bl/-/bl-0.9.5.tgz", + "integrity": "sha1-wGt5evCF6gC8Unr8jvzxHeIjIFQ=", + "requires": { + "readable-stream": "1.0.34" + } + }, + "glslify": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/glslify/-/glslify-2.3.1.tgz", + "integrity": "sha1-R6jOW/CGCVVqp+x2xqfTQwd23UY=", + "requires": { + "bl": "0.9.5", + "glsl-resolve": "0.0.1", + "glslify-bundle": "2.0.4", + "glslify-deps": "1.3.0", + "minimist": "1.2.0", + "resolve": "1.4.0", + "static-module": "1.5.0", + "through2": "0.6.5", + "xtend": "4.0.1" + } + }, + "glslify-bundle": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/glslify-bundle/-/glslify-bundle-2.0.4.tgz", + "integrity": "sha1-eV3xGYGAeIYaoZiaDHXVnCDs/dY=", + "requires": { + "glsl-inject-defines": "1.0.3", + "glsl-token-defines": "1.0.0", + "glsl-token-depth": "1.1.2", + "glsl-token-descope": "1.0.2", + "glsl-token-scope": "1.1.2", + "glsl-token-string": "1.0.1", + "glsl-tokenizer": "2.1.2" + } + } + } + }, + "gl-select-box": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/gl-select-box/-/gl-select-box-1.0.1.tgz", + "integrity": "sha1-DMjJBczif+jZGLsO4Th/WDj5Wek=", + "requires": { + "gl-buffer": "2.1.2", + "gl-shader": "4.2.0", + "glslify": "2.3.1" + }, + "dependencies": { + "bl": { + "version": "0.9.5", + "resolved": "https://registry.npmjs.org/bl/-/bl-0.9.5.tgz", + "integrity": "sha1-wGt5evCF6gC8Unr8jvzxHeIjIFQ=", + "requires": { + "readable-stream": "1.0.34" + } + }, + "glslify": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/glslify/-/glslify-2.3.1.tgz", + "integrity": "sha1-R6jOW/CGCVVqp+x2xqfTQwd23UY=", + "requires": { + "bl": "0.9.5", + "glsl-resolve": "0.0.1", + "glslify-bundle": "2.0.4", + "glslify-deps": "1.3.0", + "minimist": "1.2.0", + "resolve": "1.4.0", + "static-module": "1.5.0", + "through2": "0.6.5", + "xtend": "4.0.1" + } + }, + "glslify-bundle": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/glslify-bundle/-/glslify-bundle-2.0.4.tgz", + "integrity": "sha1-eV3xGYGAeIYaoZiaDHXVnCDs/dY=", + "requires": { + "glsl-inject-defines": "1.0.3", + "glsl-token-defines": "1.0.0", + "glsl-token-depth": "1.1.2", + "glsl-token-descope": "1.0.2", + "glsl-token-scope": "1.1.2", + "glsl-token-string": "1.0.1", + "glsl-tokenizer": "2.1.2" + } + } + } + }, + "gl-select-static": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/gl-select-static/-/gl-select-static-2.0.2.tgz", + "integrity": "sha1-8+GQHfAxgdUy55WFMjBnnUr1fuk=", + "requires": { + "bit-twiddle": "1.0.2", + "cwise": "1.0.10", + "gl-fbo": "2.0.5", + "ndarray": "1.0.18", + "typedarray-pool": "1.1.0" + } + }, + "gl-shader": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/gl-shader/-/gl-shader-4.2.0.tgz", + "integrity": "sha1-KPd4E+/6DdXNqdqx8wHRsc2j6H4=", + "requires": { + "gl-format-compiler-error": "1.0.3", + "weakmap-shim": "1.1.1" + } + }, + "gl-spikes2d": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/gl-spikes2d/-/gl-spikes2d-1.0.1.tgz", + "integrity": "sha1-ys2y09vNICuFNFLoUAqLB3lJzAM=" + }, + "gl-spikes3d": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/gl-spikes3d/-/gl-spikes3d-1.0.5.tgz", + "integrity": "sha1-aX6fLqdZe+Qauke9oRm5X0jKFX0=", + "requires": { + "gl-buffer": "2.1.2", + "gl-shader": "4.2.0", + "gl-vao": "1.3.0", + "glslify": "2.3.1" + }, + "dependencies": { + "bl": { + "version": "0.9.5", + "resolved": "https://registry.npmjs.org/bl/-/bl-0.9.5.tgz", + "integrity": "sha1-wGt5evCF6gC8Unr8jvzxHeIjIFQ=", + "requires": { + "readable-stream": "1.0.34" + } + }, + "glslify": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/glslify/-/glslify-2.3.1.tgz", + "integrity": "sha1-R6jOW/CGCVVqp+x2xqfTQwd23UY=", + "requires": { + "bl": "0.9.5", + "glsl-resolve": "0.0.1", + "glslify-bundle": "2.0.4", + "glslify-deps": "1.3.0", + "minimist": "1.2.0", + "resolve": "1.4.0", + "static-module": "1.5.0", + "through2": "0.6.5", + "xtend": "4.0.1" + } + }, + "glslify-bundle": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/glslify-bundle/-/glslify-bundle-2.0.4.tgz", + "integrity": "sha1-eV3xGYGAeIYaoZiaDHXVnCDs/dY=", + "requires": { + "glsl-inject-defines": "1.0.3", + "glsl-token-defines": "1.0.0", + "glsl-token-depth": "1.1.2", + "glsl-token-descope": "1.0.2", + "glsl-token-scope": "1.1.2", + "glsl-token-string": "1.0.1", + "glsl-tokenizer": "2.1.2" + } + } + } + }, + "gl-state": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/gl-state/-/gl-state-1.0.0.tgz", + "integrity": "sha1-Ji+qdYNbC5xTLBLzitxCXR0wzRc=", + "requires": { + "uniq": "1.0.1" + } + }, + "gl-surface3d": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/gl-surface3d/-/gl-surface3d-1.3.3.tgz", + "integrity": "sha512-fUOiSwLAR5KfgTisDmTfi77y8GRcKjC60M6qnZfKzlbkr5MXp589ZN0tNNVRPHz7p2QeZo5pFsTkJIWuyt4NNA==", + "requires": { + "binary-search-bounds": "1.0.0", + "bit-twiddle": "1.0.2", + "colormap": "2.3.0", + "dup": "1.0.0", + "gl-buffer": "2.1.2", + "gl-mat4": "1.1.4", + "gl-shader": "4.2.0", + "gl-texture2d": "2.1.0", + "gl-vao": "1.3.0", + "glsl-specular-beckmann": "1.1.2", + "glslify": "2.3.1", + "ndarray": "1.0.18", + "ndarray-gradient": "1.0.0", + "ndarray-ops": "1.2.2", + "ndarray-pack": "1.2.1", + "ndarray-scratch": "1.2.0", + "surface-nets": "1.0.2", + "typedarray-pool": "1.1.0" + }, + "dependencies": { + "bl": { + "version": "0.9.5", + "resolved": "https://registry.npmjs.org/bl/-/bl-0.9.5.tgz", + "integrity": "sha1-wGt5evCF6gC8Unr8jvzxHeIjIFQ=", + "requires": { + "readable-stream": "1.0.34" + } + }, + "glslify": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/glslify/-/glslify-2.3.1.tgz", + "integrity": "sha1-R6jOW/CGCVVqp+x2xqfTQwd23UY=", + "requires": { + "bl": "0.9.5", + "glsl-resolve": "0.0.1", + "glslify-bundle": "2.0.4", + "glslify-deps": "1.3.0", + "minimist": "1.2.0", + "resolve": "1.4.0", + "static-module": "1.5.0", + "through2": "0.6.5", + "xtend": "4.0.1" + } + }, + "glslify-bundle": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/glslify-bundle/-/glslify-bundle-2.0.4.tgz", + "integrity": "sha1-eV3xGYGAeIYaoZiaDHXVnCDs/dY=", + "requires": { + "glsl-inject-defines": "1.0.3", + "glsl-token-defines": "1.0.0", + "glsl-token-depth": "1.1.2", + "glsl-token-descope": "1.0.2", + "glsl-token-scope": "1.1.2", + "glsl-token-string": "1.0.1", + "glsl-tokenizer": "2.1.2" + } + } + } + }, + "gl-texture2d": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/gl-texture2d/-/gl-texture2d-2.1.0.tgz", + "integrity": "sha1-/2gk5+fDGoum/c2+nlxpXX4hh8c=", + "requires": { + "ndarray": "1.0.18", + "ndarray-ops": "1.2.2", + "typedarray-pool": "1.1.0" + } + }, + "gl-vao": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/gl-vao/-/gl-vao-1.3.0.tgz", + "integrity": "sha1-6ekqqVWIyrnVwvBLaTRAw99pGSM=" + }, + "gl-vec3": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/gl-vec3/-/gl-vec3-1.0.3.tgz", + "integrity": "sha1-EQ/Yl9Byn2OYMHOBVn0JRJQb8is=" + }, + "gl-vec4": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/gl-vec4/-/gl-vec4-1.0.1.tgz", + "integrity": "sha1-l9loeCgbFLUyy84QF4Xf0cs0CWQ=" + }, + "glob": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.2.tgz", + "integrity": "sha512-MJTUg1kjuLeQCJ+ccE4Vpa6kKVXkPYJ2mOCQyUuKLcLQsdrMCpBPUi8qVE6+YuaJkozeA9NusTAw3hLr8Xe5EQ==", + "requires": { + "fs.realpath": "1.0.0", + "inflight": "1.0.6", + "inherits": "2.0.3", + "minimatch": "3.0.4", + "once": "1.4.0", + "path-is-absolute": "1.0.1" + } + }, + "glob-base": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/glob-base/-/glob-base-0.3.0.tgz", + "integrity": "sha1-27Fk9iIbHAscz4Kuoyi0l98Oo8Q=", + "dev": true, + "requires": { + "glob-parent": "2.0.0", + "is-glob": "2.0.1" + } + }, + "glob-parent": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-2.0.0.tgz", + "integrity": "sha1-gTg9ctsFT8zPUzbaqQLxgvbtuyg=", + "dev": true, + "requires": { + "is-glob": "2.0.1" + } + }, + "glsl-inject-defines": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/glsl-inject-defines/-/glsl-inject-defines-1.0.3.tgz", + "integrity": "sha1-3RqswsF/yyvT/DJBHGYz0Ne2D9Q=", + "requires": { + "glsl-token-inject-block": "1.1.0", + "glsl-token-string": "1.0.1", + "glsl-tokenizer": "2.1.2" + } + }, + "glsl-inverse": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/glsl-inverse/-/glsl-inverse-1.0.0.tgz", + "integrity": "sha1-EsCx0GX1WERNHm/q95td34qRiuY=" + }, + "glsl-read-float": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/glsl-read-float/-/glsl-read-float-1.1.0.tgz", + "integrity": "sha1-37CIsBYtz8xW/E7d0vhuGMrDLyY=" + }, + "glsl-resolve": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/glsl-resolve/-/glsl-resolve-0.0.1.tgz", + "integrity": "sha1-iUvvc5ENeSyBtRQxgANdCnivdtM=", + "requires": { + "resolve": "0.6.3", + "xtend": "2.2.0" + }, + "dependencies": { + "resolve": { + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-0.6.3.tgz", + "integrity": "sha1-3ZV5gufnNt699TtYpN2RdUV13UY=" + }, + "xtend": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-2.2.0.tgz", + "integrity": "sha1-7vax8ZjByN6vrYsXZaBNrUoBxak=" + } + } + }, + "glsl-shader-name": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/glsl-shader-name/-/glsl-shader-name-1.0.0.tgz", + "integrity": "sha1-osMLO6c0mb77DMcYTXx3M91LSH0=", + "requires": { + "atob-lite": "1.0.0", + "glsl-tokenizer": "2.1.2" + } + }, + "glsl-specular-beckmann": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/glsl-specular-beckmann/-/glsl-specular-beckmann-1.1.2.tgz", + "integrity": "sha1-/OkFaTPs3yRWJ4N2pU0IKJPndfE=" + }, + "glsl-specular-cook-torrance": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/glsl-specular-cook-torrance/-/glsl-specular-cook-torrance-2.0.1.tgz", + "integrity": "sha1-qJHMBsjHtPRyhwK0gk/ay7ln148=", + "requires": { + "glsl-specular-beckmann": "1.1.2" + } + }, + "glsl-token-assignments": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/glsl-token-assignments/-/glsl-token-assignments-2.0.2.tgz", + "integrity": "sha1-pdgqt4SZwuimuDy2lJXm5mXOAZ8=" + }, + "glsl-token-defines": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/glsl-token-defines/-/glsl-token-defines-1.0.0.tgz", + "integrity": "sha1-y4kqqVmTYjFyhHDU90AySJaX+p0=", + "requires": { + "glsl-tokenizer": "2.1.2" + } + }, + "glsl-token-depth": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/glsl-token-depth/-/glsl-token-depth-1.1.2.tgz", + "integrity": "sha1-I8XjDuK9JViEtKKLyFC495HpXYQ=" + }, + "glsl-token-descope": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/glsl-token-descope/-/glsl-token-descope-1.0.2.tgz", + "integrity": "sha1-D8kKsyYYa4L1l7LnfcniHvzTIHY=", + "requires": { + "glsl-token-assignments": "2.0.2", + "glsl-token-depth": "1.1.2", + "glsl-token-properties": "1.0.1", + "glsl-token-scope": "1.1.2" + } + }, + "glsl-token-inject-block": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/glsl-token-inject-block/-/glsl-token-inject-block-1.1.0.tgz", + "integrity": "sha1-4QFfWYDBCRgkraomJfHf3ovQADQ=" + }, + "glsl-token-properties": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/glsl-token-properties/-/glsl-token-properties-1.0.1.tgz", + "integrity": "sha1-SD3D2Dnw1LXGFx0VkfJJvlPCip4=" + }, + "glsl-token-scope": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/glsl-token-scope/-/glsl-token-scope-1.1.2.tgz", + "integrity": "sha1-oXKOeN8kRE+cuT/RjvD3VQOmQ7E=" + }, + "glsl-token-string": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/glsl-token-string/-/glsl-token-string-1.0.1.tgz", + "integrity": "sha1-WUQdL4V958NEnJRWZgIezjWOSOw=" + }, + "glsl-token-whitespace-trim": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/glsl-token-whitespace-trim/-/glsl-token-whitespace-trim-1.0.0.tgz", + "integrity": "sha1-RtHf6Yx1vX1QTAXX0RsbPpzJOxA=" + }, + "glsl-tokenizer": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/glsl-tokenizer/-/glsl-tokenizer-2.1.2.tgz", + "integrity": "sha1-cgMHUi4DxXrzXABVGVDEpw7y37k=", + "requires": { + "through2": "0.6.5" + } + }, + "glslify": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/glslify/-/glslify-4.0.0.tgz", + "integrity": "sha1-Tbz60TaVPzAVA/pKjgabIzahQjQ=", + "requires": { + "bl": "1.2.1", + "glsl-resolve": "0.0.1", + "glslify-bundle": "4.0.1", + "glslify-deps": "1.3.0", + "minimist": "1.2.0", + "resolve": "1.4.0", + "static-module": "1.5.0", + "through2": "0.6.5", + "xtend": "4.0.1" + } + }, + "glslify-bundle": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/glslify-bundle/-/glslify-bundle-4.0.1.tgz", + "integrity": "sha1-ryzyBs15hRWRALM7XxRjqBt0TaE=", + "requires": { + "glsl-inject-defines": "1.0.3", + "glsl-token-defines": "1.0.0", + "glsl-token-depth": "1.1.2", + "glsl-token-descope": "1.0.2", + "glsl-token-scope": "1.1.2", + "glsl-token-string": "1.0.1", + "glsl-token-whitespace-trim": "1.0.0", + "glsl-tokenizer": "2.1.2", + "murmurhash-js": "1.0.0", + "shallow-copy": "0.0.1" + } + }, + "glslify-deps": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/glslify-deps/-/glslify-deps-1.3.0.tgz", + "integrity": "sha1-CyI0yOqePT/X9rPLfwOuWea1Glk=", + "requires": { + "events": "1.1.1", + "findup": "0.1.5", + "glsl-resolve": "0.0.1", + "glsl-tokenizer": "2.1.2", + "graceful-fs": "4.1.11", + "inherits": "2.0.3", + "map-limit": "0.0.1", + "resolve": "1.4.0" + } + }, + "graceful-fs": { + "version": "4.1.11", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.11.tgz", + "integrity": "sha1-Dovf5NHduIVNZOBOp8AOKgJuVlg=" + }, + "grid-index": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/grid-index/-/grid-index-1.0.0.tgz", + "integrity": "sha1-rSxdVM5bNUN/r/HXCprrPR0mERA=" + }, + "har-schema": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/har-schema/-/har-schema-2.0.0.tgz", + "integrity": "sha1-qUwiJOvKwEeCoNkDVSHyRzW37JI=" + }, + "har-validator": { + "version": "5.0.3", + "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-5.0.3.tgz", + "integrity": "sha1-ukAsJmGU8VlW7xXg/PJCmT9qff0=", + "requires": { + "ajv": "5.1.6", + "har-schema": "2.0.0" + } + }, + "has": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/has/-/has-1.0.1.tgz", + "integrity": "sha1-hGFzP1OLCDfJNh45qauelwTcLyg=", + "requires": { + "function-bind": "1.1.1" + } + }, + "has-color": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/has-color/-/has-color-0.1.7.tgz", + "integrity": "sha1-ZxRKUmDDT8PMpnfQQdr1L+e3iy8=" + }, + "has-flag": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-2.0.0.tgz", + "integrity": "sha1-6CB68cx7MNRGzHC3NLXovhj4jVE=" + }, + "has-hover": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/has-hover/-/has-hover-1.0.1.tgz", + "integrity": "sha1-PZdDeusZnGK4rAisvcU9O8UsF/c=", + "requires": { + "is-browser": "2.0.1" + } + }, + "has-passive-events": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-passive-events/-/has-passive-events-1.0.0.tgz", + "integrity": "sha512-2vSj6IeIsgvsRMyeQ0JaCX5Q3lX4zMn5HpoVc7MEhQ6pv8Iq9rsXjsp+E5ZwaT7T0xhMT0KmU8gtt1EFVdbJiw==", + "requires": { + "is-browser": "2.0.1" + } + }, + "hash-base": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/hash-base/-/hash-base-2.0.2.tgz", + "integrity": "sha1-ZuodhW206KVHDK32/OI65SRO8uE=", + "dev": true, + "requires": { + "inherits": "2.0.3" + } + }, + "hash.js": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/hash.js/-/hash.js-1.1.3.tgz", + "integrity": "sha512-/UETyP0W22QILqS+6HowevwhEFJ3MBJnwTf75Qob9Wz9t0DPuisL8kW8YZMK62dHAKE1c1p+gY1TtOLY+USEHA==", + "dev": true, + "requires": { + "inherits": "2.0.3", + "minimalistic-assert": "1.0.0" + } + }, + "hawk": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/hawk/-/hawk-6.0.2.tgz", + "integrity": "sha512-miowhl2+U7Qle4vdLqDdPt9m09K6yZhkLDTWGoUiUzrQCn+mHHSmfJgAyGaLRZbPmTqfFFjRV1QWCW0VWUJBbQ==", + "requires": { + "boom": "4.3.1", + "cryptiles": "3.1.2", + "hoek": "4.2.0", + "sntp": "2.1.0" + } + }, + "hmac-drbg": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/hmac-drbg/-/hmac-drbg-1.0.1.tgz", + "integrity": "sha1-0nRXAQJabHdabFRXk+1QL8DGSaE=", + "dev": true, + "requires": { + "hash.js": "1.1.3", + "minimalistic-assert": "1.0.0", + "minimalistic-crypto-utils": "1.0.1" + } + }, + "hoek": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/hoek/-/hoek-4.2.0.tgz", + "integrity": "sha512-v0XCLxICi9nPfYrS9RL8HbYnXi9obYAeLbSP00BmnZwCK9+Ih9WOjoZ8YoHCoav2csqn4FOz4Orldsy2dmDwmQ==" + }, + "hosted-git-info": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.5.0.tgz", + "integrity": "sha512-pNgbURSuab90KbTqvRPsseaTxOJCZBD0a7t+haSN33piP9cCM4l0CqdzAif2hUqm716UovKB2ROmiabGAKVXyg==", + "dev": true + }, + "http-signature": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.2.0.tgz", + "integrity": "sha1-muzZJRFHcvPZW2WmCruPfBj7rOE=", + "requires": { + "assert-plus": "1.0.0", + "jsprim": "1.4.1", + "sshpk": "1.13.1" + } + }, + "https-browserify": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/https-browserify/-/https-browserify-1.0.0.tgz", + "integrity": "sha1-7AbBDgo0wPL68Zn3/X/Hj//QPHM=", + "dev": true + }, + "husl": { + "version": "5.0.3", + "resolved": "https://registry.npmjs.org/husl/-/husl-5.0.3.tgz", + "integrity": "sha1-7icqr/G+vkDfNYjtAHtw3n5nl4g=" + }, + "ieee754": { + "version": "1.1.8", + "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.1.8.tgz", + "integrity": "sha1-vjPUCsEO8ZJnAfbwii2G+/0a0+Q=" + }, + "ify-loader": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/ify-loader/-/ify-loader-1.1.0.tgz", + "integrity": "sha512-EiyC45FRIs+z4g98+jBzuYCfoM6TKG9p7Ek5YZUeM7rucNucaMZIseRj/5Q3I4ypkZXyC2wnU1RcYrVmshe2xw==", + "dev": true, + "requires": { + "bl": "1.2.1", + "findup": "0.1.5", + "from2-array": "0.0.4", + "map-limit": "0.0.1", + "multipipe": "0.3.1", + "read-package-json": "2.0.12", + "resolve": "1.4.0" + } + }, + "incremental-convex-hull": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/incremental-convex-hull/-/incremental-convex-hull-1.0.1.tgz", + "integrity": "sha1-UUKMFMudmmFEv+abKFH7N3M0vh4=", + "requires": { + "robust-orientation": "1.1.3", + "simplicial-complex": "1.0.0" + } + }, + "indexof": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/indexof/-/indexof-0.0.1.tgz", + "integrity": "sha1-gtwzbSMrkGIXnQWrMpOmYFn9Q10=", + "dev": true + }, + "inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", + "requires": { + "once": "1.4.0", + "wrappy": "1.0.2" + } + }, + "inherits": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", + "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=" + }, + "interpret": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/interpret/-/interpret-1.1.0.tgz", + "integrity": "sha1-ftGxQQxqDg94z5XTuEQMY/eLhhQ=", + "dev": true + }, + "interval-tree-1d": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/interval-tree-1d/-/interval-tree-1d-1.0.3.tgz", + "integrity": "sha1-j9veArayx9verWNry+2OCHENhcE=", + "requires": { + "binary-search-bounds": "1.0.0" + } + }, + "invert-kv": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/invert-kv/-/invert-kv-1.0.0.tgz", + "integrity": "sha1-EEqOSqym09jNFXqO+L+rLXo//bY=", + "dev": true + }, + "invert-permutation": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/invert-permutation/-/invert-permutation-1.0.0.tgz", + "integrity": "sha1-oKeAQurbNrwXVR54fv0UOa3VSTM=" + }, + "iota-array": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/iota-array/-/iota-array-1.0.0.tgz", + "integrity": "sha1-ge9X/l0FgUzVjCSDYyqZwwoOgIc=" + }, + "is-arrayish": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", + "integrity": "sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0=", + "dev": true + }, + "is-binary-path": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-1.0.1.tgz", + "integrity": "sha1-dfFmQrSA8YenEcgUFh/TpKdlWJg=", + "dev": true, + "requires": { + "binary-extensions": "1.11.0" + } + }, + "is-browser": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-browser/-/is-browser-2.0.1.tgz", + "integrity": "sha1-i/C695mpxi/Z3lvO5M8zl8PnUpo=" + }, + "is-buffer": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", + "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==" + }, + "is-builtin-module": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-builtin-module/-/is-builtin-module-1.0.0.tgz", + "integrity": "sha1-VAVy0096wxGfj3bDDLwbHgN6/74=", + "dev": true, + "requires": { + "builtin-modules": "1.1.1" + } + }, + "is-callable": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.1.3.tgz", + "integrity": "sha1-hut1OSgF3cM69xySoO7fdO52BLI=" + }, + "is-date-object": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.1.tgz", + "integrity": "sha1-mqIOtq7rv/d/vTPnTKAbM1gdOhY=" + }, + "is-dotfile": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/is-dotfile/-/is-dotfile-1.0.3.tgz", + "integrity": "sha1-pqLzL/0t+wT1yiXs0Pa4PPeYoeE=", + "dev": true + }, + "is-equal-shallow": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/is-equal-shallow/-/is-equal-shallow-0.1.3.tgz", + "integrity": "sha1-IjgJj8Ih3gvPpdnqxMRdY4qhxTQ=", + "dev": true, + "requires": { + "is-primitive": "2.0.0" + } + }, + "is-extendable": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz", + "integrity": "sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik=", + "dev": true + }, + "is-extglob": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-1.0.0.tgz", + "integrity": "sha1-rEaBd8SUNAWgkvyPKXYMb/xiBsA=", + "dev": true + }, + "is-fullwidth-code-point": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", + "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", + "dev": true, + "requires": { + "number-is-nan": "1.0.1" + } + }, + "is-function": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-function/-/is-function-1.0.1.tgz", + "integrity": "sha1-Es+5i2W1fdPRk6MSH19uL0N2ArU=" + }, + "is-glob": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-2.0.1.tgz", + "integrity": "sha1-0Jb5JqPe1WAPP9/ZEZjLCIjC2GM=", + "dev": true, + "requires": { + "is-extglob": "1.0.0" + } + }, + "is-iexplorer": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-iexplorer/-/is-iexplorer-1.0.0.tgz", + "integrity": "sha1-HXK8ZtP+Iur2Fw3ajPEJQySM/HY=" + }, + "is-mobile": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/is-mobile/-/is-mobile-0.2.2.tgz", + "integrity": "sha1-Di4AbZntLCFVt2HfgPKjYZrirZ8=" + }, + "is-number": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-2.1.0.tgz", + "integrity": "sha1-Afy7s5NGOlSPL0ZszhbezknbkI8=", + "dev": true, + "requires": { + "kind-of": "3.2.2" + } + }, + "is-plain-obj": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-1.1.0.tgz", + "integrity": "sha1-caUMhCnfync8kqOQpKA7OfzVHT4=" + }, + "is-posix-bracket": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/is-posix-bracket/-/is-posix-bracket-0.1.1.tgz", + "integrity": "sha1-MzTceXdDaOkvAW5vvAqI9c1ua8Q=", + "dev": true + }, + "is-primitive": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-primitive/-/is-primitive-2.0.0.tgz", + "integrity": "sha1-IHurkWOEmcB7Kt8kCkGochADRXU=", + "dev": true + }, + "is-regex": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.0.4.tgz", + "integrity": "sha1-VRdIm1RwkbCTDglWVM7SXul+lJE=", + "requires": { + "has": "1.0.1" + } + }, + "is-stream": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz", + "integrity": "sha1-EtSj3U5o4Lec6428hBc66A2RykQ=", + "dev": true + }, + "is-svg-path": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-svg-path/-/is-svg-path-1.0.2.tgz", + "integrity": "sha1-d6tZDBKz0gNI5cehPQBAyHeE3aA=" + }, + "is-symbol": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.1.tgz", + "integrity": "sha1-PMWfAAJRlLarLjjbrmaJJWtmBXI=" + }, + "is-typedarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", + "integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=" + }, + "isarray": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", + "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=" + }, + "isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=", + "dev": true + }, + "isobject": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-2.1.0.tgz", + "integrity": "sha1-8GVWEJaj8dou9GJy+BXIQNh+DIk=", + "dev": true, + "requires": { + "isarray": "1.0.0" + }, + "dependencies": { + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", + "dev": true + } + } + }, + "isstream": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz", + "integrity": "sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo=" + }, + "jquery": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/jquery/-/jquery-3.2.1.tgz", + "integrity": "sha1-XE2d5lKvbNCncBVKYxu6ErAVx4c=" + }, + "jsbn": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz", + "integrity": "sha1-peZUwuWi3rXyAdls77yoDA7y9RM=", + "optional": true + }, + "json-loader": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/json-loader/-/json-loader-0.5.7.tgz", + "integrity": "sha512-QLPs8Dj7lnf3e3QYS1zkCo+4ZwqOiF9d/nZnYozTISxXWCfNs9yuky5rJw4/W34s7POaNlbZmQGaB5NiXCbP4w==", + "dev": true + }, + "json-parse-better-errors": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json-parse-better-errors/-/json-parse-better-errors-1.0.1.tgz", + "integrity": "sha512-xyQpxeWWMKyJps9CuGJYeng6ssI5bpqS9ltQpdVQ90t4ql6NdnxFKh95JcRt2cun/DjMVNrdjniLPuMA69xmCw==", + "dev": true + }, + "json-parser": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/json-parser/-/json-parser-1.1.5.tgz", + "integrity": "sha1-5i7FJh0aal/CDoEqMgdAxtkAVnc=", + "requires": { + "esprima": "2.7.3" + } + }, + "json-schema": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.2.3.tgz", + "integrity": "sha1-tIDIkuWaLwWVTOcnvT8qTogvnhM=" + }, + "json-schema-traverse": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.3.1.tgz", + "integrity": "sha1-NJptRMU6Ud6JtAgFxdXlm0F9M0A=" + }, + "json-stable-stringify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json-stable-stringify/-/json-stable-stringify-1.0.1.tgz", + "integrity": "sha1-mnWdOcXy/1A/1TAGRu1EX4jE+a8=", + "requires": { + "jsonify": "0.0.0" + } + }, + "json-stringify-safe": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", + "integrity": "sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus=" + }, + "json5": { + "version": "0.5.1", + "resolved": "https://registry.npmjs.org/json5/-/json5-0.5.1.tgz", + "integrity": "sha1-Hq3nrMASA0rYTiOWdn6tn6VJWCE=", + "dev": true + }, + "jsonify": { + "version": "0.0.0", + "resolved": "https://registry.npmjs.org/jsonify/-/jsonify-0.0.0.tgz", + "integrity": "sha1-LHS27kHZPKUbe1qu6PUDYx0lKnM=" + }, + "jsonlint-lines-primitives": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/jsonlint-lines-primitives/-/jsonlint-lines-primitives-1.6.0.tgz", + "integrity": "sha1-u4n2DIubYS/ZE92qI2ZJuEDYZhE=", + "requires": { + "JSV": "4.0.2", + "nomnom": "1.8.1" + } + }, + "jsprim": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.1.tgz", + "integrity": "sha1-MT5mvB5cwG5Di8G3SZwuXFastqI=", + "requires": { + "assert-plus": "1.0.0", + "extsprintf": "1.3.0", + "json-schema": "0.2.3", + "verror": "1.10.0" + } + }, + "kdbush": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/kdbush/-/kdbush-1.0.1.tgz", + "integrity": "sha1-PL0D6d6tnA9vZszblkUOXOzGQOA=" + }, + "kdgrass": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/kdgrass/-/kdgrass-1.0.1.tgz", + "integrity": "sha512-2sfleTaNfu4AQdL9Om42i7D+NnnIwTd+MJYkbCdyv1DvFtHkLLBc8ZwrM2nD1zp4AuSBzCfoDSWcba4c7iHodQ==" + }, + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "requires": { + "is-buffer": "1.1.6" + } + }, + "lazy-cache": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/lazy-cache/-/lazy-cache-1.0.4.tgz", + "integrity": "sha1-odePw6UEdMuAhF07O24dpJpEbo4=" + }, + "lcid": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/lcid/-/lcid-1.0.0.tgz", + "integrity": "sha1-MIrMr6C8SDo4Z7S28rlQYlHRuDU=", + "dev": true, + "requires": { + "invert-kv": "1.0.0" + } + }, + "lerp": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/lerp/-/lerp-1.0.3.tgz", + "integrity": "sha1-oYyJaPkXiW3hXM/MKNVaa3Med24=" + }, + "levn": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/levn/-/levn-0.3.0.tgz", + "integrity": "sha1-OwmSTt+fCDwEkP3UwLxEIeBHZO4=", + "requires": { + "prelude-ls": "1.1.2", + "type-check": "0.3.2" + } + }, + "load-json-file": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-2.0.0.tgz", + "integrity": "sha1-eUfkIUmvgNaWy/eXvKq8/h/inKg=", + "dev": true, + "requires": { + "graceful-fs": "4.1.11", + "parse-json": "2.2.0", + "pify": "2.3.0", + "strip-bom": "3.0.0" + } + }, + "loader-runner": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/loader-runner/-/loader-runner-2.3.0.tgz", + "integrity": "sha1-9IKuqC1UPgeSFwDVpG7yb9rGuKI=", + "dev": true + }, + "loader-utils": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-1.1.0.tgz", + "integrity": "sha1-yYrvSIvM7aL/teLeZG1qdUQp9c0=", + "dev": true, + "requires": { + "big.js": "3.2.0", + "emojis-list": "2.1.0", + "json5": "0.5.1" + } + }, + "locate-path": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-2.0.0.tgz", + "integrity": "sha1-K1aLJl7slExtnA3pw9u7ygNUzY4=", + "dev": true, + "requires": { + "p-locate": "2.0.0", + "path-exists": "3.0.0" + } + }, + "lodash": { + "version": "4.17.4", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.4.tgz", + "integrity": "sha1-eCA6TRwyiuHYbcpkYONptX9AVa4=" + }, + "lodash._baseisequal": { + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/lodash._baseisequal/-/lodash._baseisequal-3.0.7.tgz", + "integrity": "sha1-2AJfdjOdKTQnZ9zIh85cuVpbUfE=", + "requires": { + "lodash.isarray": "3.0.4", + "lodash.istypedarray": "3.0.6", + "lodash.keys": "3.1.2" + } + }, + "lodash._bindcallback": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/lodash._bindcallback/-/lodash._bindcallback-3.0.1.tgz", + "integrity": "sha1-5THCdkTPi1epnhftlbNcdIeJOS4=" + }, + "lodash._getnative": { + "version": "3.9.1", + "resolved": "https://registry.npmjs.org/lodash._getnative/-/lodash._getnative-3.9.1.tgz", + "integrity": "sha1-VwvH3t5G1hzc3mh9ZdPuy6o6r/U=" + }, + "lodash.isarguments": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/lodash.isarguments/-/lodash.isarguments-3.1.0.tgz", + "integrity": "sha1-L1c9hcaiQon/AGY7SRwdM4/zRYo=" + }, + "lodash.isarray": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/lodash.isarray/-/lodash.isarray-3.0.4.tgz", + "integrity": "sha1-eeTriMNqgSKvhvhEqpvNhRtfu1U=" + }, + "lodash.isequal": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/lodash.isequal/-/lodash.isequal-3.0.4.tgz", + "integrity": "sha1-HDXrO27wzR/1F0Pj6jz3/f/ay2Q=", + "requires": { + "lodash._baseisequal": "3.0.7", + "lodash._bindcallback": "3.0.1" + } + }, + "lodash.istypedarray": { + "version": "3.0.6", + "resolved": "https://registry.npmjs.org/lodash.istypedarray/-/lodash.istypedarray-3.0.6.tgz", + "integrity": "sha1-yaR3SYYHUB2OhJTSg7h8OSgc72I=" + }, + "lodash.keys": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/lodash.keys/-/lodash.keys-3.1.2.tgz", + "integrity": "sha1-TbwEcrFWvlCgsoaFXRvQsMZWCYo=", + "requires": { + "lodash._getnative": "3.9.1", + "lodash.isarguments": "3.1.0", + "lodash.isarray": "3.0.4" + } + }, + "longest": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/longest/-/longest-1.0.1.tgz", + "integrity": "sha1-MKCy2jj3N3DoKUoNIuZiXtd9AJc=" + }, + "lru-cache": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-4.1.1.tgz", + "integrity": "sha512-q4spe4KTfsAS1SUHLO0wz8Qiyf1+vMIAgpRYioFYDMNqKfHQbg+AVDH3i4fvpl71/P1L0dBl+fQi+P37UYf0ew==", + "dev": true, + "requires": { + "pseudomap": "1.0.2", + "yallist": "2.1.2" + } + }, + "magic-string": { + "version": "0.22.4", + "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.22.4.tgz", + "integrity": "sha512-kxBL06p6iO2qPBHsqGK2b3cRwiRGpnmSuVWNhwHcMX7qJOUr1HvricYP1LZOCdkQBUp0jiWg2d6WJwR3vYgByw==", + "requires": { + "vlq": "0.2.3" + } + }, + "map-limit": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/map-limit/-/map-limit-0.0.1.tgz", + "integrity": "sha1-63lhAxwPDo0AG/LVb6toXViCLzg=", + "requires": { + "once": "1.3.3" + }, + "dependencies": { + "once": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/once/-/once-1.3.3.tgz", + "integrity": "sha1-suJhVXzkwxTsgwTz+oJmPkKXyiA=", + "requires": { + "wrappy": "1.0.2" + } + } + } + }, + "mapbox-gl": { + "version": "0.22.1", + "resolved": "https://registry.npmjs.org/mapbox-gl/-/mapbox-gl-0.22.1.tgz", + "integrity": "sha1-kqllVH1MLyTCLLxIfu2khpTLYno=", + "requires": { + "csscolorparser": "1.0.3", + "earcut": "2.1.3", + "feature-filter": "2.2.0", + "geojson-rewind": "0.1.0", + "geojson-vt": "2.4.0", + "gl-matrix": "2.4.0", + "grid-index": "1.0.0", + "mapbox-gl-function": "1.3.0", + "mapbox-gl-shaders": "github:mapbox/mapbox-gl-shaders#de2ab007455aa2587c552694c68583f94c9f2747", + "mapbox-gl-style-spec": "github:mapbox/mapbox-gl-style-spec#83b1a3e5837d785af582efd5ed1a212f2df6a4ae", + "mapbox-gl-supported": "1.2.0", + "pbf": "1.3.7", + "pngjs": "2.3.1", + "point-geometry": "0.0.0", + "quickselect": "1.0.1", + "request": "2.83.0", + "resolve-url": "0.2.1", + "shelf-pack": "1.1.0", + "supercluster": "2.3.0", + "unassertify": "2.1.0", + "unitbezier": "0.0.0", + "vector-tile": "1.3.0", + "vt-pbf": "2.1.4", + "webworkify": "1.5.0", + "whoots-js": "2.1.0" + } + }, + "mapbox-gl-function": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/mapbox-gl-function/-/mapbox-gl-function-1.3.0.tgz", + "integrity": "sha1-zuPZV1DBidReg6tBoKV/wqilCbw=" + }, + "mapbox-gl-shaders": { + "version": "github:mapbox/mapbox-gl-shaders#de2ab007455aa2587c552694c68583f94c9f2747", + "requires": { + "brfs": "1.4.4" + } + }, + "mapbox-gl-style-spec": { + "version": "github:mapbox/mapbox-gl-style-spec#83b1a3e5837d785af582efd5ed1a212f2df6a4ae", + "requires": { + "csscolorparser": "1.0.3", + "jsonlint-lines-primitives": "1.6.0", + "lodash.isequal": "3.0.4", + "minimist": "0.0.8", + "rw": "0.1.4", + "sort-object": "0.3.2" + }, + "dependencies": { + "minimist": { + "version": "0.0.8", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz", + "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=" + } + } + }, + "mapbox-gl-supported": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/mapbox-gl-supported/-/mapbox-gl-supported-1.2.0.tgz", + "integrity": "sha1-y9NN+JQgbK3amjPI2aRgnya7GYk=" + }, + "marching-simplex-table": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/marching-simplex-table/-/marching-simplex-table-1.0.0.tgz", + "integrity": "sha1-vBYlbg+Pm1WKqbKHL4gy2UM/Uuo=", + "requires": { + "convex-hull": "1.0.3" + } + }, + "mat4-decompose": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/mat4-decompose/-/mat4-decompose-1.0.4.tgz", + "integrity": "sha1-ZetP451wh496RE60Yk1S9+frL68=", + "requires": { + "gl-mat4": "1.1.4", + "gl-vec3": "1.0.3" + } + }, + "mat4-interpolate": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/mat4-interpolate/-/mat4-interpolate-1.0.4.tgz", + "integrity": "sha1-Vf/p6zw1KV4sDVqfdyXZBoqJ/3Q=", + "requires": { + "gl-mat4": "1.1.4", + "gl-vec3": "1.0.3", + "mat4-decompose": "1.0.4", + "mat4-recompose": "1.0.4", + "quat-slerp": "1.0.1" + } + }, + "mat4-recompose": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/mat4-recompose/-/mat4-recompose-1.0.4.tgz", + "integrity": "sha1-OVPCMP8kc9x3LuAUpSySXPgbDk0=", + "requires": { + "gl-mat4": "1.1.4" + } + }, + "matrix-camera-controller": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/matrix-camera-controller/-/matrix-camera-controller-2.1.3.tgz", + "integrity": "sha1-NeUmDMHNVQliunmfLY1OlLGjk3A=", + "requires": { + "binary-search-bounds": "1.0.0", + "gl-mat4": "1.1.4", + "gl-vec3": "1.0.3", + "mat4-interpolate": "1.0.4" + } + }, + "md5.js": { + "version": "1.3.4", + "resolved": "https://registry.npmjs.org/md5.js/-/md5.js-1.3.4.tgz", + "integrity": "sha1-6b296UogpawYsENA/Fdk1bCdkB0=", + "dev": true, + "requires": { + "hash-base": "3.0.4", + "inherits": "2.0.3" + }, + "dependencies": { + "hash-base": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/hash-base/-/hash-base-3.0.4.tgz", + "integrity": "sha1-X8hoaEfs1zSZQDMZprCj8/auSRg=", + "dev": true, + "requires": { + "inherits": "2.0.3", + "safe-buffer": "5.1.1" + } + } + } + }, + "mem": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/mem/-/mem-1.1.0.tgz", + "integrity": "sha1-Xt1StIXKHZAP5kiVUFOZoN+kX3Y=", + "dev": true, + "requires": { + "mimic-fn": "1.1.0" + } + }, + "memory-fs": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/memory-fs/-/memory-fs-0.4.1.tgz", + "integrity": "sha1-OpoguEYlI+RHz7x+i7gO1me/xVI=", + "dev": true, + "requires": { + "errno": "0.1.6", + "readable-stream": "2.3.3" + }, + "dependencies": { + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", + "dev": true + }, + "readable-stream": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.3.tgz", + "integrity": "sha512-m+qzzcn7KUxEmd1gMbchF+Y2eIUbieUaxkWtptyHywrX0rE8QEYqPC07Vuy4Wm32/xE16NcdBctb8S0Xe/5IeQ==", + "dev": true, + "requires": { + "core-util-is": "1.0.2", + "inherits": "2.0.3", + "isarray": "1.0.0", + "process-nextick-args": "1.0.7", + "safe-buffer": "5.1.1", + "string_decoder": "1.0.3", + "util-deprecate": "1.0.2" + } + }, + "string_decoder": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.0.3.tgz", + "integrity": "sha512-4AH6Z5fzNNBcH+6XDMfA/BTt87skxqJlO0lAh3Dker5zThcAxG6mKz+iGu308UKoPPQ8Dcqx/4JhujzltRa+hQ==", + "dev": true, + "requires": { + "safe-buffer": "5.1.1" + } + } + } + }, + "micromatch": { + "version": "2.3.11", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-2.3.11.tgz", + "integrity": "sha1-hmd8l9FyCzY0MdBNDRUpO9OMFWU=", + "dev": true, + "requires": { + "arr-diff": "2.0.0", + "array-unique": "0.2.1", + "braces": "1.8.5", + "expand-brackets": "0.1.5", + "extglob": "0.3.2", + "filename-regex": "2.0.1", + "is-extglob": "1.0.0", + "is-glob": "2.0.1", + "kind-of": "3.2.2", + "normalize-path": "2.1.1", + "object.omit": "2.0.1", + "parse-glob": "3.0.4", + "regex-cache": "0.4.4" + } + }, + "miller-rabin": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/miller-rabin/-/miller-rabin-4.0.1.tgz", + "integrity": "sha512-115fLhvZVqWwHPbClyntxEVfVDfl9DLLTuJvq3g2O/Oxi8AiNouAHvDSzHS0viUJc+V5vm3eq91Xwqn9dp4jRA==", + "dev": true, + "requires": { + "bn.js": "4.11.8", + "brorand": "1.1.0" + } + }, + "mime-db": { + "version": "1.30.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.30.0.tgz", + "integrity": "sha1-dMZD2i3Z1qRTmZY0ZbJtXKfXHwE=" + }, + "mime-types": { + "version": "2.1.17", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.17.tgz", + "integrity": "sha1-Cdejk/A+mVp5+K+Fe3Cp4KsWVXo=", + "requires": { + "mime-db": "1.30.0" + } + }, + "mimic-fn": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-1.1.0.tgz", + "integrity": "sha1-5md4PZLonb00KBi1IwudYqZyrRg=", + "dev": true + }, + "minify-stream": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/minify-stream/-/minify-stream-1.1.0.tgz", + "integrity": "sha512-Y7bDc1y++oHPZBsz8GiS0E2M+O75OZXAKeHdG7eCcvXHS7fUKUSfUXK5iCKFtYZJaSTS+ircAnDUAhZKhHUjlA==", + "requires": { + "concat-stream": "1.6.0", + "convert-source-map": "1.5.1", + "duplexify": "3.5.3", + "from2-string": "1.1.0", + "uglify-es": "3.3.9", + "xtend": "4.0.1" + }, + "dependencies": { + "commander": { + "version": "2.13.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.13.0.tgz", + "integrity": "sha512-MVuS359B+YzaWqjCL/c+22gfryv+mCBPHAv3zyVI2GN8EY6IRP8VwtasXn8jyyhvvq84R4ImN1OKRtcbIasjYA==" + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==" + }, + "uglify-es": { + "version": "3.3.9", + "resolved": "https://registry.npmjs.org/uglify-es/-/uglify-es-3.3.9.tgz", + "integrity": "sha512-r+MU0rfv4L/0eeW3xZrd16t4NZfK8Ld4SWVglYBb7ez5uXFWHuVRs6xCTrf1yirs9a4j4Y27nn7SRfO6v67XsQ==", + "requires": { + "commander": "2.13.0", + "source-map": "0.6.1" + } + } + } + }, + "minimalistic-assert": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/minimalistic-assert/-/minimalistic-assert-1.0.0.tgz", + "integrity": "sha1-cCvi3aazf0g2vLP121ZkG2Sh09M=", + "dev": true + }, + "minimalistic-crypto-utils": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/minimalistic-crypto-utils/-/minimalistic-crypto-utils-1.0.1.tgz", + "integrity": "sha1-9sAMHAsIIkblxNmd+4x8CDsrWCo=", + "dev": true + }, + "minimatch": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", + "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", + "requires": { + "brace-expansion": "1.1.8" + } + }, + "minimist": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", + "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=" + }, + "mkdirp": { + "version": "0.5.1", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz", + "integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=", + "dev": true, + "requires": { + "minimist": "0.0.8" + }, + "dependencies": { + "minimist": { + "version": "0.0.8", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz", + "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=", + "dev": true + } + } + }, + "moment": { + "version": "2.17.1", + "resolved": "https://registry.npmjs.org/moment/-/moment-2.17.1.tgz", + "integrity": "sha1-/tlQYGPzaxDwZsi1mhRNf66+HYI=" + }, + "monotone-convex-hull-2d": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/monotone-convex-hull-2d/-/monotone-convex-hull-2d-1.0.1.tgz", + "integrity": "sha1-R/Xa6t88Sv03dkuqGqh4ekDu4Iw=", + "requires": { + "robust-orientation": "1.1.3" + } + }, + "mouse-change": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/mouse-change/-/mouse-change-1.4.0.tgz", + "integrity": "sha1-wrd+W/o0pDzhRFyBV6Tk3JiVwU8=", + "requires": { + "mouse-event": "1.0.5" + } + }, + "mouse-event": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/mouse-event/-/mouse-event-1.0.5.tgz", + "integrity": "sha1-s3ie23EJmX1aky0dAdqhVDpQFzI=" + }, + "mouse-event-offset": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/mouse-event-offset/-/mouse-event-offset-3.0.2.tgz", + "integrity": "sha1-39hqbiSMa6jK1TuQXVA3ogY+mYQ=" + }, + "mouse-wheel": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/mouse-wheel/-/mouse-wheel-1.2.0.tgz", + "integrity": "sha1-bSkDseqPtI5h8bU7kDZ3PwQs21w=", + "requires": { + "right-now": "1.0.0", + "signum": "1.0.0", + "to-px": "1.0.1" + }, + "dependencies": { + "signum": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/signum/-/signum-1.0.0.tgz", + "integrity": "sha1-dKfSvyogtA66FqkrFSEk8dVZ+nc=" + } + } + }, + "multi-stage-sourcemap": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/multi-stage-sourcemap/-/multi-stage-sourcemap-0.2.1.tgz", + "integrity": "sha1-sJ/IWG6qF/gdV1xK0C4Pej9rEQU=", + "requires": { + "source-map": "0.1.43" + } + }, + "multipipe": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/multipipe/-/multipipe-0.3.1.tgz", + "integrity": "sha1-kmJVJXYboE/qoJYFtjgrziyR8R8=", + "dev": true, + "requires": { + "duplexer2": "0.1.4" + }, + "dependencies": { + "duplexer2": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/duplexer2/-/duplexer2-0.1.4.tgz", + "integrity": "sha1-ixLauHjA1p4+eJEFFmKjL8a93ME=", + "dev": true, + "requires": { + "readable-stream": "2.3.3" + } + }, + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", + "dev": true + }, + "readable-stream": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.3.tgz", + "integrity": "sha512-m+qzzcn7KUxEmd1gMbchF+Y2eIUbieUaxkWtptyHywrX0rE8QEYqPC07Vuy4Wm32/xE16NcdBctb8S0Xe/5IeQ==", + "dev": true, + "requires": { + "core-util-is": "1.0.2", + "inherits": "2.0.3", + "isarray": "1.0.0", + "process-nextick-args": "1.0.7", + "safe-buffer": "5.1.1", + "string_decoder": "1.0.3", + "util-deprecate": "1.0.2" + } + }, + "string_decoder": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.0.3.tgz", + "integrity": "sha512-4AH6Z5fzNNBcH+6XDMfA/BTt87skxqJlO0lAh3Dker5zThcAxG6mKz+iGu308UKoPPQ8Dcqx/4JhujzltRa+hQ==", + "dev": true, + "requires": { + "safe-buffer": "5.1.1" + } + } + } + }, + "mumath": { + "version": "3.3.4", + "resolved": "https://registry.npmjs.org/mumath/-/mumath-3.3.4.tgz", + "integrity": "sha1-SNSg8P2MrU57Mglu6JsWGmPTC78=", + "requires": { + "almost-equal": "1.1.0" + } + }, + "murmurhash-js": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/murmurhash-js/-/murmurhash-js-1.0.0.tgz", + "integrity": "sha1-sGJ44h/Gw3+lMTcysEEry2rhX1E=" + }, + "nan": { + "version": "2.8.0", + "resolved": "https://registry.npmjs.org/nan/-/nan-2.8.0.tgz", + "integrity": "sha1-7XFfP+neArV6XmJS2QqWZ14fCFo=", + "dev": true, + "optional": true + }, + "ndarray": { + "version": "1.0.18", + "resolved": "https://registry.npmjs.org/ndarray/-/ndarray-1.0.18.tgz", + "integrity": "sha1-tg06cyJOxVXQ+qeXEeUCRI/T95M=", + "requires": { + "iota-array": "1.0.0", + "is-buffer": "1.1.6" + } + }, + "ndarray-extract-contour": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/ndarray-extract-contour/-/ndarray-extract-contour-1.0.1.tgz", + "integrity": "sha1-Cu4ROjozsia5DEiIz4d79HUTBeQ=", + "requires": { + "typedarray-pool": "1.1.0" + } + }, + "ndarray-fill": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/ndarray-fill/-/ndarray-fill-1.0.2.tgz", + "integrity": "sha1-owpg9xiODJWC/N1YiWrNy1IqHtY=", + "requires": { + "cwise": "1.0.10" + } + }, + "ndarray-gradient": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/ndarray-gradient/-/ndarray-gradient-1.0.0.tgz", + "integrity": "sha1-t0kaUVxqZJ8ZpiMk//byf8jCU5M=", + "requires": { + "cwise-compiler": "1.1.3", + "dup": "1.0.0" + } + }, + "ndarray-homography": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/ndarray-homography/-/ndarray-homography-1.0.0.tgz", + "integrity": "sha1-w1UW6oa8KGK06ASiNqJwcwn+KWs=", + "requires": { + "gl-matrix-invert": "1.0.0", + "ndarray-warp": "1.0.1" + } + }, + "ndarray-linear-interpolate": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/ndarray-linear-interpolate/-/ndarray-linear-interpolate-1.0.0.tgz", + "integrity": "sha1-eLySuFuavBW25n7mWCj54hN65ys=" + }, + "ndarray-ops": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/ndarray-ops/-/ndarray-ops-1.2.2.tgz", + "integrity": "sha1-WeiNLDKn7ryxvGkPrhQVeVV6YU4=", + "requires": { + "cwise-compiler": "1.1.3" + } + }, + "ndarray-pack": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/ndarray-pack/-/ndarray-pack-1.2.1.tgz", + "integrity": "sha1-jK6+qqJNXs9w/4YCBjeXfajuWFo=", + "requires": { + "cwise-compiler": "1.1.3", + "ndarray": "1.0.18" + } + }, + "ndarray-scratch": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/ndarray-scratch/-/ndarray-scratch-1.2.0.tgz", + "integrity": "sha1-YwRjbWLrqT20cnrBPGkzQdulDgE=", + "requires": { + "ndarray": "1.0.18", + "ndarray-ops": "1.2.2", + "typedarray-pool": "1.1.0" + } + }, + "ndarray-sort": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/ndarray-sort/-/ndarray-sort-1.0.1.tgz", + "integrity": "sha1-/qBbTLg0x/TgIWo1TzynUTAN/Wo=", + "requires": { + "typedarray-pool": "1.1.0" + } + }, + "ndarray-warp": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/ndarray-warp/-/ndarray-warp-1.0.1.tgz", + "integrity": "sha1-qKElqqu6C+v5O9bKg+ar1oIqNOA=", + "requires": { + "cwise": "1.0.10", + "ndarray-linear-interpolate": "1.0.0" + } + }, + "nextafter": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/nextafter/-/nextafter-1.0.0.tgz", + "integrity": "sha1-t9d7U1MQ4+CX5gJauwqQNHfsGjo=", + "requires": { + "double-bits": "1.1.1" + } + }, + "node-libs-browser": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/node-libs-browser/-/node-libs-browser-2.1.0.tgz", + "integrity": "sha512-5AzFzdoIMb89hBGMZglEegffzgRg+ZFoUmisQ8HI4j1KDdpx13J0taNp2y9xPbur6W61gepGDDotGBVQ7mfUCg==", + "dev": true, + "requires": { + "assert": "1.4.1", + "browserify-zlib": "0.2.0", + "buffer": "4.9.1", + "console-browserify": "1.1.0", + "constants-browserify": "1.0.0", + "crypto-browserify": "3.12.0", + "domain-browser": "1.1.7", + "events": "1.1.1", + "https-browserify": "1.0.0", + "os-browserify": "0.3.0", + "path-browserify": "0.0.0", + "process": "0.11.10", + "punycode": "1.4.1", + "querystring-es3": "0.2.1", + "readable-stream": "2.3.3", + "stream-browserify": "2.0.1", + "stream-http": "2.7.2", + "string_decoder": "1.0.3", + "timers-browserify": "2.0.4", + "tty-browserify": "0.0.0", + "url": "0.11.0", + "util": "0.10.3", + "vm-browserify": "0.0.4" + }, + "dependencies": { + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", + "dev": true + }, + "readable-stream": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.3.tgz", + "integrity": "sha512-m+qzzcn7KUxEmd1gMbchF+Y2eIUbieUaxkWtptyHywrX0rE8QEYqPC07Vuy4Wm32/xE16NcdBctb8S0Xe/5IeQ==", + "dev": true, + "requires": { + "core-util-is": "1.0.2", + "inherits": "2.0.3", + "isarray": "1.0.0", + "process-nextick-args": "1.0.7", + "safe-buffer": "5.1.1", + "string_decoder": "1.0.3", + "util-deprecate": "1.0.2" + } + }, + "string_decoder": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.0.3.tgz", + "integrity": "sha512-4AH6Z5fzNNBcH+6XDMfA/BTt87skxqJlO0lAh3Dker5zThcAxG6mKz+iGu308UKoPPQ8Dcqx/4JhujzltRa+hQ==", + "dev": true, + "requires": { + "safe-buffer": "5.1.1" + } + } + } + }, + "nomnom": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/nomnom/-/nomnom-1.8.1.tgz", + "integrity": "sha1-IVH3Ikcrp55Qp2/BJbuMjy5Nwqc=", + "requires": { + "chalk": "0.4.0", + "underscore": "1.6.0" + }, + "dependencies": { + "ansi-styles": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-1.0.0.tgz", + "integrity": "sha1-yxAt8cVvUSPquLZ817mAJ6AnkXg=" + }, + "chalk": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-0.4.0.tgz", + "integrity": "sha1-UZmj3c0MHv4jvAjBsCewYXbgxk8=", + "requires": { + "ansi-styles": "1.0.0", + "has-color": "0.1.7", + "strip-ansi": "0.1.1" + } + }, + "underscore": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.6.0.tgz", + "integrity": "sha1-izixDKze9jM3uLJOT/htRa6lKag=" + } + } + }, + "normalize-package-data": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.4.0.tgz", + "integrity": "sha512-9jjUFbTPfEy3R/ad/2oNbKtW9Hgovl5O1FvFWKkKblNXoN/Oou6+9+KKohPK13Yc3/TyunyWhJp6gvRNR/PPAw==", + "dev": true, + "requires": { + "hosted-git-info": "2.5.0", + "is-builtin-module": "1.0.0", + "semver": "5.4.1", + "validate-npm-package-license": "3.0.1" + } + }, + "normalize-path": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-2.1.1.tgz", + "integrity": "sha1-GrKLVW4Zg2Oowab35vogE3/mrtk=", + "dev": true, + "requires": { + "remove-trailing-separator": "1.1.0" + } + }, + "normalize-svg-path": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/normalize-svg-path/-/normalize-svg-path-0.1.0.tgz", + "integrity": "sha1-RWNg5g7Odfvve11+FgSA5//Rb+U=" + }, + "normals": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/normals/-/normals-1.1.0.tgz", + "integrity": "sha1-MltZXtNK/kZ6bFWhT9kIV4f/WcA=" + }, + "npm-run-path": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-2.0.2.tgz", + "integrity": "sha1-NakjLfo11wZ7TLLd8jV7GHFTbF8=", + "dev": true, + "requires": { + "path-key": "2.0.1" + } + }, + "number-is-nan": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz", + "integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=", + "dev": true + }, + "numeric": { + "version": "1.2.6", + "resolved": "https://registry.npmjs.org/numeric/-/numeric-1.2.6.tgz", + "integrity": "sha1-dlsCvvl5iPz4gNTrPza4D6MTNao=" + }, + "oauth-sign": { + "version": "0.8.2", + "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.8.2.tgz", + "integrity": "sha1-Rqarfwrq2N6unsBWV4C31O/rnUM=" + }, + "object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=" + }, + "object-inspect": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.3.0.tgz", + "integrity": "sha512-OHHnLgLNXpM++GnJRyyhbr2bwl3pPVm4YvaraHrRvDt/N3r+s/gDVHciA7EJBTkijKXj61ssgSAikq1fb0IBRg==" + }, + "object-keys": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.0.11.tgz", + "integrity": "sha1-xUYBd4rVYPEULODgG8yotW0TQm0=" + }, + "object.omit": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/object.omit/-/object.omit-2.0.1.tgz", + "integrity": "sha1-Gpx0SCnznbuFjHbKNXmuKlTr0fo=", + "dev": true, + "requires": { + "for-own": "0.1.5", + "is-extendable": "0.1.1" + } + }, + "once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", + "requires": { + "wrappy": "1.0.2" + } + }, + "optical-properties": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/optical-properties/-/optical-properties-1.0.0.tgz", + "integrity": "sha512-XnBQYbIIzDVr7U3L7d3xyAEqp1W+HTkqmw/G4L/Ae/+dq57bT1jqW2uDwV0wCUzO8gsTDIZhGQsGrMb17VSkEA==" + }, + "optionator": { + "version": "0.8.2", + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.8.2.tgz", + "integrity": "sha1-NkxeQJ0/TWMB1sC0wFu6UBgK62Q=", + "requires": { + "deep-is": "0.1.3", + "fast-levenshtein": "2.0.6", + "levn": "0.3.0", + "prelude-ls": "1.1.2", + "type-check": "0.3.2", + "wordwrap": "1.0.0" + } + }, + "orbit-camera-controller": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/orbit-camera-controller/-/orbit-camera-controller-4.0.0.tgz", + "integrity": "sha1-bis28OeHhmPDMPUNqbfOaGwncAU=", + "requires": { + "filtered-vector": "1.2.4", + "gl-mat4": "1.1.4" + } + }, + "os-browserify": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/os-browserify/-/os-browserify-0.3.0.tgz", + "integrity": "sha1-hUNzx/XCMVkU/Jv8a9gjj92h7Cc=", + "dev": true + }, + "os-homedir": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/os-homedir/-/os-homedir-1.0.2.tgz", + "integrity": "sha1-/7xJiDNuDoM94MFox+8VISGqf7M=" + }, + "os-locale": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/os-locale/-/os-locale-2.1.0.tgz", + "integrity": "sha512-3sslG3zJbEYcaC4YVAvDorjGxc7tv6KVATnLPZONiljsUncvihe9BQoVCEs0RZ1kmf4Hk9OBqlZfJZWI4GanKA==", + "dev": true, + "requires": { + "execa": "0.7.0", + "lcid": "1.0.0", + "mem": "1.1.0" + } + }, + "p-finally": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/p-finally/-/p-finally-1.0.0.tgz", + "integrity": "sha1-P7z7FbiZpEEjs0ttzBi3JDNqLK4=", + "dev": true + }, + "p-limit": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-1.1.0.tgz", + "integrity": "sha1-sH/y2aXYi+yAYDWJWiurZqJ5iLw=", + "dev": true + }, + "p-locate": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-2.0.0.tgz", + "integrity": "sha1-IKAQOyIqcMj9OcwuWAaA893l7EM=", + "dev": true, + "requires": { + "p-limit": "1.1.0" + } + }, + "pad-left": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/pad-left/-/pad-left-1.0.2.tgz", + "integrity": "sha1-GeVzXqmDlaJs7carkm6tEPMQDUw=", + "requires": { + "repeat-string": "1.6.1" + } + }, + "pako": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/pako/-/pako-1.0.6.tgz", + "integrity": "sha512-lQe48YPsMJAig+yngZ87Lus+NF+3mtu7DVOBu6b/gHO1YpKwIj5AWjZ/TOS7i46HD/UixzWb1zeWDZfGZ3iYcg==", + "dev": true + }, + "parse-asn1": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/parse-asn1/-/parse-asn1-5.1.0.tgz", + "integrity": "sha1-N8T5t+06tlx0gXtfJICTf7+XxxI=", + "dev": true, + "requires": { + "asn1.js": "4.9.2", + "browserify-aes": "1.1.1", + "create-hash": "1.1.3", + "evp_bytestokey": "1.0.3", + "pbkdf2": "3.0.14" + } + }, + "parse-glob": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/parse-glob/-/parse-glob-3.0.4.tgz", + "integrity": "sha1-ssN2z7EfNVE7rdFz7wu246OIORw=", + "dev": true, + "requires": { + "glob-base": "0.3.0", + "is-dotfile": "1.0.3", + "is-extglob": "1.0.0", + "is-glob": "2.0.1" + } + }, + "parse-json": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-2.2.0.tgz", + "integrity": "sha1-9ID0BDTvgHQfhGkJn43qGPVaTck=", + "dev": true, + "requires": { + "error-ex": "1.3.1" + } + }, + "parse-svg-path": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/parse-svg-path/-/parse-svg-path-0.1.2.tgz", + "integrity": "sha1-en7A0esG+lMlx9PgCbhZoJtdSes=" + }, + "parse-unit": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/parse-unit/-/parse-unit-1.0.1.tgz", + "integrity": "sha1-fhu21b7zh0wo45JSaiVBFwKR7s8=" + }, + "path-browserify": { + "version": "0.0.0", + "resolved": "https://registry.npmjs.org/path-browserify/-/path-browserify-0.0.0.tgz", + "integrity": "sha1-oLhwcpquIUAFt9UDLsLLuw+0RRo=", + "dev": true + }, + "path-exists": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", + "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=", + "dev": true + }, + "path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=" + }, + "path-key": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-2.0.1.tgz", + "integrity": "sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A=", + "dev": true + }, + "path-parse": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.5.tgz", + "integrity": "sha1-PBrfhx6pzWyUMbbqK9dKD/BVxME=" + }, + "path-posix": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/path-posix/-/path-posix-1.0.0.tgz", + "integrity": "sha1-BrJhE/Vr6rBCVFojv6iAA8ysJg8=" + }, + "path-type": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-2.0.0.tgz", + "integrity": "sha1-8BLMuEFbcJb8LaoQVMPXI4lZTHM=", + "dev": true, + "requires": { + "pify": "2.3.0" + } + }, + "pbf": { + "version": "1.3.7", + "resolved": "https://registry.npmjs.org/pbf/-/pbf-1.3.7.tgz", + "integrity": "sha1-Hj0Ee6PL6Ahq6FSiVQOrRTfUM10=", + "requires": { + "ieee754": "1.1.8", + "resolve-protobuf-schema": "2.0.0" + } + }, + "pbkdf2": { + "version": "3.0.14", + "resolved": "https://registry.npmjs.org/pbkdf2/-/pbkdf2-3.0.14.tgz", + "integrity": "sha512-gjsZW9O34fm0R7PaLHRJmLLVfSoesxztjPjE9o6R+qtVJij90ltg1joIovN9GKrRW3t1PzhDDG3UMEMFfZ+1wA==", + "dev": true, + "requires": { + "create-hash": "1.1.3", + "create-hmac": "1.1.6", + "ripemd160": "2.0.1", + "safe-buffer": "5.1.1", + "sha.js": "2.4.9" + } + }, + "performance-now": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz", + "integrity": "sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns=" + }, + "permutation-parity": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/permutation-parity/-/permutation-parity-1.0.0.tgz", + "integrity": "sha1-AXTVH8pwSxG5pLFSsj1Tf9xrXvQ=", + "requires": { + "typedarray-pool": "1.1.0" + } + }, + "permutation-rank": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/permutation-rank/-/permutation-rank-1.0.0.tgz", + "integrity": "sha1-n9mLvOzwj79ZlLXq3JSmLmeUg7U=", + "requires": { + "invert-permutation": "1.0.0", + "typedarray-pool": "1.1.0" + } + }, + "pick-by-alias": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/pick-by-alias/-/pick-by-alias-1.2.0.tgz", + "integrity": "sha1-X3yysfIabh6ISgyHhVqko3NhEHs=" + }, + "pify": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", + "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", + "dev": true + }, + "planar-dual": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/planar-dual/-/planar-dual-1.0.2.tgz", + "integrity": "sha1-tqQjVSOxsMt55fkm+OozXdmC1WM=", + "requires": { + "compare-angle": "1.0.1", + "dup": "1.0.0" + } + }, + "planar-graph-to-polyline": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/planar-graph-to-polyline/-/planar-graph-to-polyline-1.0.5.tgz", + "integrity": "sha1-iCuGBRmbqIv9RkyVUzA1VsUrmIo=", + "requires": { + "edges-to-adjacency-list": "1.0.0", + "planar-dual": "1.0.2", + "point-in-big-polygon": "2.0.0", + "robust-orientation": "1.1.3", + "robust-sum": "1.0.0", + "two-product": "1.0.2", + "uniq": "1.0.1" + } + }, + "plotly.js": { + "version": "1.33.1", + "resolved": "https://registry.npmjs.org/plotly.js/-/plotly.js-1.33.1.tgz", + "integrity": "sha512-OgV4rJCUnr2VwIfnoxEU1za3DbnH8BEVg8oIWST1EagFqLQ/MpOVFsAbm6u4V2ZJnVS8F0VTCMcUmdokHUG/fA==", + "requires": { + "3d-view": "2.0.0", + "@plotly/d3-sankey": "0.5.0", + "alpha-shape": "1.0.0", + "bubleify": "1.1.0", + "canvas-fit": "1.5.0", + "color-normalize": "1.0.3", + "color-rgba": "2.0.0", + "convex-hull": "1.0.3", + "country-regex": "1.1.0", + "d3": "3.5.17", + "d3-force": "1.1.0", + "delaunay-triangulate": "1.1.6", + "es6-promise": "3.3.1", + "fast-isnumeric": "1.1.1", + "font-atlas-sdf": "1.3.3", + "gl-contour2d": "1.1.3", + "gl-error3d": "1.0.7", + "gl-heatmap2d": "1.0.3", + "gl-line3d": "1.1.1", + "gl-mat4": "1.1.4", + "gl-mesh3d": "1.3.1", + "gl-plot2d": "1.3.0", + "gl-plot3d": "1.5.4", + "gl-pointcloud2d": "1.0.0", + "gl-scatter3d": "1.0.10", + "gl-select-box": "1.0.1", + "gl-shader": "4.2.0", + "gl-spikes2d": "1.0.1", + "gl-surface3d": "1.3.3", + "has-hover": "1.0.1", + "kdgrass": "1.0.1", + "mapbox-gl": "0.22.1", + "matrix-camera-controller": "2.1.3", + "minify-stream": "1.1.0", + "mouse-change": "1.4.0", + "mouse-event-offset": "3.0.2", + "mouse-wheel": "1.2.0", + "ndarray": "1.0.18", + "ndarray-fill": "1.0.2", + "ndarray-homography": "1.0.0", + "ndarray-ops": "1.2.2", + "polybooljs": "1.2.0", + "regl": "1.3.1", + "regl-error2d": "2.0.4", + "regl-line2d": "2.1.2", + "regl-scatter2d": "2.1.13", + "right-now": "1.0.0", + "robust-orientation": "1.1.3", + "sane-topojson": "2.0.0", + "strongly-connected-components": "1.0.1", + "superscript-text": "1.0.0", + "svg-path-sdf": "1.1.1", + "tinycolor2": "1.4.1", + "topojson-client": "2.1.0", + "webgl-context": "2.2.0", + "world-calendars": "1.0.3" + } + }, + "pngjs": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/pngjs/-/pngjs-2.3.1.tgz", + "integrity": "sha1-EdHhK5y2TWPjDBQ6Mw9MH1Z9qF8=" + }, + "point-geometry": { + "version": "0.0.0", + "resolved": "https://registry.npmjs.org/point-geometry/-/point-geometry-0.0.0.tgz", + "integrity": "sha1-b8vK16gDtkGCR91uScKFPFhNr/c=" + }, + "point-in-big-polygon": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/point-in-big-polygon/-/point-in-big-polygon-2.0.0.tgz", + "integrity": "sha1-ObYT6mzxfWtD4Yj3fzTETGszulU=", + "requires": { + "binary-search-bounds": "1.0.0", + "interval-tree-1d": "1.0.3", + "robust-orientation": "1.1.3", + "slab-decomposition": "1.0.2" + } + }, + "polybooljs": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/polybooljs/-/polybooljs-1.2.0.tgz", + "integrity": "sha1-tDkMLgedTCYtOyUExiiNlbp6R1g=" + }, + "polytope-closest-point": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/polytope-closest-point/-/polytope-closest-point-1.0.0.tgz", + "integrity": "sha1-5uV/QIGrXox3i4Ee8G4sSK4zjD8=", + "requires": { + "numeric": "1.2.6" + } + }, + "prelude-ls": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.1.2.tgz", + "integrity": "sha1-IZMqVJ9eUv/ZqCf1cOBL5iqX2lQ=" + }, + "preserve": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/preserve/-/preserve-0.2.0.tgz", + "integrity": "sha1-gV7R9uvGWSb4ZbMQwHE7yzMVzks=", + "dev": true + }, + "process": { + "version": "0.11.10", + "resolved": "https://registry.npmjs.org/process/-/process-0.11.10.tgz", + "integrity": "sha1-czIwDoQBYb2j5podHZGn1LwW8YI=", + "dev": true + }, + "process-nextick-args": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-1.0.7.tgz", + "integrity": "sha1-FQ4gt1ZZCtP5EJPyWk8q2L/zC6M=" + }, + "protocol-buffers-schema": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/protocol-buffers-schema/-/protocol-buffers-schema-2.2.0.tgz", + "integrity": "sha1-0pxs1z+2VZePtpiWkRgNuEQRn2E=" + }, + "prr": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/prr/-/prr-1.0.1.tgz", + "integrity": "sha1-0/wRS6BplaRexok/SEzrHXj19HY=", + "dev": true + }, + "pseudomap": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/pseudomap/-/pseudomap-1.0.2.tgz", + "integrity": "sha1-8FKijacOYYkX7wqKw0wa5aaChrM=", + "dev": true + }, + "public-encrypt": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/public-encrypt/-/public-encrypt-4.0.0.tgz", + "integrity": "sha1-OfaZ86RlYN1eusvKaTyvfGXBjMY=", + "dev": true, + "requires": { + "bn.js": "4.11.8", + "browserify-rsa": "4.0.1", + "create-hash": "1.1.3", + "parse-asn1": "5.1.0", + "randombytes": "2.0.5" + } + }, + "punycode": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz", + "integrity": "sha1-wNWmOycYgArY4esPpSachN1BhF4=" + }, + "qs": { + "version": "6.5.1", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.1.tgz", + "integrity": "sha512-eRzhrN1WSINYCDCbrz796z37LOe3m5tmW7RQf6oBntukAG1nmovJvhnwHHRMAfeoItc1m2Hk02WER2aQ/iqs+A==" + }, + "quat-slerp": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/quat-slerp/-/quat-slerp-1.0.1.tgz", + "integrity": "sha1-K6oVzjprvcMkHZcusXKDE57Wnyk=", + "requires": { + "gl-quat": "1.0.0" + } + }, + "querystring": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/querystring/-/querystring-0.2.0.tgz", + "integrity": "sha1-sgmEkgO7Jd+CDadW50cAWHhSFiA=", + "dev": true + }, + "querystring-es3": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/querystring-es3/-/querystring-es3-0.2.1.tgz", + "integrity": "sha1-nsYfeQSYdXB9aUFFlv2Qek1xHnM=", + "dev": true + }, + "querystringify": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/querystringify/-/querystringify-1.0.0.tgz", + "integrity": "sha1-YoYkIRLFtxL6ZU5SZlK/ahP/Bcs=" + }, + "quickselect": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/quickselect/-/quickselect-1.0.1.tgz", + "integrity": "sha512-Jt30UQSzTbxf6L2bFTMabHtGtYUzQcvOY0a+s5brm8tzndV/XWifBIH9v5QKtH5gGCZ5RRDwRhdhGMDVHAEGNQ==" + }, + "quote-stream": { + "version": "0.0.0", + "resolved": "https://registry.npmjs.org/quote-stream/-/quote-stream-0.0.0.tgz", + "integrity": "sha1-zeKelMQJsW4Z3HCYuJtmWPlyHTs=", + "requires": { + "minimist": "0.0.8", + "through2": "0.4.2" + }, + "dependencies": { + "minimist": { + "version": "0.0.8", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz", + "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=" + }, + "object-keys": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-0.4.0.tgz", + "integrity": "sha1-KKaq50KN0sOpLz2V8hM13SBOAzY=" + }, + "through2": { + "version": "0.4.2", + "resolved": "https://registry.npmjs.org/through2/-/through2-0.4.2.tgz", + "integrity": "sha1-2/WGYDEVHsg1K7bE22SiKSqEC5s=", + "requires": { + "readable-stream": "1.0.34", + "xtend": "2.1.2" + } + }, + "xtend": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-2.1.2.tgz", + "integrity": "sha1-bv7MKk2tjmlixJAbM3znuoe10os=", + "requires": { + "object-keys": "0.4.0" + } + } + } + }, + "randomatic": { + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/randomatic/-/randomatic-1.1.7.tgz", + "integrity": "sha512-D5JUjPyJbaJDkuAazpVnSfVkLlpeO3wDlPROTMLGKG1zMFNFRgrciKo1ltz/AzNTkqE0HzDx655QOL51N06how==", + "dev": true, + "requires": { + "is-number": "3.0.0", + "kind-of": "4.0.0" + }, + "dependencies": { + "is-number": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", + "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", + "dev": true, + "requires": { + "kind-of": "3.2.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "1.1.6" + } + } + } + }, + "kind-of": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-4.0.0.tgz", + "integrity": "sha1-IIE989cSkosgc3hpGkUGb65y3Vc=", + "dev": true, + "requires": { + "is-buffer": "1.1.6" + } + } + } + }, + "randombytes": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.0.5.tgz", + "integrity": "sha512-8T7Zn1AhMsQ/HI1SjcCfT/t4ii3eAqco3yOcSzS4mozsOz69lHLsoMXmF9nZgnFanYscnSlUSgs8uZyKzpE6kg==", + "dev": true, + "requires": { + "safe-buffer": "5.1.1" + } + }, + "randomfill": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/randomfill/-/randomfill-1.0.3.tgz", + "integrity": "sha512-YL6GrhrWoic0Eq8rXVbMptH7dAxCs0J+mh5Y0euNekPPYaxEmdVGim6GdoxoRzKW2yJoU8tueifS7mYxvcFDEQ==", + "dev": true, + "requires": { + "randombytes": "2.0.5", + "safe-buffer": "5.1.1" + } + }, + "rat-vec": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/rat-vec/-/rat-vec-1.1.1.tgz", + "integrity": "sha1-Dd4rZrezS7G80qI4BerIBth/0X8=", + "requires": { + "big-rat": "1.0.4" + } + }, + "read-package-json": { + "version": "2.0.12", + "resolved": "https://registry.npmjs.org/read-package-json/-/read-package-json-2.0.12.tgz", + "integrity": "sha512-m7/I0+tP6D34EVvSlzCtuVA4D/dHL6OpLcn2e4XVP5X57pCKGUy1JjRSBVKHWpB+vUU91sL85h84qX0MdXzBSw==", + "dev": true, + "requires": { + "glob": "7.1.2", + "graceful-fs": "4.1.11", + "json-parse-better-errors": "1.0.1", + "normalize-package-data": "2.4.0", + "slash": "1.0.0" + } + }, + "read-pkg": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-2.0.0.tgz", + "integrity": "sha1-jvHAYjxqbbDcZxPEv6xGMysjaPg=", + "dev": true, + "requires": { + "load-json-file": "2.0.0", + "normalize-package-data": "2.4.0", + "path-type": "2.0.0" + } + }, + "read-pkg-up": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-2.0.0.tgz", + "integrity": "sha1-a3KoBImE4MQeeVEP1en6mbO1Sb4=", + "dev": true, + "requires": { + "find-up": "2.1.0", + "read-pkg": "2.0.0" + } + }, + "readable-stream": { + "version": "1.0.34", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz", + "integrity": "sha1-Elgg40vIQtLyqq+v5MKRbuMsFXw=", + "requires": { + "core-util-is": "1.0.2", + "inherits": "2.0.3", + "isarray": "0.0.1", + "string_decoder": "0.10.31" + } + }, + "readdirp": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-2.1.0.tgz", + "integrity": "sha1-TtCtBg3zBzMAxIRANz9y0cxkLXg=", + "dev": true, + "requires": { + "graceful-fs": "4.1.11", + "minimatch": "3.0.4", + "readable-stream": "2.3.3", + "set-immediate-shim": "1.0.1" + }, + "dependencies": { + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", + "dev": true + }, + "readable-stream": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.3.tgz", + "integrity": "sha512-m+qzzcn7KUxEmd1gMbchF+Y2eIUbieUaxkWtptyHywrX0rE8QEYqPC07Vuy4Wm32/xE16NcdBctb8S0Xe/5IeQ==", + "dev": true, + "requires": { + "core-util-is": "1.0.2", + "inherits": "2.0.3", + "isarray": "1.0.0", + "process-nextick-args": "1.0.7", + "safe-buffer": "5.1.1", + "string_decoder": "1.0.3", + "util-deprecate": "1.0.2" + } + }, + "string_decoder": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.0.3.tgz", + "integrity": "sha512-4AH6Z5fzNNBcH+6XDMfA/BTt87skxqJlO0lAh3Dker5zThcAxG6mKz+iGu308UKoPPQ8Dcqx/4JhujzltRa+hQ==", + "dev": true, + "requires": { + "safe-buffer": "5.1.1" + } + } + } + }, + "reduce-simplicial-complex": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/reduce-simplicial-complex/-/reduce-simplicial-complex-1.0.0.tgz", + "integrity": "sha1-dNaWovg196bc2SBl/YxRgfLt+Lw=", + "requires": { + "cell-orientation": "1.0.1", + "compare-cell": "1.0.0", + "compare-oriented-cell": "1.0.1" + } + }, + "regex-cache": { + "version": "0.4.4", + "resolved": "https://registry.npmjs.org/regex-cache/-/regex-cache-0.4.4.tgz", + "integrity": "sha512-nVIZwtCjkC9YgvWkpM55B5rBhBYRZhAaJbgcFYXXsHnbZ9UZI9nnVWYZpBlCqv9ho2eZryPnWrZGsOdPwVWXWQ==", + "dev": true, + "requires": { + "is-equal-shallow": "0.1.3" + } + }, + "regl": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/regl/-/regl-1.3.1.tgz", + "integrity": "sha1-KZXmOnmExSDvLaD28QJ/cFEzgUA=" + }, + "regl-error2d": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/regl-error2d/-/regl-error2d-2.0.4.tgz", + "integrity": "sha512-EsK+KJ2OREwMyVQ5jRBcoHN3vWPM8RSKU6mHlAVZ4sh71XsbQh4ob+IQ200nHasvusWY6ensMZG+RwTbG5tvXQ==", + "requires": { + "array-bounds": "1.0.1", + "bubleify": "1.1.0", + "color-normalize": "1.0.3", + "flatten-vertex-data": "1.0.0", + "object-assign": "4.1.1", + "pick-by-alias": "1.2.0", + "to-float32": "1.0.0", + "update-diff": "1.1.0" + } + }, + "regl-line2d": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/regl-line2d/-/regl-line2d-2.1.2.tgz", + "integrity": "sha512-xV1wRhzjq6JcE3ojKdF+LF9mufIzYugMUH97X4QFohi3nYyobpRYU2FBaEDowUCvInnkNeLNzhj837nm50oKew==", + "requires": { + "array-bounds": "1.0.1", + "array-normalize": "1.1.3", + "bubleify": "1.1.0", + "color-normalize": "1.0.3", + "earcut": "2.1.3", + "flatten-vertex-data": "1.0.0", + "glslify": "6.1.0", + "object-assign": "4.1.1", + "pick-by-alias": "1.2.0", + "to-float32": "1.0.0", + "update-diff": "1.1.0" + }, + "dependencies": { + "escodegen": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/escodegen/-/escodegen-1.9.0.tgz", + "integrity": "sha512-v0MYvNQ32bzwoG2OSFzWAkuahDQHK92JBN0pTAALJ4RIxEZe766QJPDR8Hqy7XNUy5K3fnVL76OqYAdc4TZEIw==", + "requires": { + "esprima": "3.1.3", + "estraverse": "4.2.0", + "esutils": "2.0.2", + "optionator": "0.8.2", + "source-map": "0.5.7" + } + }, + "esprima": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-3.1.3.tgz", + "integrity": "sha1-/cpRzuYTOJXjyI1TXOSdv/YqRjM=" + }, + "estraverse": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.2.0.tgz", + "integrity": "sha1-De4/7TH81GlhjOc0IJn8GvoL2xM=" + }, + "esutils": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.2.tgz", + "integrity": "sha1-Cr9PHKpbyx96nYrMbepPqqBLrJs=" + }, + "glslify": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/glslify/-/glslify-6.1.0.tgz", + "integrity": "sha1-zf/P0qZXFyISjT0TNWwTbebOl0I=", + "requires": { + "bl": "1.2.1", + "concat-stream": "1.6.0", + "duplexify": "3.5.3", + "falafel": "2.1.0", + "from2": "2.3.0", + "glsl-resolve": "0.0.1", + "glsl-token-whitespace-trim": "1.0.0", + "glslify-bundle": "5.0.0", + "glslify-deps": "1.3.0", + "minimist": "1.2.0", + "resolve": "1.4.0", + "stack-trace": "0.0.9", + "static-eval": "1.1.1", + "tape": "4.8.0", + "through2": "2.0.3", + "xtend": "4.0.1" + } + }, + "glslify-bundle": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/glslify-bundle/-/glslify-bundle-5.0.0.tgz", + "integrity": "sha1-AlKtoe+d8wtmAAbguyH9EwtIbkI=", + "requires": { + "glsl-inject-defines": "1.0.3", + "glsl-token-defines": "1.0.0", + "glsl-token-depth": "1.1.2", + "glsl-token-descope": "1.0.2", + "glsl-token-scope": "1.1.2", + "glsl-token-string": "1.0.1", + "glsl-token-whitespace-trim": "1.0.0", + "glsl-tokenizer": "2.1.2", + "murmurhash-js": "1.0.0", + "shallow-copy": "0.0.1" + } + }, + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=" + }, + "readable-stream": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.3.tgz", + "integrity": "sha512-m+qzzcn7KUxEmd1gMbchF+Y2eIUbieUaxkWtptyHywrX0rE8QEYqPC07Vuy4Wm32/xE16NcdBctb8S0Xe/5IeQ==", + "requires": { + "core-util-is": "1.0.2", + "inherits": "2.0.3", + "isarray": "1.0.0", + "process-nextick-args": "1.0.7", + "safe-buffer": "5.1.1", + "string_decoder": "1.0.3", + "util-deprecate": "1.0.2" + } + }, + "source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", + "optional": true + }, + "static-eval": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/static-eval/-/static-eval-1.1.1.tgz", + "integrity": "sha1-yoEwIQNUzxPZpyK8fpI3eEV7sZI=", + "requires": { + "escodegen": "1.9.0" + } + }, + "string_decoder": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.0.3.tgz", + "integrity": "sha512-4AH6Z5fzNNBcH+6XDMfA/BTt87skxqJlO0lAh3Dker5zThcAxG6mKz+iGu308UKoPPQ8Dcqx/4JhujzltRa+hQ==", + "requires": { + "safe-buffer": "5.1.1" + } + }, + "through2": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.3.tgz", + "integrity": "sha1-AARWmzfHx0ujnEPzzteNGtlBQL4=", + "requires": { + "readable-stream": "2.3.3", + "xtend": "4.0.1" + } + } + } + }, + "regl-scatter2d": { + "version": "2.1.13", + "resolved": "https://registry.npmjs.org/regl-scatter2d/-/regl-scatter2d-2.1.13.tgz", + "integrity": "sha512-7JDIzlBcLerTf/sxZfY/82rFjQyQ3OWsoNbI4EkhahXEuvewsCeB/Wf+leOmEFBw0gg5j+rby76xKLQLx90NAA==", + "requires": { + "array-range": "1.0.1", + "binary-search-bounds": "2.0.4", + "bubleify": "1.1.0", + "clamp": "1.0.1", + "color-id": "1.1.0", + "color-normalize": "1.0.3", + "flatten-vertex-data": "1.0.0", + "glslify": "6.1.0", + "is-iexplorer": "1.0.0", + "object-assign": "4.1.1", + "pick-by-alias": "1.2.0", + "snap-points-2d": "3.2.0", + "to-float32": "1.0.0", + "update-diff": "1.1.0" + }, + "dependencies": { + "binary-search-bounds": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/binary-search-bounds/-/binary-search-bounds-2.0.4.tgz", + "integrity": "sha512-2hg5kgdKql5ClF2ErBcSx0U5bnl5hgS4v7wMnLFodyR47yMtj2w+UAZB+0CiqyHct2q543i7Bi4/aMIegorCCg==" + }, + "escodegen": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/escodegen/-/escodegen-1.9.0.tgz", + "integrity": "sha512-v0MYvNQ32bzwoG2OSFzWAkuahDQHK92JBN0pTAALJ4RIxEZe766QJPDR8Hqy7XNUy5K3fnVL76OqYAdc4TZEIw==", + "requires": { + "esprima": "3.1.3", + "estraverse": "4.2.0", + "esutils": "2.0.2", + "optionator": "0.8.2", + "source-map": "0.5.7" + } + }, + "esprima": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-3.1.3.tgz", + "integrity": "sha1-/cpRzuYTOJXjyI1TXOSdv/YqRjM=" + }, + "estraverse": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.2.0.tgz", + "integrity": "sha1-De4/7TH81GlhjOc0IJn8GvoL2xM=" + }, + "esutils": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.2.tgz", + "integrity": "sha1-Cr9PHKpbyx96nYrMbepPqqBLrJs=" + }, + "glslify": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/glslify/-/glslify-6.1.0.tgz", + "integrity": "sha1-zf/P0qZXFyISjT0TNWwTbebOl0I=", + "requires": { + "bl": "1.2.1", + "concat-stream": "1.6.0", + "duplexify": "3.5.3", + "falafel": "2.1.0", + "from2": "2.3.0", + "glsl-resolve": "0.0.1", + "glsl-token-whitespace-trim": "1.0.0", + "glslify-bundle": "5.0.0", + "glslify-deps": "1.3.0", + "minimist": "1.2.0", + "resolve": "1.4.0", + "stack-trace": "0.0.9", + "static-eval": "1.1.1", + "tape": "4.8.0", + "through2": "2.0.3", + "xtend": "4.0.1" + } + }, + "glslify-bundle": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/glslify-bundle/-/glslify-bundle-5.0.0.tgz", + "integrity": "sha1-AlKtoe+d8wtmAAbguyH9EwtIbkI=", + "requires": { + "glsl-inject-defines": "1.0.3", + "glsl-token-defines": "1.0.0", + "glsl-token-depth": "1.1.2", + "glsl-token-descope": "1.0.2", + "glsl-token-scope": "1.1.2", + "glsl-token-string": "1.0.1", + "glsl-token-whitespace-trim": "1.0.0", + "glsl-tokenizer": "2.1.2", + "murmurhash-js": "1.0.0", + "shallow-copy": "0.0.1" + } + }, + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=" + }, + "readable-stream": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.3.tgz", + "integrity": "sha512-m+qzzcn7KUxEmd1gMbchF+Y2eIUbieUaxkWtptyHywrX0rE8QEYqPC07Vuy4Wm32/xE16NcdBctb8S0Xe/5IeQ==", + "requires": { + "core-util-is": "1.0.2", + "inherits": "2.0.3", + "isarray": "1.0.0", + "process-nextick-args": "1.0.7", + "safe-buffer": "5.1.1", + "string_decoder": "1.0.3", + "util-deprecate": "1.0.2" + } + }, + "source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", + "optional": true + }, + "static-eval": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/static-eval/-/static-eval-1.1.1.tgz", + "integrity": "sha1-yoEwIQNUzxPZpyK8fpI3eEV7sZI=", + "requires": { + "escodegen": "1.9.0" + } + }, + "string_decoder": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.0.3.tgz", + "integrity": "sha512-4AH6Z5fzNNBcH+6XDMfA/BTt87skxqJlO0lAh3Dker5zThcAxG6mKz+iGu308UKoPPQ8Dcqx/4JhujzltRa+hQ==", + "requires": { + "safe-buffer": "5.1.1" + } + }, + "through2": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.3.tgz", + "integrity": "sha1-AARWmzfHx0ujnEPzzteNGtlBQL4=", + "requires": { + "readable-stream": "2.3.3", + "xtend": "4.0.1" + } + } + } + }, + "remove-trailing-separator": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/remove-trailing-separator/-/remove-trailing-separator-1.1.0.tgz", + "integrity": "sha1-wkvOKig62tW8P1jg1IJJuSN52O8=", + "dev": true + }, + "repeat-element": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/repeat-element/-/repeat-element-1.1.2.tgz", + "integrity": "sha1-7wiaF40Ug7quTZPrmLT55OEdmQo=", + "dev": true + }, + "repeat-string": { + "version": "1.6.1", + "resolved": "https://registry.npmjs.org/repeat-string/-/repeat-string-1.6.1.tgz", + "integrity": "sha1-jcrkcOHIirwtYA//Sndihtp15jc=" + }, + "request": { + "version": "2.83.0", + "resolved": "https://registry.npmjs.org/request/-/request-2.83.0.tgz", + "integrity": "sha512-lR3gD69osqm6EYLk9wB/G1W/laGWjzH90t1vEa2xuxHD5KUrSzp9pUSfTm+YC5Nxt2T8nMPEvKlhbQayU7bgFw==", + "requires": { + "aws-sign2": "0.7.0", + "aws4": "1.6.0", + "caseless": "0.12.0", + "combined-stream": "1.0.5", + "extend": "3.0.1", + "forever-agent": "0.6.1", + "form-data": "2.3.1", + "har-validator": "5.0.3", + "hawk": "6.0.2", + "http-signature": "1.2.0", + "is-typedarray": "1.0.0", + "isstream": "0.1.2", + "json-stringify-safe": "5.0.1", + "mime-types": "2.1.17", + "oauth-sign": "0.8.2", + "performance-now": "2.1.0", + "qs": "6.5.1", + "safe-buffer": "5.1.1", + "stringstream": "0.0.5", + "tough-cookie": "2.3.3", + "tunnel-agent": "0.6.0", + "uuid": "3.2.1" + } + }, + "require-directory": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", + "integrity": "sha1-jGStX9MNqxyXbiNE/+f3kqam30I=", + "dev": true + }, + "require-main-filename": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-1.0.1.tgz", + "integrity": "sha1-l/cXtp1IeE9fUmpsWqj/3aBVpNE=", + "dev": true + }, + "requires-port": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz", + "integrity": "sha1-kl0mAdOaxIXgkc8NpcbmlNw9yv8=" + }, + "resolve": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.4.0.tgz", + "integrity": "sha512-aW7sVKPufyHqOmyyLzg/J+8606v5nevBgaliIlV7nUpVMsDnoBGV/cbSLNjZAg9q0Cfd/+easKVKQ8vOu8fn1Q==", + "requires": { + "path-parse": "1.0.5" + } + }, + "resolve-protobuf-schema": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/resolve-protobuf-schema/-/resolve-protobuf-schema-2.0.0.tgz", + "integrity": "sha1-5nsGKmfwLRG9aIbnDv2niEB+D7Q=", + "requires": { + "protocol-buffers-schema": "2.2.0" + } + }, + "resolve-url": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/resolve-url/-/resolve-url-0.2.1.tgz", + "integrity": "sha1-LGN/53yJOv0qZj/iGqkIAGjiBSo=" + }, + "resumer": { + "version": "0.0.0", + "resolved": "https://registry.npmjs.org/resumer/-/resumer-0.0.0.tgz", + "integrity": "sha1-8ej0YeQGS6Oegq883CqMiT0HZ1k=", + "requires": { + "through": "2.3.8" + } + }, + "right-align": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/right-align/-/right-align-0.1.3.tgz", + "integrity": "sha1-YTObci/mo1FWiSENJOFMlhSGE+8=", + "requires": { + "align-text": "0.1.4" + } + }, + "right-now": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/right-now/-/right-now-1.0.0.tgz", + "integrity": "sha1-bolgne69fc2vja7Mmuo5z1haCRg=" + }, + "rimraf": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.2.tgz", + "integrity": "sha512-lreewLK/BlghmxtfH36YYVg1i8IAce4TI7oao75I1g245+6BctqTVQiBP3YUJ9C6DQOXJmkYR9X9fCLtCOJc5w==", + "dev": true, + "requires": { + "glob": "7.1.2" + } + }, + "ripemd160": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/ripemd160/-/ripemd160-2.0.1.tgz", + "integrity": "sha1-D0WEKVxTo2KK9+bXmsohzlfRxuc=", + "dev": true, + "requires": { + "hash-base": "2.0.2", + "inherits": "2.0.3" + } + }, + "robust-compress": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/robust-compress/-/robust-compress-1.0.0.tgz", + "integrity": "sha1-TPYsSzGNgwhRYBK7jBF1Lzkymxs=" + }, + "robust-determinant": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/robust-determinant/-/robust-determinant-1.1.0.tgz", + "integrity": "sha1-jsrnm3nKqz509t6+IjflORon6cc=", + "requires": { + "robust-compress": "1.0.0", + "robust-scale": "1.0.2", + "robust-sum": "1.0.0", + "two-product": "1.0.2" + } + }, + "robust-dot-product": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/robust-dot-product/-/robust-dot-product-1.0.0.tgz", + "integrity": "sha1-yboBeL0sMEv9cl9Y6Inx2UYARVM=", + "requires": { + "robust-sum": "1.0.0", + "two-product": "1.0.2" + } + }, + "robust-in-sphere": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/robust-in-sphere/-/robust-in-sphere-1.1.3.tgz", + "integrity": "sha1-HFiD0WpOkjkpR27zSBmFe/Kpz3U=", + "requires": { + "robust-scale": "1.0.2", + "robust-subtract": "1.0.0", + "robust-sum": "1.0.0", + "two-product": "1.0.2" + } + }, + "robust-linear-solve": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/robust-linear-solve/-/robust-linear-solve-1.0.0.tgz", + "integrity": "sha1-DNasUEBpGm8qo81jEdcokFyjofE=", + "requires": { + "robust-determinant": "1.1.0" + } + }, + "robust-orientation": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/robust-orientation/-/robust-orientation-1.1.3.tgz", + "integrity": "sha1-2v9bANO+TmByLw6cAVbvln8cIEk=", + "requires": { + "robust-scale": "1.0.2", + "robust-subtract": "1.0.0", + "robust-sum": "1.0.0", + "two-product": "1.0.2" + } + }, + "robust-product": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/robust-product/-/robust-product-1.0.0.tgz", + "integrity": "sha1-aFJQAHzbunzx3nW/9tKScBEJir4=", + "requires": { + "robust-scale": "1.0.2", + "robust-sum": "1.0.0" + } + }, + "robust-scale": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/robust-scale/-/robust-scale-1.0.2.tgz", + "integrity": "sha1-d1Ey7QlULQKOWLLMecBikLz3jDI=", + "requires": { + "two-product": "1.0.2", + "two-sum": "1.0.0" + } + }, + "robust-segment-intersect": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/robust-segment-intersect/-/robust-segment-intersect-1.0.1.tgz", + "integrity": "sha1-MlK2oPwboUreaRXMvgnLzpqrHBw=", + "requires": { + "robust-orientation": "1.1.3" + } + }, + "robust-subtract": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/robust-subtract/-/robust-subtract-1.0.0.tgz", + "integrity": "sha1-4LFk4e2LpOOl3aRaEgODSNvtPpo=" + }, + "robust-sum": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/robust-sum/-/robust-sum-1.0.0.tgz", + "integrity": "sha1-FmRuUlKStNJdgnV6KGlV4Lv6U9k=" + }, + "rw": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/rw/-/rw-0.1.4.tgz", + "integrity": "sha1-SQPL2AJIrg7eaFv1j9I2p6mymj4=" + }, + "safe-buffer": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.1.tgz", + "integrity": "sha512-kKvNJn6Mm93gAczWVJg7wH+wGYWNrDHdWvpUmHyEsgCtIwwo3bqPtV4tR5tuPaUhTOo/kvhVwd8XwwOllGYkbg==" + }, + "sane-topojson": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/sane-topojson/-/sane-topojson-2.0.0.tgz", + "integrity": "sha1-QOJXNqKMTM6qojP0W7hjc6J4W4Q=" + }, + "semver": { + "version": "5.4.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.4.1.tgz", + "integrity": "sha512-WfG/X9+oATh81XtllIo/I8gOiY9EXRdv1cQdyykeXK17YcUW3EXUAi2To4pcH6nZtJPr7ZOpM5OMyWJZm+8Rsg==", + "dev": true + }, + "set-blocking": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", + "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=", + "dev": true + }, + "set-immediate-shim": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/set-immediate-shim/-/set-immediate-shim-1.0.1.tgz", + "integrity": "sha1-SysbJ+uAip+NzEgaWOXlb1mfP2E=", + "dev": true + }, + "setimmediate": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/setimmediate/-/setimmediate-1.0.5.tgz", + "integrity": "sha1-KQy7Iy4waULX1+qbg3Mqt4VvgoU=", + "dev": true + }, + "sha.js": { + "version": "2.4.9", + "resolved": "https://registry.npmjs.org/sha.js/-/sha.js-2.4.9.tgz", + "integrity": "sha512-G8zektVqbiPHrylgew9Zg1VRB1L/DtXNUVAM6q4QLy8NE3qtHlFXTf8VLL4k1Yl6c7NMjtZUTdXV+X44nFaT6A==", + "dev": true, + "requires": { + "inherits": "2.0.3", + "safe-buffer": "5.1.1" + } + }, + "shallow-copy": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/shallow-copy/-/shallow-copy-0.0.1.tgz", + "integrity": "sha1-QV9CcC1z2BAzApLMXuhurhoRoXA=" + }, + "shebang-command": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-1.2.0.tgz", + "integrity": "sha1-RKrGW2lbAzmJaMOfNj/uXer98eo=", + "dev": true, + "requires": { + "shebang-regex": "1.0.0" + } + }, + "shebang-regex": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-1.0.0.tgz", + "integrity": "sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM=", + "dev": true + }, + "shelf-pack": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/shelf-pack/-/shelf-pack-1.1.0.tgz", + "integrity": "sha1-tGea/dAK1o39m70rWj6BkpOnTYI=" + }, + "signal-exit": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.2.tgz", + "integrity": "sha1-tf3AjxKH6hF4Yo5BXiUTK3NkbG0=", + "dev": true + }, + "signum": { + "version": "0.0.0", + "resolved": "https://registry.npmjs.org/signum/-/signum-0.0.0.tgz", + "integrity": "sha1-q1UbEAM1EHCnBHg/GgnF52kfnPY=" + }, + "simplicial-complex": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/simplicial-complex/-/simplicial-complex-1.0.0.tgz", + "integrity": "sha1-bDOk7Wn81Nkbe8rdOzC2NoPq4kE=", + "requires": { + "bit-twiddle": "1.0.2", + "union-find": "1.0.2" + } + }, + "simplicial-complex-boundary": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/simplicial-complex-boundary/-/simplicial-complex-boundary-1.0.1.tgz", + "integrity": "sha1-csn/HiTeqjdMm7L6DL8MCB6++BU=", + "requires": { + "boundary-cells": "2.0.1", + "reduce-simplicial-complex": "1.0.0" + } + }, + "simplicial-complex-contour": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/simplicial-complex-contour/-/simplicial-complex-contour-1.0.2.tgz", + "integrity": "sha1-iQqsrChDZTQBEFRc8mKaJuBL+dE=", + "requires": { + "marching-simplex-table": "1.0.0", + "ndarray": "1.0.18", + "ndarray-sort": "1.0.1", + "typedarray-pool": "1.1.0" + } + }, + "simplify-planar-graph": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/simplify-planar-graph/-/simplify-planar-graph-2.0.1.tgz", + "integrity": "sha1-vIWJNyXzLo+oriVoE5hEbSy892Y=", + "requires": { + "robust-orientation": "1.1.3", + "simplicial-complex": "0.3.3" + }, + "dependencies": { + "bit-twiddle": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/bit-twiddle/-/bit-twiddle-0.0.2.tgz", + "integrity": "sha1-wurruVKjuUrMFASX4c3NLxoz9Y4=" + }, + "simplicial-complex": { + "version": "0.3.3", + "resolved": "https://registry.npmjs.org/simplicial-complex/-/simplicial-complex-0.3.3.tgz", + "integrity": "sha1-TDDK1X+eRXKd2PMGyHU1efRr6Z4=", + "requires": { + "bit-twiddle": "0.0.2", + "union-find": "0.0.4" + } + }, + "union-find": { + "version": "0.0.4", + "resolved": "https://registry.npmjs.org/union-find/-/union-find-0.0.4.tgz", + "integrity": "sha1-uFSzMBYZva0USwAUx4+W6sDS8PY=" + } + } + }, + "slab-decomposition": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/slab-decomposition/-/slab-decomposition-1.0.2.tgz", + "integrity": "sha1-He1WdU1AixBznxRRA9/GGAf2UTQ=", + "requires": { + "binary-search-bounds": "1.0.0", + "functional-red-black-tree": "1.0.1", + "robust-orientation": "1.1.3" + } + }, + "slash": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-1.0.0.tgz", + "integrity": "sha1-xB8vbDn8FtHNF61LXYlhFK5HDVU=", + "dev": true + }, + "snap-points-2d": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/snap-points-2d/-/snap-points-2d-3.2.0.tgz", + "integrity": "sha1-DhniKjoOlrziHN9cfx1+1blnRfA=", + "requires": { + "array-bounds": "1.0.1" + } + }, + "sntp": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/sntp/-/sntp-2.1.0.tgz", + "integrity": "sha512-FL1b58BDrqS3A11lJ0zEdnJ3UOKqVxawAkF3k7F0CVN7VQ34aZrV+G8BZ1WC9ZL7NyrwsW0oviwsWDgRuVYtJg==", + "requires": { + "hoek": "4.2.0" + } + }, + "sort-asc": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/sort-asc/-/sort-asc-0.1.0.tgz", + "integrity": "sha1-q3md9h/HPqCVbHnEtTHtHp53J+k=" + }, + "sort-desc": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/sort-desc/-/sort-desc-0.1.1.tgz", + "integrity": "sha1-GYuMDN6wlcRjNBhh45JdTuNZqe4=" + }, + "sort-object": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/sort-object/-/sort-object-0.3.2.tgz", + "integrity": "sha1-mODRme3kDgfGGoRAPGHWw7KQ+eI=", + "requires": { + "sort-asc": "0.1.0", + "sort-desc": "0.1.1" + } + }, + "source-list-map": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/source-list-map/-/source-list-map-2.0.0.tgz", + "integrity": "sha512-I2UmuJSRr/T8jisiROLU3A3ltr+swpniSmNPI4Ml3ZCX6tVnDsuZzK7F2hl5jTqbZBWCEKlj5HRQiPExXLgE8A==", + "dev": true + }, + "source-map": { + "version": "0.1.43", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.1.43.tgz", + "integrity": "sha1-wkvBRspRfBRx9drL4lcbK3+eM0Y=", + "requires": { + "amdefine": "1.0.1" + } + }, + "spdx-correct": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-1.0.2.tgz", + "integrity": "sha1-SzBz2TP/UfORLwOsVRlJikFQ20A=", + "dev": true, + "requires": { + "spdx-license-ids": "1.2.2" + } + }, + "spdx-expression-parse": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-1.0.4.tgz", + "integrity": "sha1-m98vIOH0DtRH++JzJmGR/O1RYmw=", + "dev": true + }, + "spdx-license-ids": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-1.2.2.tgz", + "integrity": "sha1-yd96NCRZSt5r0RkA1ZZpbcBrrFc=", + "dev": true + }, + "split-polygon": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/split-polygon/-/split-polygon-1.0.0.tgz", + "integrity": "sha1-DqzIoTanaxKj2VJW6n2kXbDC0kc=", + "requires": { + "robust-dot-product": "1.0.0", + "robust-sum": "1.0.0" + } + }, + "sprintf-js": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.1.1.tgz", + "integrity": "sha1-Nr54Mgr+WAH2zqPueLblqrlA6gw=" + }, + "sshpk": { + "version": "1.13.1", + "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.13.1.tgz", + "integrity": "sha1-US322mKHFEMW3EwY/hzx2UBzm+M=", + "requires": { + "asn1": "0.2.3", + "assert-plus": "1.0.0", + "bcrypt-pbkdf": "1.0.1", + "dashdash": "1.14.1", + "ecc-jsbn": "0.1.1", + "getpass": "0.1.7", + "jsbn": "0.1.1", + "tweetnacl": "0.14.5" + } + }, + "stack-trace": { + "version": "0.0.9", + "resolved": "https://registry.npmjs.org/stack-trace/-/stack-trace-0.0.9.tgz", + "integrity": "sha1-qPbq7KkGdMMz58Q5U/J1tFFRBpU=" + }, + "static-eval": { + "version": "0.2.4", + "resolved": "https://registry.npmjs.org/static-eval/-/static-eval-0.2.4.tgz", + "integrity": "sha1-t9NNg4k3uWn5ZBygfUj47eJj6ns=", + "requires": { + "escodegen": "0.0.28" + }, + "dependencies": { + "escodegen": { + "version": "0.0.28", + "resolved": "https://registry.npmjs.org/escodegen/-/escodegen-0.0.28.tgz", + "integrity": "sha1-Dk/xcV8yh3XWyrUaxEpAbNer/9M=", + "requires": { + "esprima": "1.0.4", + "estraverse": "1.3.2", + "source-map": "0.1.43" + } + }, + "esprima": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-1.0.4.tgz", + "integrity": "sha1-n1V+CPw7TSbs6d00+Pv0drYlha0=" + }, + "estraverse": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-1.3.2.tgz", + "integrity": "sha1-N8K4k+8T1yPydth41g2FNRUqbEI=" + } + } + }, + "static-module": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/static-module/-/static-module-1.5.0.tgz", + "integrity": "sha1-J9qYg8QajNCSNvhC8MHrxu32PYY=", + "requires": { + "concat-stream": "1.6.0", + "duplexer2": "0.0.2", + "escodegen": "1.3.3", + "falafel": "2.1.0", + "has": "1.0.1", + "object-inspect": "0.4.0", + "quote-stream": "0.0.0", + "readable-stream": "1.0.34", + "shallow-copy": "0.0.1", + "static-eval": "0.2.4", + "through2": "0.4.2" + }, + "dependencies": { + "object-inspect": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-0.4.0.tgz", + "integrity": "sha1-9RV8EWwUVbJDsG7pdwM5LFrYn+w=" + }, + "object-keys": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-0.4.0.tgz", + "integrity": "sha1-KKaq50KN0sOpLz2V8hM13SBOAzY=" + }, + "through2": { + "version": "0.4.2", + "resolved": "https://registry.npmjs.org/through2/-/through2-0.4.2.tgz", + "integrity": "sha1-2/WGYDEVHsg1K7bE22SiKSqEC5s=", + "requires": { + "readable-stream": "1.0.34", + "xtend": "2.1.2" + } + }, + "xtend": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-2.1.2.tgz", + "integrity": "sha1-bv7MKk2tjmlixJAbM3znuoe10os=", + "requires": { + "object-keys": "0.4.0" + } + } + } + }, + "stream-browserify": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/stream-browserify/-/stream-browserify-2.0.1.tgz", + "integrity": "sha1-ZiZu5fm9uZQKTkUUyvtDu3Hlyds=", + "dev": true, + "requires": { + "inherits": "2.0.3", + "readable-stream": "2.3.3" + }, + "dependencies": { + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", + "dev": true + }, + "readable-stream": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.3.tgz", + "integrity": "sha512-m+qzzcn7KUxEmd1gMbchF+Y2eIUbieUaxkWtptyHywrX0rE8QEYqPC07Vuy4Wm32/xE16NcdBctb8S0Xe/5IeQ==", + "dev": true, + "requires": { + "core-util-is": "1.0.2", + "inherits": "2.0.3", + "isarray": "1.0.0", + "process-nextick-args": "1.0.7", + "safe-buffer": "5.1.1", + "string_decoder": "1.0.3", + "util-deprecate": "1.0.2" + } + }, + "string_decoder": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.0.3.tgz", + "integrity": "sha512-4AH6Z5fzNNBcH+6XDMfA/BTt87skxqJlO0lAh3Dker5zThcAxG6mKz+iGu308UKoPPQ8Dcqx/4JhujzltRa+hQ==", + "dev": true, + "requires": { + "safe-buffer": "5.1.1" + } + } + } + }, + "stream-http": { + "version": "2.7.2", + "resolved": "https://registry.npmjs.org/stream-http/-/stream-http-2.7.2.tgz", + "integrity": "sha512-c0yTD2rbQzXtSsFSVhtpvY/vS6u066PcXOX9kBB3mSO76RiUQzL340uJkGBWnlBg4/HZzqiUXtaVA7wcRcJgEw==", + "dev": true, + "requires": { + "builtin-status-codes": "3.0.0", + "inherits": "2.0.3", + "readable-stream": "2.3.3", + "to-arraybuffer": "1.0.1", + "xtend": "4.0.1" + }, + "dependencies": { + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", + "dev": true + }, + "readable-stream": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.3.tgz", + "integrity": "sha512-m+qzzcn7KUxEmd1gMbchF+Y2eIUbieUaxkWtptyHywrX0rE8QEYqPC07Vuy4Wm32/xE16NcdBctb8S0Xe/5IeQ==", + "dev": true, + "requires": { + "core-util-is": "1.0.2", + "inherits": "2.0.3", + "isarray": "1.0.0", + "process-nextick-args": "1.0.7", + "safe-buffer": "5.1.1", + "string_decoder": "1.0.3", + "util-deprecate": "1.0.2" + } + }, + "string_decoder": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.0.3.tgz", + "integrity": "sha512-4AH6Z5fzNNBcH+6XDMfA/BTt87skxqJlO0lAh3Dker5zThcAxG6mKz+iGu308UKoPPQ8Dcqx/4JhujzltRa+hQ==", + "dev": true, + "requires": { + "safe-buffer": "5.1.1" + } + } + } + }, + "stream-shift": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/stream-shift/-/stream-shift-1.0.0.tgz", + "integrity": "sha1-1cdSgl5TZ+eG944Y5EXqIjoVWVI=" + }, + "string-width": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", + "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==", + "dev": true, + "requires": { + "is-fullwidth-code-point": "2.0.0", + "strip-ansi": "4.0.0" + }, + "dependencies": { + "ansi-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", + "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", + "dev": true + }, + "is-fullwidth-code-point": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", + "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", + "dev": true + }, + "strip-ansi": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", + "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", + "dev": true, + "requires": { + "ansi-regex": "3.0.0" + } + } + } + }, + "string.prototype.trim": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/string.prototype.trim/-/string.prototype.trim-1.1.2.tgz", + "integrity": "sha1-0E3iyJ4Tf019IG8Ia17S+ua+jOo=", + "requires": { + "define-properties": "1.1.2", + "es-abstract": "1.10.0", + "function-bind": "1.1.1" + } + }, + "string_decoder": { + "version": "0.10.31", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", + "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=" + }, + "stringstream": { + "version": "0.0.5", + "resolved": "https://registry.npmjs.org/stringstream/-/stringstream-0.0.5.tgz", + "integrity": "sha1-TkhM1N5aC7vuGORjB3EKioFiGHg=" + }, + "strip-ansi": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-0.1.1.tgz", + "integrity": "sha1-OeipjQRNFQZgq+SmgIrPcLt7yZE=" + }, + "strip-bom": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", + "integrity": "sha1-IzTBjpx1n3vdVv3vfprj1YjmjtM=", + "dev": true + }, + "strip-eof": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/strip-eof/-/strip-eof-1.0.0.tgz", + "integrity": "sha1-u0P/VZim6wXYm1n80SnJgzE2Br8=", + "dev": true + }, + "strongly-connected-components": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/strongly-connected-components/-/strongly-connected-components-1.0.1.tgz", + "integrity": "sha1-CSDitN9nyOrulsa2I0/inoc9upk=" + }, + "supercluster": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/supercluster/-/supercluster-2.3.0.tgz", + "integrity": "sha1-h6tWCBu+qaHXJN9TUe6ejDry9Is=", + "requires": { + "kdbush": "1.0.1" + } + }, + "superscript-text": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/superscript-text/-/superscript-text-1.0.0.tgz", + "integrity": "sha1-58snUlZzYN9QvrBhDOjfPXHY39g=" + }, + "supports-color": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-4.5.0.tgz", + "integrity": "sha1-vnoN5ITexcXN34s9WRJQRJEvY1s=", + "requires": { + "has-flag": "2.0.0" + } + }, + "surface-nets": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/surface-nets/-/surface-nets-1.0.2.tgz", + "integrity": "sha1-5DPIy7qUpydMb0yZVStGG/H8eks=", + "requires": { + "ndarray-extract-contour": "1.0.1", + "triangulate-hypercube": "1.0.1", + "zero-crossings": "1.0.1" + } + }, + "svg-arc-to-cubic-bezier": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/svg-arc-to-cubic-bezier/-/svg-arc-to-cubic-bezier-3.0.0.tgz", + "integrity": "sha1-iFaaoYqLrWOEA7+taB97Wp8vZoU=" + }, + "svg-path-bounds": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/svg-path-bounds/-/svg-path-bounds-1.0.1.tgz", + "integrity": "sha1-v0WLeDcmv1NDG0Yz8nkvYHSNn3Q=", + "requires": { + "abs-svg-path": "0.1.1", + "is-svg-path": "1.0.2", + "normalize-svg-path": "1.0.1", + "parse-svg-path": "0.1.2" + }, + "dependencies": { + "normalize-svg-path": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/normalize-svg-path/-/normalize-svg-path-1.0.1.tgz", + "integrity": "sha1-b3Ka1rcLtMpO/y/ksQdInv4dVv4=", + "requires": { + "svg-arc-to-cubic-bezier": "3.0.0" + } + } + } + }, + "svg-path-sdf": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/svg-path-sdf/-/svg-path-sdf-1.1.1.tgz", + "integrity": "sha1-oqlHJb/mw8Gsn6UmYCc/P18JMuU=", + "requires": { + "bitmap-sdf": "1.0.3", + "draw-svg-path": "1.0.0", + "is-svg-path": "1.0.2", + "parse-svg-path": "0.1.2", + "svg-path-bounds": "1.0.1" + } + }, + "tapable": { + "version": "0.2.8", + "resolved": "https://registry.npmjs.org/tapable/-/tapable-0.2.8.tgz", + "integrity": "sha1-mTcqXJmb8t8WCvwNdL7U9HlIzSI=", + "dev": true + }, + "tape": { + "version": "4.8.0", + "resolved": "https://registry.npmjs.org/tape/-/tape-4.8.0.tgz", + "integrity": "sha512-TWILfEnvO7I8mFe35d98F6T5fbLaEtbFTG/lxWvid8qDfFTxt19EBijWmB4j3+Hoh5TfHE2faWs73ua+EphuBA==", + "requires": { + "deep-equal": "1.0.1", + "defined": "1.0.0", + "for-each": "0.3.2", + "function-bind": "1.1.1", + "glob": "7.1.2", + "has": "1.0.1", + "inherits": "2.0.3", + "minimist": "1.2.0", + "object-inspect": "1.3.0", + "resolve": "1.4.0", + "resumer": "0.0.0", + "string.prototype.trim": "1.1.2", + "through": "2.3.8" + } + }, + "text-cache": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/text-cache/-/text-cache-4.1.0.tgz", + "integrity": "sha1-fFgJDoWsCRD5dt9M/Izoqg6lh2Y=", + "requires": { + "vectorize-text": "3.0.2" + } + }, + "through": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", + "integrity": "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=" + }, + "through2": { + "version": "0.6.5", + "resolved": "https://registry.npmjs.org/through2/-/through2-0.6.5.tgz", + "integrity": "sha1-QaucZ7KdVyCQcUEOHXp6lozTrUg=", + "requires": { + "readable-stream": "1.0.34", + "xtend": "4.0.1" + } + }, + "timers-browserify": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/timers-browserify/-/timers-browserify-2.0.4.tgz", + "integrity": "sha512-uZYhyU3EX8O7HQP+J9fTVYwsq90Vr68xPEFo7yrVImIxYvHgukBEgOB/SgGoorWVTzGM/3Z+wUNnboA4M8jWrg==", + "dev": true, + "requires": { + "setimmediate": "1.0.5" + } + }, + "tiny-sdf": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/tiny-sdf/-/tiny-sdf-1.0.2.tgz", + "integrity": "sha1-KOdphcRMTlhMS2fY7N2bM6HKwow=" + }, + "tinycolor2": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/tinycolor2/-/tinycolor2-1.4.1.tgz", + "integrity": "sha1-9PrTM0R7wLB9TcjpIJ2POaisd+g=" + }, + "to-arraybuffer": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/to-arraybuffer/-/to-arraybuffer-1.0.1.tgz", + "integrity": "sha1-fSKbH8xjfkZsoIEYCDanqr/4P0M=", + "dev": true + }, + "to-float32": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/to-float32/-/to-float32-1.0.0.tgz", + "integrity": "sha512-AtYAqiHS1q+IqVfZOExaRC72mUZuMZP7yU1xsR07y0SLLEvPf68R+xGfya3eY4CR7jxT/zQt3wM8w4mGq/mPXA==" + }, + "to-px": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/to-px/-/to-px-1.0.1.tgz", + "integrity": "sha1-W7rtXl1PdkRbzJA8KTojB90yRkY=", + "requires": { + "parse-unit": "1.0.1" + } + }, + "to-utf8": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/to-utf8/-/to-utf8-0.0.1.tgz", + "integrity": "sha1-0Xrqcv8vujm55DYBvns/9y4ImFI=" + }, + "topojson-client": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/topojson-client/-/topojson-client-2.1.0.tgz", + "integrity": "sha1-/59784mRGF4LQoTCsGroNPDqxsg=", + "requires": { + "commander": "2.1.0" + } + }, + "tough-cookie": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.3.3.tgz", + "integrity": "sha1-C2GKVWW23qkL80JdBNVe3EdadWE=", + "requires": { + "punycode": "1.4.1" + } + }, + "triangulate-hypercube": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/triangulate-hypercube/-/triangulate-hypercube-1.0.1.tgz", + "integrity": "sha1-2Acdsuv8/VHzCNC88qXEils20Tc=", + "requires": { + "gamma": "0.1.0", + "permutation-parity": "1.0.0", + "permutation-rank": "1.0.0" + } + }, + "triangulate-polyline": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/triangulate-polyline/-/triangulate-polyline-1.0.3.tgz", + "integrity": "sha1-v4uod6hQVBA/65+lphtOjXAXgU0=", + "requires": { + "cdt2d": "1.0.0" + } + }, + "tty-browserify": { + "version": "0.0.0", + "resolved": "https://registry.npmjs.org/tty-browserify/-/tty-browserify-0.0.0.tgz", + "integrity": "sha1-oVe6QC2iTpv5V/mqadUk7tQpAaY=", + "dev": true + }, + "tunnel-agent": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", + "integrity": "sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0=", + "requires": { + "safe-buffer": "5.1.1" + } + }, + "turntable-camera-controller": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/turntable-camera-controller/-/turntable-camera-controller-3.0.1.tgz", + "integrity": "sha1-jb0/4AVQGRxlFky4iJcQSVeK/Zk=", + "requires": { + "filtered-vector": "1.2.4", + "gl-mat4": "1.1.4", + "gl-vec3": "1.0.3" + } + }, + "tweetnacl": { + "version": "0.14.5", + "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz", + "integrity": "sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q=", + "optional": true + }, + "two-product": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/two-product/-/two-product-1.0.2.tgz", + "integrity": "sha1-Z9ldSyV6kh4stL16+VEfkIhSLqo=" + }, + "two-sum": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/two-sum/-/two-sum-1.0.0.tgz", + "integrity": "sha1-MdPzIjnk9zHsqd+RVeKyl/AIq2Q=" + }, + "type-check": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.3.2.tgz", + "integrity": "sha1-WITKtRLPHTVeP7eE8wgEsrUg23I=", + "requires": { + "prelude-ls": "1.1.2" + } + }, + "typedarray": { + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz", + "integrity": "sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=" + }, + "typedarray-pool": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/typedarray-pool/-/typedarray-pool-1.1.0.tgz", + "integrity": "sha1-0RT0hIAUifU+yrXoCIqiMET0mNk=", + "requires": { + "bit-twiddle": "1.0.2", + "dup": "1.0.0" + } + }, + "uglify-js": { + "version": "2.8.29", + "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-2.8.29.tgz", + "integrity": "sha1-KcVzMUgFe7Th913zW3qcty5qWd0=", + "requires": { + "source-map": "0.5.7", + "uglify-to-browserify": "1.0.2", + "yargs": "3.10.0" + }, + "dependencies": { + "source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=" + } + } + }, + "uglify-to-browserify": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/uglify-to-browserify/-/uglify-to-browserify-1.0.2.tgz", + "integrity": "sha1-bgkk1r2mta/jSeOabWMoUKD4grc=", + "optional": true + }, + "uglifyjs-webpack-plugin": { + "version": "0.4.6", + "resolved": "https://registry.npmjs.org/uglifyjs-webpack-plugin/-/uglifyjs-webpack-plugin-0.4.6.tgz", + "integrity": "sha1-uVH0q7a9YX5m9j64kUmOORdj4wk=", + "dev": true, + "requires": { + "source-map": "0.5.7", + "uglify-js": "2.8.29", + "webpack-sources": "1.1.0" + }, + "dependencies": { + "source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", + "dev": true + } + } + }, + "unassert": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/unassert/-/unassert-1.5.1.tgz", + "integrity": "sha1-y8iOw4dBfFpeTALTzQe+mL11/3Y=", + "requires": { + "acorn": "4.0.13", + "call-matcher": "1.0.1", + "deep-equal": "1.0.1", + "espurify": "1.7.0", + "estraverse": "4.2.0", + "esutils": "2.0.2", + "object-assign": "4.1.1" + }, + "dependencies": { + "acorn": { + "version": "4.0.13", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-4.0.13.tgz", + "integrity": "sha1-EFSVrlNh1pe9GVyCUZLhrX8lN4c=" + }, + "estraverse": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.2.0.tgz", + "integrity": "sha1-De4/7TH81GlhjOc0IJn8GvoL2xM=" + }, + "esutils": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.2.tgz", + "integrity": "sha1-Cr9PHKpbyx96nYrMbepPqqBLrJs=" + } + } + }, + "unassertify": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/unassertify/-/unassertify-2.1.0.tgz", + "integrity": "sha512-CB3C3vbOwrZydRuGdU8H421r4/qhM8RLuEOo3G+wEFf7kDP4TR+7oDuj1yOik5pUzXMaJmzxICM7akupP1AlJw==", + "requires": { + "acorn": "5.2.1", + "convert-source-map": "1.5.1", + "escodegen": "1.9.0", + "multi-stage-sourcemap": "0.2.1", + "through": "2.3.8", + "unassert": "1.5.1" + }, + "dependencies": { + "escodegen": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/escodegen/-/escodegen-1.9.0.tgz", + "integrity": "sha512-v0MYvNQ32bzwoG2OSFzWAkuahDQHK92JBN0pTAALJ4RIxEZe766QJPDR8Hqy7XNUy5K3fnVL76OqYAdc4TZEIw==", + "requires": { + "esprima": "3.1.3", + "estraverse": "4.2.0", + "esutils": "2.0.2", + "optionator": "0.8.2", + "source-map": "0.5.7" + } + }, + "esprima": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-3.1.3.tgz", + "integrity": "sha1-/cpRzuYTOJXjyI1TXOSdv/YqRjM=" + }, + "estraverse": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.2.0.tgz", + "integrity": "sha1-De4/7TH81GlhjOc0IJn8GvoL2xM=" + }, + "esutils": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.2.tgz", + "integrity": "sha1-Cr9PHKpbyx96nYrMbepPqqBLrJs=" + }, + "source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", + "optional": true + } + } + }, + "underscore": { + "version": "1.8.3", + "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.8.3.tgz", + "integrity": "sha1-Tz+1OxBuYJf8+ctBCfKl6b36UCI=" + }, + "union-find": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/union-find/-/union-find-1.0.2.tgz", + "integrity": "sha1-KSusQV5q06iVNdI3AQ20pTYoTlg=" + }, + "uniq": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/uniq/-/uniq-1.0.1.tgz", + "integrity": "sha1-sxxa6CVIRKOoKBVBzisEuGWnNP8=" + }, + "unitbezier": { + "version": "0.0.0", + "resolved": "https://registry.npmjs.org/unitbezier/-/unitbezier-0.0.0.tgz", + "integrity": "sha1-M79/XXKExTUL/Fx/dw+6dUnFSl4=" + }, + "update-diff": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/update-diff/-/update-diff-1.1.0.tgz", + "integrity": "sha1-9RAYLYHugZ+4LDprIrYrve2ngI8=" + }, + "url": { + "version": "0.11.0", + "resolved": "https://registry.npmjs.org/url/-/url-0.11.0.tgz", + "integrity": "sha1-ODjpfPxgUh63PFJajlW/3Z4uKPE=", + "dev": true, + "requires": { + "punycode": "1.3.2", + "querystring": "0.2.0" + }, + "dependencies": { + "punycode": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.3.2.tgz", + "integrity": "sha1-llOgNvt8HuQjQvIyXM7v6jkmxI0=", + "dev": true + } + } + }, + "url-parse": { + "version": "1.1.9", + "resolved": "https://registry.npmjs.org/url-parse/-/url-parse-1.1.9.tgz", + "integrity": "sha1-xn8dd11R8KGJEd17P/rSe7nlvRk=", + "requires": { + "querystringify": "1.0.0", + "requires-port": "1.0.0" + } + }, + "util": { + "version": "0.10.3", + "resolved": "https://registry.npmjs.org/util/-/util-0.10.3.tgz", + "integrity": "sha1-evsa/lCAUkZInj23/g7TeTNqwPk=", + "dev": true, + "requires": { + "inherits": "2.0.1" + }, + "dependencies": { + "inherits": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz", + "integrity": "sha1-sX0I0ya0Qj5Wjv9xn5GwscvfafE=", + "dev": true + } + } + }, + "util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=" + }, + "uuid": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.2.1.tgz", + "integrity": "sha512-jZnMwlb9Iku/O3smGWvZhauCf6cvvpKi4BKRiliS3cxnI+Gz9j5MEpTz2UFuXiKPJocb7gnsLHwiS05ige5BEA==" + }, + "validate-npm-package-license": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.1.tgz", + "integrity": "sha1-KAS6vnEq0zeUWaz74kdGqywwP7w=", + "dev": true, + "requires": { + "spdx-correct": "1.0.2", + "spdx-expression-parse": "1.0.4" + } + }, + "vector-tile": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/vector-tile/-/vector-tile-1.3.0.tgz", + "integrity": "sha1-BtUWqDsGPwTILvU5zxuxrr62lrQ=", + "requires": { + "point-geometry": "0.0.0" + } + }, + "vectorize-text": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/vectorize-text/-/vectorize-text-3.0.2.tgz", + "integrity": "sha1-BasWMOQJ83eWTiuSBbLVWakvYNg=", + "requires": { + "cdt2d": "1.0.0", + "clean-pslg": "1.1.2", + "ndarray": "1.0.18", + "planar-graph-to-polyline": "1.0.5", + "simplify-planar-graph": "2.0.1", + "surface-nets": "1.0.2", + "triangulate-polyline": "1.0.3" + } + }, + "verror": { + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/verror/-/verror-1.10.0.tgz", + "integrity": "sha1-OhBcoXBTr1XW4nDB+CiGguGNpAA=", + "requires": { + "assert-plus": "1.0.0", + "core-util-is": "1.0.2", + "extsprintf": "1.3.0" + } + }, + "vlq": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/vlq/-/vlq-0.2.3.tgz", + "integrity": "sha512-DRibZL6DsNhIgYQ+wNdWDL2SL3bKPlVrRiBqV5yuMm++op8W4kGFtaQfCs4KEJn0wBZcHVHJ3eoywX8983k1ow==" + }, + "vm-browserify": { + "version": "0.0.4", + "resolved": "https://registry.npmjs.org/vm-browserify/-/vm-browserify-0.0.4.tgz", + "integrity": "sha1-XX6kW7755Kb/ZflUOOCofDV9WnM=", + "dev": true, + "requires": { + "indexof": "0.0.1" + } + }, + "vt-pbf": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/vt-pbf/-/vt-pbf-2.1.4.tgz", + "integrity": "sha1-td98P5cGFW4LmIGpncsFY1dAtSI=", + "requires": { + "pbf": "1.3.7", + "point-geometry": "0.0.0", + "vector-tile": "1.3.0" + } + }, + "watchpack": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-1.4.0.tgz", + "integrity": "sha1-ShRyvLuVK9Cpu0A2gB+VTfs5+qw=", + "dev": true, + "requires": { + "async": "2.6.0", + "chokidar": "1.7.0", + "graceful-fs": "4.1.11" + } + }, + "weak-map": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/weak-map/-/weak-map-1.0.5.tgz", + "integrity": "sha1-eWkVhNmGB/UHC9O3CkDmuyLkAes=" + }, + "weakmap-shim": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/weakmap-shim/-/weakmap-shim-1.1.1.tgz", + "integrity": "sha1-1lr9eEEJshZuAP9XHDMVDsKkC0k=" + }, + "webgl-context": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/webgl-context/-/webgl-context-2.2.0.tgz", + "integrity": "sha1-jzfXJXz23xzQpJ5qextyG5TMhqA=", + "requires": { + "get-canvas-context": "1.0.2" + } + }, + "webpack": { + "version": "3.10.0", + "resolved": "https://registry.npmjs.org/webpack/-/webpack-3.10.0.tgz", + "integrity": "sha512-fxxKXoicjdXNUMY7LIdY89tkJJJ0m1Oo8PQutZ5rLgWbV5QVKI15Cn7+/IHnRTd3vfKfiwBx6SBqlorAuNA8LA==", + "dev": true, + "requires": { + "acorn": "5.2.1", + "acorn-dynamic-import": "2.0.2", + "ajv": "5.1.6", + "ajv-keywords": "2.1.1", + "async": "2.6.0", + "enhanced-resolve": "3.4.1", + "escope": "3.6.0", + "interpret": "1.1.0", + "json-loader": "0.5.7", + "json5": "0.5.1", + "loader-runner": "2.3.0", + "loader-utils": "1.1.0", + "memory-fs": "0.4.1", + "mkdirp": "0.5.1", + "node-libs-browser": "2.1.0", + "source-map": "0.5.7", + "supports-color": "4.5.0", + "tapable": "0.2.8", + "uglifyjs-webpack-plugin": "0.4.6", + "watchpack": "1.4.0", + "webpack-sources": "1.1.0", + "yargs": "8.0.2" + }, + "dependencies": { + "camelcase": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-4.1.0.tgz", + "integrity": "sha1-1UVjW+HjPFQmScaRc+Xeas+uNN0=", + "dev": true + }, + "cliui": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-3.2.0.tgz", + "integrity": "sha1-EgYBU3qRbSmUD5NNo7SNWFo5IT0=", + "dev": true, + "requires": { + "string-width": "1.0.2", + "strip-ansi": "3.0.1", + "wrap-ansi": "2.1.0" + }, + "dependencies": { + "string-width": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", + "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", + "dev": true, + "requires": { + "code-point-at": "1.1.0", + "is-fullwidth-code-point": "1.0.0", + "strip-ansi": "3.0.1" + } + } + } + }, + "source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", + "dev": true + }, + "strip-ansi": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", + "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", + "dev": true, + "requires": { + "ansi-regex": "2.1.1" + } + }, + "yargs": { + "version": "8.0.2", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-8.0.2.tgz", + "integrity": "sha1-YpmpBVsc78lp/355wdkY3Osiw2A=", + "dev": true, + "requires": { + "camelcase": "4.1.0", + "cliui": "3.2.0", + "decamelize": "1.2.0", + "get-caller-file": "1.0.2", + "os-locale": "2.1.0", + "read-pkg-up": "2.0.0", + "require-directory": "2.1.1", + "require-main-filename": "1.0.1", + "set-blocking": "2.0.0", + "string-width": "2.1.1", + "which-module": "2.0.0", + "y18n": "3.2.1", + "yargs-parser": "7.0.0" + } + } + } + }, + "webpack-sources": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-1.1.0.tgz", + "integrity": "sha512-aqYp18kPphgoO5c/+NaUvEeACtZjMESmDChuD3NBciVpah3XpMEU9VAAtIaB1BsfJWWTSdv8Vv1m3T0aRk2dUw==", + "dev": true, + "requires": { + "source-list-map": "2.0.0", + "source-map": "0.6.1" + }, + "dependencies": { + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + } + } + }, + "webworkify": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/webworkify/-/webworkify-1.5.0.tgz", + "integrity": "sha512-AMcUeyXAhbACL8S2hqqdqOLqvJ8ylmIbNwUIqQujRSouf4+eUFaXbG6F1Rbu+srlJMmxQWsiU7mOJi0nMBfM1g==" + }, + "wgs84": { + "version": "0.0.0", + "resolved": "https://registry.npmjs.org/wgs84/-/wgs84-0.0.0.tgz", + "integrity": "sha1-NP3FVZF7blfPKigu0ENxDASc3HY=" + }, + "which": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/which/-/which-1.3.0.tgz", + "integrity": "sha512-xcJpopdamTuY5duC/KnTTNBraPK54YwpenP4lzxU8H91GudWpFv38u0CKjclE1Wi2EH2EDz5LRcHcKbCIzqGyg==", + "dev": true, + "requires": { + "isexe": "2.0.0" + } + }, + "which-module": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/which-module/-/which-module-2.0.0.tgz", + "integrity": "sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho=", + "dev": true + }, + "whoots-js": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/whoots-js/-/whoots-js-2.1.0.tgz", + "integrity": "sha1-vLIBw04OrzNfzOWuLPh0V5qZxIc=" + }, + "window-size": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/window-size/-/window-size-0.1.0.tgz", + "integrity": "sha1-VDjNLqk7IC76Ohn+iIeu58lPnJ0=" + }, + "wordwrap": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-1.0.0.tgz", + "integrity": "sha1-J1hIEIkUVqQXHI0CJkQa3pDLyus=" + }, + "world-calendars": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/world-calendars/-/world-calendars-1.0.3.tgz", + "integrity": "sha1-slxQMrokEo/8QdCfr0pewbnBQzU=", + "requires": { + "object-assign": "4.1.1" + } + }, + "wrap-ansi": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-2.1.0.tgz", + "integrity": "sha1-2Pw9KE3QV5T+hJc8rs3Rz4JP3YU=", + "dev": true, + "requires": { + "string-width": "1.0.2", + "strip-ansi": "3.0.1" + }, + "dependencies": { + "string-width": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", + "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", + "dev": true, + "requires": { + "code-point-at": "1.1.0", + "is-fullwidth-code-point": "1.0.0", + "strip-ansi": "3.0.1" + } + }, + "strip-ansi": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", + "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", + "dev": true, + "requires": { + "ansi-regex": "2.1.1" + } + } + } + }, + "wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=" + }, + "xtend": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.1.tgz", + "integrity": "sha1-pcbVMr5lbiPbgg77lDofBJmNY68=" + }, + "y18n": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-3.2.1.tgz", + "integrity": "sha1-bRX7qITAhnnA136I53WegR4H+kE=", + "dev": true + }, + "yallist": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-2.1.2.tgz", + "integrity": "sha1-HBH5IY8HYImkfdUS+TxmmaaoHVI=", + "dev": true + }, + "yargs": { + "version": "3.10.0", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-3.10.0.tgz", + "integrity": "sha1-9+572FfdfB0tOMDnTvvWgdFDH9E=", + "requires": { + "camelcase": "1.2.1", + "cliui": "2.1.0", + "decamelize": "1.2.0", + "window-size": "0.1.0" + } + }, + "yargs-parser": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-7.0.0.tgz", + "integrity": "sha1-jQrELxbqVd69MyyvTEA4s+P139k=", + "dev": true, + "requires": { + "camelcase": "4.1.0" + }, + "dependencies": { + "camelcase": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-4.1.0.tgz", + "integrity": "sha1-1UVjW+HjPFQmScaRc+Xeas+uNN0=", + "dev": true + } + } + }, + "zero-crossings": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/zero-crossings/-/zero-crossings-1.0.1.tgz", + "integrity": "sha1-xWK9MRNkPzRDokXRJAa4i2m5qf8=", + "requires": { + "cwise-compiler": "1.1.3" + } + } + } +} diff --git a/ipyplotly/js/package.json b/ipyplotly/js/package.json new file mode 100644 index 00000000000..c67dc76a89e --- /dev/null +++ b/ipyplotly/js/package.json @@ -0,0 +1,41 @@ +{ + "name": "ipyplotly", + "version": "0.1.0", + "description": "pythonic plotly API for use in Jupyter", + "author": "Jon Mease", + "main": "src/index.js", + "repository": { + "type": "git", + "url": "https://github.com/jmmease/ipyplotly.git" + }, + "keywords": [ + "jupyter", + "widgets", + "ipython", + "ipywidgets" + ], + "files": [ + "src/**/*.js", + "dist/*.js" + ], + "scripts": { + "clean": "rimraf dist/ && rimraf ../ipyplotly/static", + "build": "webpack", + "prepublish": "npm run clean && npm run build", + "test": "echo \"Error: no test specified\" && exit 1" + }, + "devDependencies": { + "json-loader": "^0.5.4", + "webpack": "^3.5.5", + "rimraf": "^2.6.1", + "ify-loader": "^1.1.0" + }, + "dependencies": { + "plotly.js": "^1.33.1", + "@jupyter-widgets/base": "^1.0.4", + "lodash": "^4.0" + }, + "jupyterlab": { + "extension": "src/jupyterlab-plugin" + } +} diff --git a/ipyplotly/js/src/Figure.js b/ipyplotly/js/src/Figure.js new file mode 100644 index 00000000000..1128a1bb9da --- /dev/null +++ b/ipyplotly/js/src/Figure.js @@ -0,0 +1,1228 @@ +var widgets = require('@jupyter-widgets/base'); +var _ = require('lodash'); +var Plotly = require('plotly.js'); + + +// Models +// ====== +var FigureModel = widgets.DOMWidgetModel.extend({ + + defaults: _.extend(widgets.DOMWidgetModel.prototype.defaults(), { + _model_name: 'FigureModel', + _view_name: 'FigureView', + _model_module: 'ipyplotly', + _view_module: 'ipyplotly', + + _data: [], + _layout: {}, // Not synced to python side + + // Message properties + _py2js_addTraces: null, + _py2js_deleteTraces: null, + _py2js_moveTraces: null, + _py2js_restyle: null, + _py2js_relayout: null, + _py2js_update: null, + _py2js_animate: null, + + _py2js_removeLayoutProps: null, + _py2js_removeStyleProps: null, + + _py2js_requestSvg: null, + + // JS -> Python + _js2py_restyle: null, + _js2py_relayout: null, + _js2py_update: null, + + _js2py_layoutDelta: null, + _js2py_tracesDelta: null, + + // callbacks + _js2py_pointsCallback: null, + + // svg + _js2py_svg: null, + + // message tracking + _last_relayout_msg_id: 0, + _last_restyle_msg_id: 0 + }), + + initialize: function() { + FigureModel.__super__.initialize.apply(this, arguments); + console.log(['FigureModel: initialize', this._data, this._layout]); + + this.on('change:_py2js_addTraces', this.do_addTraces, this); + this.on('change:_py2js_deleteTraces', this.do_deleteTraces, this); + this.on('change:_py2js_moveTraces', this.do_moveTraces, this); + this.on("change:_py2js_restyle", this.do_restyle, this); + this.on("change:_py2js_relayout", this.do_relayout, this); + this.on("change:_py2js_update", this.do_update, this); + this.on("change:_py2js_animate", this.do_animate, this); + this.on("change:_py2js_removeLayoutProps", this.do_removeLayoutProps, this); + this.on("change:_py2js_removeStyleProps", this.do_removeStyleProps, this); + }, + + _str_to_dict_path: function (rawKey) { + + // Split string on periods. e.g. 'foo.bar[0]' -> ['foo', 'bar[0]'] + var keyPath = rawKey.split('.'); + var regex = /(.*)\[(\d+)\]/; + + // Split out bracket indexes. e.g. ['foo', 'bar[0]'] -> ['foo', 'bar', '0'] + var keyPath2 = []; + for (var k = 0; k < keyPath.length; k++) { + var key = keyPath[k]; + var match = regex.exec(key); + if (match === null) { + keyPath2.push(key); + } else { + keyPath2.push(match[1]); + keyPath2.push(match[2]); + } + } + + // Convert elements to ints if possible. e.g. e.g. ['foo', 'bar', '0'] -> ['foo', 'bar', 0] + for (k = 0; k < keyPath2.length; k++) { + key = keyPath2[k]; + var potentialInt = parseInt(key); + if (!isNaN(potentialInt)) { + keyPath2[k] = potentialInt; + } + } + return keyPath2 + }, + + normalize_trace_indexes: function (trace_indexes) { + if (trace_indexes === null || trace_indexes === undefined) { + var numTraces = this.get('_data').length; + trace_indexes = Array.apply(null, new Array(numTraces)).map(function (_, i) {return i;}); + } + if (!Array.isArray(trace_indexes)) { + // Make sure idx is an array + trace_indexes = [trace_indexes]; + } + return trace_indexes + }, + + + do_addTraces: function () { + // add trace to plot + console.log('Figure Model: do_addTraces'); + var data = this.get('_py2js_addTraces'); + + if (data !== null) { + console.log(data); + var tracesData = this.get('_data'); + _.forEach(data, function (traceData) { + tracesData.push(traceData); + }) + } + }, + + do_deleteTraces: function () { + // add trace to plot + var data = this.get('_py2js_deleteTraces'); + console.log('Figure Model: do_deleteTraces'); + if (data !== null) { + var delete_inds = data['delete_inds']; + var tracesData = this.get('_data'); + + // Remove del inds in reverse order so indexes remain valid throughout loop + delete_inds.slice().reverse().forEach(function (del_ind) { + tracesData.splice(del_ind, 1); + }); + } + }, + + do_moveTraces: function () { + console.log('Figure Model: do_moveTraces'); + + var move_data = this.get('_py2js_moveTraces'); + console.log('do_moveTraces'); + + if (move_data !== null) { + var currentInds = move_data[0]; + var newInds = move_data[1]; + var tracesData = this.get('_data'); + + // ### Remove by curr_inds in reverse order ### + var movingTracesData = []; + for (var ci = currentInds.length - 1; ci >= 0; ci--) { + // Insert moving tracesData at beginning of the list + movingTracesData.splice(0, 0, tracesData[currentInds[ci]]); + tracesData.splice(currentInds[ci], 1); + } + + // ### Sort newInds and movingTracesData by newInds ### + var newIndexSortedArrays = _(newInds).zip(movingTracesData) + .sortBy(0) + .unzip() + .value(); + + newInds = newIndexSortedArrays[0]; + movingTracesData = newIndexSortedArrays[1]; + + // ### Insert by newInds in forward order ### + for (var ni = 0; ni < newInds.length; ni++) { + tracesData.splice(newInds[ni], 0, movingTracesData[ni]); + } + } + }, + + do_restyle: function () { + console.log('FigureModel: do_restyle'); + var data = this.get('_py2js_restyle'); + if (data !== null) { + var style = data[0]; + var trace_indexes = this.normalize_trace_indexes(data[1]); + this._performRestyle(style, trace_indexes) + } + }, + + _performRestyle: function (style, trace_indexes){ + + for (var rawKey in style) { + if (!style.hasOwnProperty(rawKey)) { continue } + var v = style[rawKey]; + + if (!Array.isArray(v)) { + v = [v] + } + + var keyPath = this._str_to_dict_path(rawKey); + + for (var i = 0; i < trace_indexes.length; i++) { + var trace_ind = trace_indexes[i]; + var valParent = this.get('_data')[trace_ind]; + + for (var kp = 0; kp < keyPath.length-1; kp++) { + var keyPathEl = keyPath[kp]; + + // Extend val_parent list if needed + if (Array.isArray(valParent)) { + if (typeof keyPathEl === 'number') { + while (valParent.length <= keyPathEl) { + valParent.push(null) + } + } + } else { // object + // Initialize child if needed + if (valParent[keyPathEl] === undefined) { + if (typeof keyPath[kp + 1] === 'number') { + valParent[keyPathEl] = [] + } else { + valParent[keyPathEl] = {} + } + } + } + valParent = valParent[keyPathEl]; + } + + var lastKey = keyPath[keyPath.length-1]; + var trace_v = v[i % v.length]; + + if (trace_v === undefined) { + // Nothing to do + } else if (trace_v === null){ + if(valParent.hasOwnProperty(lastKey)) { + delete valParent[lastKey]; + } + } else { + if (Array.isArray(valParent) && typeof lastKey === 'number') { + while (valParent.length <= lastKey) { + // Make sure array is long enough to assign into + valParent.push(null) + } + } + valParent[lastKey] = trace_v; + } + } + } + }, + + do_relayout: function () { + console.log('FigureModel: do_relayout'); + var data = this.get('_py2js_relayout'); + if (data !== null) { + console.log(data); + this._performRelayout(data); + console.log(this.get('_layout')) + } + }, + + _performRelayout: function (relayout_data) { + this._performRelayoutLike(relayout_data, this.get('_layout')) + }, + + _performRelayoutLike: function (relayout_data, parent_data) { + // Perform a relayout style operation on a given parent object + for (var rawKey in relayout_data) { + if (!relayout_data.hasOwnProperty(rawKey)) { + continue + } + + var v = relayout_data[rawKey]; + var keyPath = this._str_to_dict_path(rawKey); + + var valParent = parent_data; + + for (var kp = 0; kp < keyPath.length-1; kp++) { + var keyPathEl = keyPath[kp]; + + // Extend val_parent list if needed + if (Array.isArray(valParent)) { + if(typeof keyPathEl === 'number') { + while (valParent.length <= keyPathEl) { + valParent.push(null) + } + } + } else { + // Initialize child if needed + if (valParent[keyPathEl] === undefined) { + if (typeof keyPath[kp + 1] === 'number') { + valParent[keyPathEl] = [] + } else { + valParent[keyPathEl] = {} + } + } + } + valParent = valParent[keyPathEl]; + } + + var lastKey = keyPath[keyPath.length-1]; + + if (v === undefined) { + // Nothing to do + } else if (v === null){ + if(valParent.hasOwnProperty(lastKey)) { + delete valParent[lastKey]; + } + } else { + if (Array.isArray(valParent) && typeof lastKey === 'number') { + while (valParent.length <= lastKey) { + // Make sure array is long enough to assign into + valParent.push(null) + } + } + valParent[lastKey] = v; + } + } + }, + + do_update: function() { + console.log('FigureModel: do_update'); + var data = this.get('_py2js_update'); + if (data !== null) { + console.log(data); + + var style = data[0]; + var layout = data[1]; + var trace_indexes = this.normalize_trace_indexes(data[2]); + this._performRestyle(style, trace_indexes); + this._performRelayout(layout); + } + }, + + do_animate: function () { + console.log('FigureModel: do_animate'); + var data = this.get('_py2js_animate'); + if (data !== null) { + console.log(data); + var animationData = data[0]; + + var styles = animationData['data']; + var layout = animationData['layout']; + var trace_indexes = this.normalize_trace_indexes(animationData['traces']); + + for (var i = 0; i < styles.length; i++) { + var style = styles[i]; + var trace_index = trace_indexes[i]; + var trace = this.get('_data')[trace_index]; + this._performRelayoutLike(style, trace); + } + + this._performRelayout(layout); + } + }, + + // ### Remove props ### + do_removeLayoutProps: function () { + console.log('FigureModel:do_removeLayoutProps'); + var data = this.get('_py2js_removeLayoutProps'); + if (data !== null) { + console.log(this.get('_layout')); + for(var i=0; i < data.length; i++) { + + var keyPath = data[i]; + var valParent = this.get('_layout'); + + for (var kp = 0; kp < keyPath.length - 1; kp++) { + var keyPathEl = keyPath[kp]; + if (valParent[keyPathEl] === undefined) { + valParent = null; + break + } + valParent = valParent[keyPathEl]; + } + if (valParent !== null) { + var lastKey = keyPath[keyPath.length - 1]; + if (valParent.hasOwnProperty(lastKey)) { + delete valParent[lastKey]; + console.log('Removed ' + keyPath) + } + } + } + console.log(this.get('_layout')); + } + }, + + do_removeStyleProps: function () { + console.log('FigureModel:do_removeStyleProps'); + var data = this.get('_py2js_removeStyleProps'); + if (data !== null) { + console.log(data); + var keyPaths = data[0]; + var trace_indexes = this.normalize_trace_indexes(data[1]); + + for(var k=0; k < keyPaths.length; k++) { + + var keyPath = keyPaths[k]; + + for (var i = 0; i < trace_indexes.length; i++) { + var trace_ind = trace_indexes[i]; + var valParent = this.get('_data')[trace_ind]; + + for (var kp = 0; kp < keyPath.length - 1; kp++) { + var keyPathEl = keyPath[kp]; + if (valParent[keyPathEl] === undefined) { + valParent = null; + break + } + valParent = valParent[keyPathEl]; + } + if (valParent !== null) { + var lastKey = keyPath[keyPath.length - 1]; + if (valParent.hasOwnProperty(lastKey)) { + delete valParent[lastKey]; + console.log('Removed ' + keyPath) + } + } + } + } + } + } +}, { + serializers: _.extend({ + _data: { deserialize: py2js_serializer, serialize: js2py_serializer}, + _layout: { deserialize: py2js_serializer, serialize: js2py_serializer}, + _py2js_addTraces: { deserialize: py2js_serializer, serialize: js2py_serializer}, + _py2js_deleteTraces: { deserialize: py2js_serializer, serialize: js2py_serializer}, + _py2js_moveTraces: { deserialize: py2js_serializer, serialize: js2py_serializer}, + _py2js_restyle: { deserialize: py2js_serializer, serialize: js2py_serializer}, + _py2js_relayout: { deserialize: py2js_serializer, serialize: js2py_serializer}, + _py2js_update: { deserialize: py2js_serializer, serialize: js2py_serializer}, + _py2js_animate: { deserialize: py2js_serializer, serialize: js2py_serializer}, + _py2js_removeLayoutProps: { deserialize: py2js_serializer, serialize: js2py_serializer}, + _py2js_removeStyleProps: { deserialize: py2js_serializer, serialize: js2py_serializer}, + _js2py_restyle: { deserialize: py2js_serializer, serialize: js2py_serializer}, + _js2py_relayout: { deserialize: py2js_serializer, serialize: js2py_serializer}, + _js2py_update: { deserialize: py2js_serializer, serialize: js2py_serializer}, + _js2py_layoutDelta: { deserialize: py2js_serializer, serialize: js2py_serializer}, + _js2py_tracesDelta: { deserialize: py2js_serializer, serialize: js2py_serializer}, + _js2py_pointsCallback: { deserialize: py2js_serializer, serialize: js2py_serializer}, + }, widgets.DOMWidgetModel.serializers) +}); + +var numpy_dtype_to_typedarray_type = { + int8: Int8Array, + int16: Int16Array, + int32: Int32Array, + uint8: Uint8Array, + uint16: Uint16Array, + uint32: Uint32Array, + float32: Float32Array, + float64: Float64Array +}; + +function js2py_serializer(v, widgetManager) { + var res; + if (Array.isArray(v)) { + res = new Array(v.length); + for (var i = 0; i < v.length; i++) { + res[i] = js2py_serializer(v[i]); + } + } else if (_.isPlainObject(v)) { + res = {}; + for (var p in v) { + if (v.hasOwnProperty(p)) { + res[p] = js2py_serializer(v[p]); + } + } + } else if (v === undefined) { + res = '_undefined_'; + } else { + res = v; + } + return res +} + +function py2js_serializer(v, widgetManager) { + var res; + if (Array.isArray(v)) { + res = new Array(v.length); + for (var i = 0; i < v.length; i++) { + res[i] = py2js_serializer(v[i]); + } + } else if (_.isPlainObject(v)) { + if (_.has(v, 'buffer') && _.has(v, 'dtype') && _.has(v, 'shape')) { + var typedarray_type = numpy_dtype_to_typedarray_type[v.dtype]; + var typedarray = new typedarray_type(v.buffer.buffer); + res = Array.from(typedarray); + } else { + res = {}; + for (var p in v) { + if (v.hasOwnProperty(p)) { + res[p] = py2js_serializer(v[p]); + } + } + } + } else if (v === '_undefined_') { + res = undefined; + } else { + res = v; + } + return res +} + +// Figure View +// =========== +var FigureView = widgets.DOMWidgetView.extend({ + + render: function() { + + var that = this; + + // Wire up property callbacks + // -------------------------- + // Python -> JS event properties + this.model.on('change:_py2js_addTraces', this.do_addTraces, this); + this.model.on('change:_py2js_deleteTraces', this.do_deleteTraces, this); + this.model.on('change:_py2js_moveTraces', this.do_moveTraces, this); + this.model.on('change:_py2js_restyle', this.do_restyle, this); + this.model.on("change:_py2js_relayout", this.do_relayout, this); + this.model.on("change:_py2js_update", this.do_update, this); + this.model.on("change:_py2js_animate", this.do_animate, this); + this.model.on("change:_py2js_requestSvg", this.do_requestSvg, this); + + // Increment message ids + // --------------------- + var relayout_msg_id = this.model.get('_last_relayout_msg_id') + 1; + this.model.set('_last_relayout_msg_id', relayout_msg_id); + var restyle_msg_id = this.model.get('_last_restyle_msg_id') + 1; + this.model.set('_last_restyle_msg_id', restyle_msg_id); + this.touch(); + + // Set view UID + // ------------ + this.viewID = randstr(); + console.log('Created view with id: ' + this.viewID); + + // Initialize figure + // ----------------- + console.log('render'); + console.log(this.model.get('_data')); + console.log(this.model.get('_layout')); + + // Clone traces and layout so plotly instances in the views don't mutate the model + var initial_traces = JSON.parse(JSON.stringify(this.model.get('_data'))); + var initial_layout = JSON.parse(JSON.stringify(this.model.get('_layout'))); + + Plotly.newPlot(this.el, initial_traces, initial_layout).then(function () { + + // Update layout + var relayoutDelta = that.create_delta_object(that.model.get('_layout'), that.getFullLayout()); + relayoutDelta['_relayout_msg_id'] = relayout_msg_id; + that.model.set('_js2py_layoutDelta', relayoutDelta); + + // Update traces + // Loop over new traces + var traceDeltas = new Array(initial_traces.length); + var fullData = that.getFullData(); + for(var i=0; i < initial_traces.length; i++) { + var fullTraceData = fullData[i]; + var traceData = initial_traces[i]; + traceDeltas[i] = that.create_delta_object(traceData, fullTraceData); + traceDeltas[i]['_restyle_msg_id'] = restyle_msg_id; + } + + console.log(traceDeltas); + that.model.set('_js2py_styleDelta', traceDeltas); + + // sync any/all changes back to model + that.touch(); + + // Wire up plotly event callbacks + that.el.on('plotly_restyle', function(update) {that.handle_plotly_restyle(update)}); + that.el.on('plotly_relayout', function(update) {that.handle_plotly_relayout(update)}); + that.el.on('plotly_update', function(update) {that.handle_plotly_update(update)}); + + that.el.on('plotly_click', function(update) {that.handle_plotly_click(update)}); + that.el.on('plotly_hover', function(update) {that.handle_plotly_hover(update)}); + that.el.on('plotly_unhover', function(update) {that.handle_plotly_unhover(update)}); + that.el.on('plotly_selected', function(update) {that.handle_plotly_selected(update)}); + that.el.on('plotly_doubleclick', function(update) {that.handle_plotly_doubleclick(update)}); + that.el.on('plotly_afterplot', function(update) {that.handle_plotly_afterplot(update)}); + }); + }, + destroy: function() { + Plotly.purge(this.el); + }, + getFullData: function () { + // Merge so that we use .data properties if available. + // e.g. colorscales can be stored by name in this.el.data (Viridis) but by array in el._fullData. We want + // the string in this case + return _.merge(this.el._fullData, this.el.data); + }, + + getFullLayout: function () { + return _.merge(this.el._fullLayout, this.el.layout); + }, + + buildPointsObject: function (data) { + + var pointsObject; + if (data.hasOwnProperty('points')) { + // Most cartesian plots + var pointObjects = data['points']; + var numPoints = pointObjects.length; + pointsObject = { + 'curveNumbers': new Array(numPoints), + 'pointNumbers': new Array(numPoints), + 'xs': new Array(numPoints), + 'ys': new Array(numPoints)}; + + + for (var p = 0; p < numPoints; p++) { + pointsObject['curveNumbers'][p] = pointObjects[p]['curveNumber']; + pointsObject['pointNumbers'][p] = pointObjects[p]['pointNumber']; + pointsObject['xs'][p] = pointObjects[p]['x']; + pointsObject['ys'][p] = pointObjects[p]['y']; + } + + // Add z if present + var hasZ = pointObjects[0] !== undefined && pointObjects[0].hasOwnProperty('z'); + if (hasZ) { + pointsObject['zs'] = new Array(numPoints); + for (p = 0; p < numPoints; p++) { + pointsObject['zs'][p] = pointObjects[p]['z']; + } + } + + return pointsObject + } else { + return null + } + }, + + buildMouseEventObject: function (data) { + var event = data['event']; + if (event === undefined) { + return {} + } else { + var mouseEventObject = { + // Keyboard modifiers + 'alt': event['altKey'], + 'ctrl': event['ctrlKey'], + 'meta': event['metaKey'], + 'shift': event['shiftKey'], + + // Mouse buttons + 'button': event['button'], + // Indicates which button was pressed on the mouse to trigger the event. + // 0: Main button pressed, usually the left button or the un-initialized state + // 1: Auxiliary button pressed, usually the wheel button or the middle button (if present) + // 2: Secondary button pressed, usually the right button + // 3: Fourth button, typically the Browser Back button + // 4: Fifth button, typically the Browser Forward button + 'buttons': event['buttons'] + // Indicates which buttons are pressed on the mouse when the event is triggered. + // 0 : No button or un-initialized + // 1 : Primary button (usually left) + // 2 : Secondary button (usually right) + // 4 : Auxilary button (usually middle or mouse wheel button) + // 8 : 4th button (typically the "Browser Back" button) + // 16 : 5th button (typically the "Browser Forward" button) + }; + return mouseEventObject + } + }, + + buildSelectorObject: function(data) { + var selectorObject = {}; + + // Test for box select + if (data.hasOwnProperty('range')) { + selectorObject['type'] = 'box'; + selectorObject['xrange'] = data['range']['x']; + selectorObject['yrange'] = data['range']['y']; + } else if (data.hasOwnProperty('lassoPoints')) { + selectorObject['type'] = 'lasso'; + selectorObject['xs'] = data['lassoPoints']['x']; + selectorObject['ys'] = data['lassoPoints']['y']; + } + return selectorObject + }, + + handle_plotly_restyle: function (data) { + if (data !== null && data !== undefined && data[0].hasOwnProperty('_doNotReportToPy')) { + // Restyle originated on the Python side + return + } + + // Work around some plotly bugs/limitations + if (data === null || data === undefined) { + + data = new Array(this.el.data.length); + + for (var t = 0; t < this.el.data.length; t++) { + var traceData = this.el.data[t]; + data[t] = {'uid': traceData['uid']}; + if (traceData['type'] === 'parcoords') { + + // Parallel coordinate diagram 'constraintrange' property not provided + for (var d = 0; d < traceData.dimensions.length; d++) { + var constraintrange = traceData.dimensions[d]['constraintrange']; + if (constraintrange !== undefined) { + data[t]['dimensions[' + d + '].constraintrange'] = [constraintrange]; + } + } + } + } + } + + // Add viewID to style + data[0]['_view_id'] = this.viewID; + + // Log message + console.log("plotly_restyle"); + console.log(data); + + this.model.set('_js2py_restyle', data); + this.touch(); + }, + + handle_plotly_relayout: function (data) { + if (data !== null && data !== undefined && data.hasOwnProperty('_doNotReportToPy')) { + // Relayout originated on the Python side + return + } + + // Work around some plotly bugs/limitations + + // Sometimes (in scatterGL at least) axis range isn't wrapped in range + if ('xaxis' in data && Array.isArray(data['xaxis'])) { + data['xaxis'] = {'range': data['xaxis']} + } + + if ('yaxis' in data && Array.isArray(data['yaxis'])) { + data['yaxis'] = {'range': data['yaxis']} + } + + // Add viewID + data['_view_id'] = this.viewID; + + // Log message + console.log("plotly_relayout"); + console.log(data); + + this.model.set('_js2py_relayout', data); + this.touch(); + }, + + handle_plotly_update: function (data) { + if (data !== null && data !== undefined && + data['data'][0].hasOwnProperty('_doNotReportToPy')) { + // Update originated on the Python side + return + } + + // Add viewID to style element + data['data'][0]['_view_id'] = this.viewID; + + // Log message + console.log("plotly_update"); + console.log(data); + + this.model.set('_js2py_update', data); + this.touch(); + }, + + handle_plotly_click: function (data) { + console.log("plotly_click"); + + if (data === null || data === undefined) return; + + var pyData = { + 'event_type': 'plotly_click', + 'points': this.buildPointsObject(data), + 'state': this.buildMouseEventObject(data) + }; + + if (pyData['points'] !== null) { + console.log(data); + console.log(pyData); + this.model.set('_js2py_pointsCallback', pyData); + this.touch(); + } + }, + + handle_plotly_hover: function (data) { + console.log("plotly_hover"); + + if (data === null || data === undefined) return; + + var pyData = { + 'event_type': 'plotly_hover', + 'points': this.buildPointsObject(data), + 'state': this.buildMouseEventObject(data) + }; + + if (pyData['points'] !== null && pyData['points'] !== undefined) { + console.log(data); + console.log(pyData); + this.model.set('_js2py_pointsCallback', pyData); + this.touch(); + } + }, + + handle_plotly_unhover: function (data) { + console.log("plotly_unhover"); + + if (data === null || data === undefined) return; + + var pyData = { + 'event_type': 'plotly_unhover', + 'points': this.buildPointsObject(data), + 'state': this.buildMouseEventObject(data) + }; + + if (pyData['points'] !== null) { + console.log(data); + console.log(pyData); + this.model.set('_js2py_pointsCallback', pyData); + this.touch(); + } + }, + + handle_plotly_selected: function (data) { + console.log("plotly_selected"); + + if (data === null || + data === undefined) return; + + var pyData = { + 'event_type': 'plotly_selected', + 'points': this.buildPointsObject(data), + 'selector': this.buildSelectorObject(data), + }; + + if (pyData['points'] !== null) { + console.log(data); + console.log(pyData); + this.model.set('_js2py_pointsCallback', pyData); + this.touch(); + } + }, + + handle_plotly_doubleclick: function (data) { + // console.log("plotly_doubleclick"); + // console.log(data); + }, + + handle_plotly_afterplot: function (data) { + // console.log("plotly_afterplot"); + // console.log(data); + }, + + do_addTraces: function () { + // add trace to plot + + var data = this.model.get('_py2js_addTraces'); + console.log('Figure View: do_addTraces'); + + if (data !== null) { + console.log(data); + var prev_num_traces = this.el.data.length; + + // console.log(data); + var that = this; + Plotly.addTraces(this.el, data).then(function () { + // Loop over new traces + var traceDeltas = new Array(data.length); + var tracesData = that.model.get('_data'); + var fullData = that.getFullData(); + var restyle_msg_id = data[0]['_restyle_msg_id']; + var relayout_msg_id = data[0]['_relayout_msg_id']; + console.log('relayout_msg_id: ' + relayout_msg_id); + for(var i=0; i < data.length; i++) { + var fullTraceData = fullData[i + prev_num_traces]; + var traceData = tracesData[i + prev_num_traces]; + traceDeltas[i] = that.create_delta_object(traceData, fullTraceData); + traceDeltas[i]['_restyle_msg_id'] = restyle_msg_id; + } + + that.model.set('_js2py_styleDelta', traceDeltas); + + + // Update layout + var layoutDelta = that.create_delta_object(that.model.get('_layout'), that.getFullLayout()); + layoutDelta['_relayout_msg_id'] = relayout_msg_id; + that.model.set('_js2py_layoutDelta', layoutDelta); + console.log(layoutDelta); + + that.touch(); + }); + } + }, + + do_deleteTraces: function () { + var data = this.model.get('_py2js_deleteTraces'); + console.log('do_deleteTraces'); + if (data !== null){ + var delete_inds = data['delete_inds']; + var relayout_msg_id = data['_relayout_msg_id']; + + console.log(delete_inds); + var that = this; + Plotly.deleteTraces(this.el, delete_inds).then(function () { + // Send back layout delta + var relayoutDelta = that.create_delta_object(that.model.get('_layout'), that.getFullLayout()); + relayoutDelta['_relayout_msg_id'] = relayout_msg_id; + that.model.set('_js2py_layoutDelta', relayoutDelta); + that.touch(); + }); + } + }, + + do_moveTraces: function () { + var move_data = this.model.get('_py2js_moveTraces'); + console.log('do_moveTraces'); + + if (move_data !== null){ + var current_inds = move_data[0]; + var new_inds = move_data[1]; + + var inds_equal = current_inds.length===new_inds.length && + current_inds.every(function(v,i) { return v === new_inds[i]}); + + if (!inds_equal) { + console.log(current_inds + "->" + new_inds); + Plotly.moveTraces(this.el, current_inds, new_inds) + } + } + }, + + do_restyle: function () { + console.log('do_restyle'); + var data = this.model.get('_py2js_restyle'); + console.log(data); + if (data !== null) { + var style = data[0]; + var trace_indexes = this.model.normalize_trace_indexes(data[1]); + + if (style['_view_id'] === this.viewID) { + // Operation originated from this view, don't re-apply it + console.log('Skipping restyle for view ' + this.viewID); + return + } else { + console.log('Applying restyle for view ' + this.viewID) + } + + style['_doNotReportToPy'] = true; + Plotly.restyle(this.el, style, trace_indexes); + + // uid + var restyle_msg_id = style['_restyle_msg_id']; + + // Send back style delta + var traceDeltas = new Array(trace_indexes.length); + var trace_data = this.model.get('_data'); + var fullData = this.getFullData(); + for (var i = 0; i < trace_indexes.length; i++) { + traceDeltas[i] = this.create_delta_object(trace_data[trace_indexes[i]], fullData[trace_indexes[i]]); + traceDeltas[i]['_restyle_msg_id'] = restyle_msg_id; + } + + this.model.set('_js2py_styleDelta', traceDeltas); + + // Send back layout delta + var relayout_msg_id = style['_relayout_msg_id']; + var relayoutDelta = this.create_delta_object(this.model.get('_layout'), this.getFullLayout()); + relayoutDelta['_relayout_msg_id'] = relayout_msg_id; + this.model.set('_js2py_layoutDelta', relayoutDelta); + + this.touch(); + } + }, + + do_relayout: function () { + console.log('FigureView: do_relayout'); + var data = this.model.get('_py2js_relayout'); + if (data !== null) { + + if (data['_view_id'] === this.viewID) { + // Operation originated from this view, don't re-apply it + console.log('Skipping relayout for view ' + this.viewID) + return + } else { + console.log('Applying relayout for view ' + this.viewID) + } + + data['_doNotReportToPy'] = true; + Plotly.relayout(this.el, data); + + var layoutDelta = this.create_delta_object(this.model.get('_layout'), this.getFullLayout()); + + // Add message id + layoutDelta['_relayout_msg_id'] = data['_relayout_msg_id']; + + console.log(layoutDelta); + console.log(this.model.get('_layout')); + this.model.set('_js2py_layoutDelta', layoutDelta); + + this.touch(); + } + }, + + do_update: function () { + console.log('FigureView: do_update'); + var data = this.model.get('_py2js_update'); + if (data !== null) { + var style = data[0]; + var layout = data[1]; + var trace_indexes = this.model.normalize_trace_indexes(data[2]); + + if (style['_view_id'] === this.viewID) { + // Operation originated from this view, don't re-apply it + console.log('Skipping update for view ' + this.viewID); + return + } else { + console.log('Applying update for view ' + this.viewID) + } + + style['_doNotReportToPy'] = true; + Plotly.update(this.el, style, layout, trace_indexes); + + // Message ids + var restyle_msg_id = style['_restyle_msg_id']; + var relayout_msg_id = layout['_relayout_msg_id']; + + // Send back style delta + var traceDeltas = new Array(trace_indexes.length); + var trace_data = this.model.get('_data'); + var fullData = this.getFullData(); + for (var i = 0; i < trace_indexes.length; i++) { + traceDeltas[i] = this.create_delta_object(trace_data[trace_indexes[i]], fullData[trace_indexes[i]]); + traceDeltas[i]['_restyle_msg_id'] = restyle_msg_id; + } + + this.model.set('_js2py_styleDelta', traceDeltas); + + // Send back layout delta + var relayoutDelta = this.create_delta_object(this.model.get('_layout'), this.getFullLayout()); + relayoutDelta['_relayout_msg_id'] = relayout_msg_id; + this.model.set('_js2py_layoutDelta', relayoutDelta); + + this.touch(); + } + }, + + do_animate: function() { + console.log('FigureView: do_animate'); + var data = this.model.get('_py2js_animate'); + if (data !== null) { + + // Unpack params + var animationData = data[0]; + var animationOpts = data[1]; + + var styles = animationData['data']; + var layout = animationData['layout']; + var trace_indexes = this.model.normalize_trace_indexes(animationData['traces']); + + animationData['_doNotReportToPy'] = true; + var that = this; + Plotly.animate(this.el, animationData, animationOpts).then(function () { + // Send back style delta + var traceDeltas = new Array(trace_indexes.length); + var trace_data = that.model.get('_data'); + var fullData = that.getFullData(); + for (var i = 0; i < trace_indexes.length; i++) { + var restyle_msg_id = styles[i]['_restyle_msg_id']; + traceDeltas[i] = that.create_delta_object(trace_data[trace_indexes[i]], fullData[trace_indexes[i]]); + traceDeltas[i]['_restyle_msg_id'] = restyle_msg_id; + } + + that.model.set('_js2py_styleDelta', traceDeltas); + + // Send back layout delta + var relayout_msg_id = layout['_relayout_msg_id']; + var relayoutDelta = that.create_delta_object(that.model.get('_layout'), that.getFullLayout()); + relayoutDelta['_relayout_msg_id'] = relayout_msg_id; + that.model.set('_js2py_layoutDelta', relayoutDelta); + + that.touch(); + }); + } + }, + + do_requestSvg: function() { + console.log('FigureView: do_requestSvg'); + var req_id = this.model.get('_py2js_requestSvg'); + var that = this; + if (req_id !== null) { + Plotly.toImage(this.el, {format:'svg'}).then(function (svg_uri) { + console.log([req_id, svg_uri]); + + that.send({event: 'svg', req_id: req_id, svg_uri: svg_uri}); + + // that.model.set('_js2py_svg', [req_id, svg_uri]); + // that.touch(); + }); + } + }, + + clone_fullLayout_data: function (fullLayout) { + var fullStr = JSON.stringify(fullLayout, function(k, v) { + if (k.length > 0 && k[0] === '_') { + return undefined + } + return v + }); + return JSON.parse(fullStr) + }, + + clone_fullData_metadata: function (fullData) { + var fullStr = JSON.stringify(fullData, function(k, v) { + if (k.length > 0 && k[0] === '_') { + return undefined + } else if (Array.isArray(v)) { + // For performance, we don't clone arrays + return undefined + } + return v + }); + return JSON.parse(fullStr) + }, + + create_delta_object: function(data, fullData) { + var res; + if(Array.isArray(fullData)) { + res = new Array(fullData.length); + } else { + res = {}; + } + + if (data === null || data === undefined) { + data = {}; + } + for (var p in fullData) { + if (p[0] !== '_' && fullData.hasOwnProperty(p) && fullData[p] !== null) { + + var props_equal; + if (data.hasOwnProperty(p) && Array.isArray(data[p]) && Array.isArray(fullData[p])) { + props_equal = JSON.stringify(data[p]) === JSON.stringify(fullData[p]); + } else if (data.hasOwnProperty(p)) { + props_equal = data[p] === fullData[p]; + } else { + props_equal = false; + } + + if (!props_equal || p === 'uid') { // Let uids through + // property has non-null value in fullData that doesn't match the value in + var full_val = fullData[p]; + if (data.hasOwnProperty(p) && typeof full_val === 'object') { + if(Array.isArray(full_val)) { + + if (full_val.length > 0 && typeof(full_val[0]) === 'object') { + // We have an object array + res[p] = new Array(full_val.length); + for (var i = 0; i < full_val.length; i++) { + if (!Array.isArray(data[p]) || data[p].length <= i) { + res[p][i] = full_val[i] + } else { + res[p][i] = this.create_delta_object(data[p][i], full_val[i]); + } + } + } else { + // We have a primitive array + res[p] = full_val; + } + } else { // object + var full_obj = this.create_delta_object(data[p], full_val); + if (Object.keys(full_obj).length > 0) { + // new object is not empty + res[p] = full_obj; + } + } + } else if (typeof full_val === 'object' && !Array.isArray(full_val)) { + res[p] = this.create_delta_object({}, full_val); + + } else if (full_val !== undefined) { + res[p] = full_val; + } + } + } + } + return res + } +}); + +// Copied from Plotly src/lib/index.js (How can we call it?) +// random string generator +function randstr(existing, bits, base) { + /* + * Include number of bits, the base of the string you want + * and an optional array of existing strings to avoid. + */ + if(!base) base = 16; + if(bits === undefined) bits = 24; + if(bits <= 0) return '0'; + + var digits = Math.log(Math.pow(2, bits)) / Math.log(base), + res = '', + i, + b, + x; + + for(i = 2; digits === Infinity; i *= 2) { + digits = Math.log(Math.pow(2, bits / i)) / Math.log(base) * i; + } + + var rem = digits - Math.floor(digits); + + for(i = 0; i < Math.floor(digits); i++) { + x = Math.floor(Math.random() * base).toString(base); + res = x + res; + } + + if(rem) { + b = Math.pow(base, rem); + x = Math.floor(Math.random() * b).toString(base); + res = x + res; + } + + var parsed = parseInt(res, base); + if((existing && (existing.indexOf(res) > -1)) || + (parsed !== Infinity && parsed >= Math.pow(2, bits))) { + return randstr(existing, bits, base); + } + else return res; +}; + +module.exports = { + FigureView : FigureView, + FigureModel: FigureModel, +}; diff --git a/ipyplotly/js/src/embed.js b/ipyplotly/js/src/embed.js new file mode 100644 index 00000000000..85bc6308ad7 --- /dev/null +++ b/ipyplotly/js/src/embed.js @@ -0,0 +1,9 @@ +// Entry point for the unpkg bundle containing custom model definitions. +// +// It differs from the notebook bundle in that it does not need to define a +// dynamic baseURL for the static assets and may load some css that would +// already be loaded by the notebook otherwise. + +// Export widget models and views, and the npm package version number. +module.exports = require('./Figure.js'); +module.exports['version'] = require('../package.json').version; diff --git a/ipyplotly/js/src/extension.js b/ipyplotly/js/src/extension.js new file mode 100644 index 00000000000..373ddbd7bb7 --- /dev/null +++ b/ipyplotly/js/src/extension.js @@ -0,0 +1,19 @@ +// This file contains the javascript that is run when the notebook is loaded. +// It contains some requirejs configuration and the `load_ipython_extension` +// which is required for any notebook extension. + +// Configure requirejs +if (window.require) { + window.require.config({ + map: { + "*" : { + "ipyplotly": "nbextensions/ipyplotly/index", + } + } + }); +} + +// Export the required load_ipython_extention +module.exports = { + load_ipython_extension: function() {} +}; diff --git a/ipyplotly/js/src/index.js b/ipyplotly/js/src/index.js new file mode 100644 index 00000000000..6b99ca27677 --- /dev/null +++ b/ipyplotly/js/src/index.js @@ -0,0 +1,12 @@ +// Entry point for the notebook bundle containing custom model definitions. +// +// Setup notebook base URL +// +// Some static assets may be required by the custom widget javascript. The base +// url for the notebook is not known at build time and is therefore computed +// dynamically. +__webpack_public_path__ = document.querySelector('body').getAttribute('data-base-url') + 'nbextensions/ipyplotly/'; + +// Export widget models and views, and the npm package version number. +module.exports = require('./Figure.js'); +module.exports['version'] = require('../package.json').version; diff --git a/ipyplotly/js/src/jupyterlab-plugin.js b/ipyplotly/js/src/jupyterlab-plugin.js new file mode 100644 index 00000000000..2e00415f0cc --- /dev/null +++ b/ipyplotly/js/src/jupyterlab-plugin.js @@ -0,0 +1,18 @@ +var ipyplotly = require('./index'); +var base = require('@jupyter-widgets/base'); + +/** + * The widget manager provider. + */ +module.exports = { + id: 'ipyplotly', + requires: [base.IJupyterWidgetRegistry], + activate: function(app, widgets) { + widgets.registerWidget({ + name: 'ipyplotly', + version: ipyplotly.version, + exports: ipyplotly + }); + }, + autoStart: true +}; diff --git a/ipyplotly/js/webpack.config.js b/ipyplotly/js/webpack.config.js new file mode 100644 index 00000000000..ab05809b519 --- /dev/null +++ b/ipyplotly/js/webpack.config.js @@ -0,0 +1,80 @@ +var path = require('path'); +var version = require('./package.json').version; + +// Custom webpack loaders are generally the same for all webpack bundles, hence +// stored in a separate local variable. +var rules = [ + { test: /\.css$/, use: ['style-loader', 'css-loader']}, + { test: /\.json$/, use: 'json-loader' }, + { test: /\.js$/, use: 'ify-loader' } +]; + + +module.exports = [ + {// Notebook extension + // + // This bundle only contains the part of the JavaScript that is run on + // load of the notebook. This section generally only performs + // some configuration for requirejs, and provides the legacy + // "load_ipython_extension" function which is required for any notebook + // extension. + // + entry: './src/extension.js', + output: { + filename: 'extension.js', + path: path.resolve(__dirname, '..', 'ipyplotly', 'static'), + libraryTarget: 'amd' + } + }, + {// Bundle for the notebook containing the custom widget views and models + // + // This bundle contains the implementation for the custom widget views and + // custom widget. + // It must be an amd module + // + entry: './src/index.js', + output: { + filename: 'index.js', + path: path.resolve(__dirname, '..', 'ipyplotly', 'static'), + libraryTarget: 'amd' + }, + devtool: 'source-map', + node: { + fs: 'empty' + }, + module: { + rules: rules + }, + externals: ['@jupyter-widgets/base'] + }, + {// Embeddable ipyplotly bundle + // + // This bundle is generally almost identical to the notebook bundle + // containing the custom widget views and models. + // + // The only difference is in the configuration of the webpack public path + // for the static assets. + // + // It will be automatically distributed by unpkg to work with the static + // widget embedder. + // + // The target bundle is always `dist/index.js`, which is the path required + // by the custom widget embedder. + // + entry: './src/embed.js', + output: { + filename: 'index.js', + path: path.resolve(__dirname, 'dist'), + libraryTarget: 'amd', + publicPath: 'https://unpkg.com/ipyplotly@' + version + '/dist/' + }, + devtool: 'source-map', + node: { + fs: 'empty' + }, + module: { + rules: rules + }, + externals: ['@jupyter-widgets/base'] + } +]; diff --git a/ipyplotly/recipe/build.bat b/ipyplotly/recipe/build.bat new file mode 100644 index 00000000000..b9cd616ce4d --- /dev/null +++ b/ipyplotly/recipe/build.bat @@ -0,0 +1,2 @@ +"%PYTHON%" setup.py install --single-version-externally-managed --record=record.txt +if errorlevel 1 exit 1 diff --git a/ipyplotly/recipe/build.sh b/ipyplotly/recipe/build.sh new file mode 100644 index 00000000000..7fa0f85774b --- /dev/null +++ b/ipyplotly/recipe/build.sh @@ -0,0 +1 @@ +$PYTHON setup.py install --single-version-externally-managed --record=record.txt # Python command to install the script. diff --git a/ipyplotly/recipe/meta.yaml b/ipyplotly/recipe/meta.yaml new file mode 100644 index 00000000000..725b37bfd9d --- /dev/null +++ b/ipyplotly/recipe/meta.yaml @@ -0,0 +1,34 @@ +{% set name = "ipyplotly" %} +{% set version = "0.1.0a2" %} + +package: + name: {{ name }} + version: {{ version }} + +source: + path: ../ + +requirements: + build: + - python + - setuptools + + run: + - python >=3.5 + - ipywidgets >=7.0 + - numpy + - pandas >=0.20 + - pillow >=4.2 + - cairosvg >=2.0.0rc6 + - plotly >=2.1 + +build: + noarch: python + +test: + requires: + - pytest + imports: + - ipyplotly + source_files: + - test/ diff --git a/ipyplotly/recipe/post-link.bat b/ipyplotly/recipe/post-link.bat new file mode 100644 index 00000000000..0a89431b6d7 --- /dev/null +++ b/ipyplotly/recipe/post-link.bat @@ -0,0 +1,4 @@ +@echo off + +"%PREFIX%\Scripts\jupyter-nbextension.exe" enable widgetsnbextension --py --sys-prefix > NUL 2>&1 && if errorlevel 1 exit 1 +"%PREFIX%\Scripts\jupyter-nbextension.exe" enable ipyplotly --py --sys-prefix > NUL 2>&1 && if errorlevel 1 exit 1 diff --git a/ipyplotly/recipe/post-link.sh b/ipyplotly/recipe/post-link.sh new file mode 100644 index 00000000000..973bc4e3c69 --- /dev/null +++ b/ipyplotly/recipe/post-link.sh @@ -0,0 +1,2 @@ +"${PREFIX}/bin/jupyter-nbextension" enable --py widgetsnbextension --sys-prefix +"${PREFIX}/bin/jupyter-nbextension" enable --py ipyplotly --sys-prefix diff --git a/ipyplotly/recipe/pre-unlink.bat b/ipyplotly/recipe/pre-unlink.bat new file mode 100644 index 00000000000..aada7fd29a6 --- /dev/null +++ b/ipyplotly/recipe/pre-unlink.bat @@ -0,0 +1,3 @@ +@echo off + +"%PREFIX%\Scripts\jupyter-nbextension.exe" disable ipyplotly --py --sys-prefix > NUL 2>&1 && if errorlevel 1 exit 1 diff --git a/ipyplotly/recipe/pre-unlink.sh b/ipyplotly/recipe/pre-unlink.sh new file mode 100644 index 00000000000..fcea4dbbb35 --- /dev/null +++ b/ipyplotly/recipe/pre-unlink.sh @@ -0,0 +1 @@ +"${PREFIX}/bin/jupyter-nbextension" disable ipyplotly --py --sys-prefix > /dev/null 2>&1 diff --git a/ipyplotly/recipe/run_test.py b/ipyplotly/recipe/run_test.py new file mode 100644 index 00000000000..e31ce6e1e11 --- /dev/null +++ b/ipyplotly/recipe/run_test.py @@ -0,0 +1,2 @@ +import pytest +pytest.main(['test/']) diff --git a/ipyplotly/setup.cfg b/ipyplotly/setup.cfg new file mode 100644 index 00000000000..3c6e79cf31d --- /dev/null +++ b/ipyplotly/setup.cfg @@ -0,0 +1,2 @@ +[bdist_wheel] +universal=1 diff --git a/ipyplotly/setup.py b/ipyplotly/setup.py new file mode 100644 index 00000000000..263d137be2e --- /dev/null +++ b/ipyplotly/setup.py @@ -0,0 +1,190 @@ +from __future__ import print_function +from setuptools import setup, find_packages, Command +from setuptools.command.sdist import sdist +from setuptools.command.build_py import build_py +from setuptools.command.egg_info import egg_info +from subprocess import check_call +import os +import sys +import platform + +here = os.path.dirname(os.path.abspath(__file__)) +node_root = os.path.join(here, 'js') +is_repo = os.path.exists(os.path.join(here, '.git')) + +npm_path = os.pathsep.join([ + os.path.join(node_root, 'node_modules', '.bin'), + os.environ.get('PATH', os.defpath), +]) + +from distutils import log +log.set_verbosity(log.DEBUG) +log.info('setup.py entered') +log.info('$PATH=%s' % os.environ['PATH']) + +LONG_DESCRIPTION = 'A pythonic plotly API and ipywidget for use in Jupyter' + +def js_prerelease(command, strict=False): + """decorator for building minified js/css prior to another command""" + class DecoratedCommand(command): + def run(self): + jsdeps = self.distribution.get_command_obj('jsdeps') + if not is_repo and all(os.path.exists(t) for t in jsdeps.targets): + # sdist, nothing to do + command.run(self) + return + + try: + self.distribution.run_command('jsdeps') + except Exception as e: + missing = [t for t in jsdeps.targets if not os.path.exists(t)] + if strict or missing: + log.warn('rebuilding js and css failed') + if missing: + log.error('missing files: %s' % missing) + raise e + else: + log.warn('rebuilding js and css failed (not a problem)') + log.warn(str(e)) + command.run(self) + update_package_data(self.distribution) + return DecoratedCommand + +def update_package_data(distribution): + """update package_data to catch changes during setup""" + build_py = distribution.get_command_obj('build_py') + # distribution.package_data = find_package_data() + # re-init build_py options which load package_data + build_py.finalize_options() + + +class NPM(Command): + description = 'install package.json dependencies using npm' + + user_options = [] + + node_modules = os.path.join(node_root, 'node_modules') + + targets = [ + os.path.join(here, 'ipyplotly', 'static', 'extension.js'), + os.path.join(here, 'ipyplotly', 'static', 'index.js') + ] + + def initialize_options(self): + pass + + def finalize_options(self): + pass + + def get_npm_name(self): + npmName = 'npm'; + if platform.system() == 'Windows': + npmName = 'npm.cmd'; + + return npmName; + + def has_npm(self): + npmName = self.get_npm_name(); + try: + check_call([npmName, '--version']) + return True + except: + return False + + def should_run_npm_install(self): + package_json = os.path.join(node_root, 'package.json') + node_modules_exists = os.path.exists(self.node_modules) + return self.has_npm() + + def run(self): + has_npm = self.has_npm() + if not has_npm: + log.error("`npm` unavailable. If you're running this command using sudo, make sure `npm` is available to sudo") + + env = os.environ.copy() + env['PATH'] = npm_path + + if self.should_run_npm_install(): + log.info("Installing build dependencies with npm. This may take a while...") + npmName = self.get_npm_name(); + check_call([npmName, 'install'], cwd=node_root, stdout=sys.stdout, stderr=sys.stderr) + os.utime(self.node_modules, None) + + for t in self.targets: + if not os.path.exists(t): + msg = 'Missing file: %s' % t + if not has_npm: + msg += '\nnpm is required to build a development version of widgetsnbextension' + raise ValueError(msg) + + # update package data in case this created new files + update_package_data(self.distribution) + + +class CodegenCommand(Command): + description = 'Generate class hierarchy from Plotly JSON schema' + user_options = [] + + def initialize_options(self): + pass + + def finalize_options(self): + pass + + def run(self): + from codegen import perform_codegen + perform_codegen() + + +version_ns = {} +with open(os.path.join(here, 'ipyplotly', '_version.py')) as f: + exec(f.read(), {}, version_ns) + +setup_args = { + 'name': 'ipyplotly', + 'version': version_ns['__version__'], + 'description': 'pythonic plotly API for use in Jupyter', + 'long_description': LONG_DESCRIPTION, + 'include_package_data': True, + 'data_files': [ + ('share/jupyter/nbextensions/ipyplotly', [ + 'ipyplotly/static/extension.js', + 'ipyplotly/static/index.js', + 'ipyplotly/static/index.js.map', + ]), + ], + 'python_requires': '>=3.5', + 'install_requires': [ + 'ipywidgets>=7.0', + 'numpy>=1.13', + 'pandas>=0.20', + 'plotly>=2.1' + ], + 'packages': find_packages(exclude=('codegen',)), + 'zip_safe': False, + 'cmdclass': { + 'build_py': js_prerelease(build_py), + 'egg_info': js_prerelease(egg_info), + 'sdist': js_prerelease(sdist, strict=True), + 'jsdeps': NPM, + 'codegen': CodegenCommand, + }, + + 'author': 'Jon Mease', + 'author_email': 'jon.mease@gmail.com', + 'keywords': [ + 'ipython', + 'jupyter', + 'widgets', + ], + 'classifiers': [ + 'Development Status :: 4 - Beta', + 'Framework :: IPython', + 'Intended Audience :: Developers', + 'Intended Audience :: Science/Research', + 'Topic :: Multimedia :: Graphics', + 'Programming Language :: Python :: 3.5', + ], +} + +setup(**setup_args) diff --git a/ipyplotly/test/codegen/test_codegen.py b/ipyplotly/test/codegen/test_codegen.py new file mode 100644 index 00000000000..359ea8acb91 --- /dev/null +++ b/ipyplotly/test/codegen/test_codegen.py @@ -0,0 +1,60 @@ +import os +import importlib +import pytest +import inspect + + +# Datatypes modules +# ----------------- +datatypes_root = 'ipyplotly/datatypes' +datatype_modules = [dirpath.replace('/', '.') + for dirpath, _, _ in os.walk(datatypes_root) + if not dirpath.endswith('__pycache__')] + + +@pytest.fixture(params=datatype_modules) +def datatypes_module(request): + return request.param + + +# Validate datatype modules +# ------------------------- +def test_import_datatypes(datatypes_module): + importlib.import_module(datatypes_module) + + +def test_construct_datatypes(datatypes_module): + module = importlib.import_module(datatypes_module) + for name, obj in inspect.getmembers(module, inspect.isclass): + if obj.__module__ == datatypes_module: + datatype_class = obj + + # Call datatype constructor with not arguments + datatype_class() + + +# Validate validator modules +# -------------------------- +validators_root = 'ipyplotly/validators' +validator_modules = [dirpath.replace('/', '.') + for dirpath, _, _ in os.walk(validators_root) + if not dirpath.endswith('__pycache__')] + + +@pytest.fixture(params=validator_modules) +def validators_module(request): + return request.param + + +def test_import_validators(validators_module): + importlib.import_module(validators_module) + + +def test_construct_validators(validators_module): + module = importlib.import_module(validators_module) + for name, obj in inspect.getmembers(module, inspect.isclass): + if obj.__module__ == validators_module: + validator_class = obj + + # Call datatype constructor with not arguments + validator_class() diff --git a/ipyplotly/test/datatypes/properties/conftest.py b/ipyplotly/test/datatypes/properties/conftest.py new file mode 100644 index 00000000000..0c7f8b26dc3 --- /dev/null +++ b/ipyplotly/test/datatypes/properties/conftest.py @@ -0,0 +1,13 @@ +from unittest import mock +import pytest + + +@pytest.fixture(scope="module") +def parent(): + parent_obj = mock.Mock() + parent_props = {'plotly_obj': {}} + parent_prop_defaults = {'plotly_obj': {}} + parent_obj._get_child_props.return_value = parent_props['plotly_obj'] + parent_obj._get_child_prop_defaults.return_value = parent_prop_defaults['plotly_obj'] + parent_obj._in_batch_mode = False + return parent_obj diff --git a/ipyplotly/test/datatypes/properties/test_compound_property.py b/ipyplotly/test/datatypes/properties/test_compound_property.py new file mode 100644 index 00000000000..ef506672e73 --- /dev/null +++ b/ipyplotly/test/datatypes/properties/test_compound_property.py @@ -0,0 +1,129 @@ +from unittest import mock +import pytest +from ipyplotly.basedatatypes import BasePlotlyType +from ipyplotly.basevalidators import CompoundValidator + + +# Fixtures +# -------- +@pytest.fixture() +def plotly_obj(): + + # ### Setup plotly obj (make fixture eventually) ### + plotly_obj = BasePlotlyType('plotly_obj') + + # Add validator + validator = mock.Mock(spec=CompoundValidator, + wraps=CompoundValidator('prop1', 'plotly_obj', data_class=mock.Mock, data_docs='')) + plotly_obj._validators['prop1'] = validator + + # Mock out _send_update + plotly_obj._send_update = mock.Mock() + + return plotly_obj + + +# Validation +# ---------- +def test_set_invalid_property(plotly_obj): + with pytest.raises(KeyError) as failure: + plotly_obj['bogus'] = 'Hello' + + +def test_get_invalid_property(plotly_obj): + with pytest.raises(KeyError) as failure: + p = plotly_obj['bogus'] + + +# Orphan +# ------ +@pytest.mark.xfail +def test_set_get_compound_property(plotly_obj): + # Setup value + # ----------- + v = mock.Mock() + d = {'a': 23} + type(v)._data = mock.PropertyMock(return_value=d) + + # Perform set_prop + # ---------------- + plotly_obj['prop1'] = v + + # Mutate d + # -------- + # Just to make sure we copy data on assignment + d['a'] = 1 + + # Object Assertions + # ----------------- + # ### test get object is a copy ### + assert plotly_obj['prop1'] is not v + + # ### _send_update sent ### + plotly_obj._send_update.assert_called_once_with('prop1', {'a': 23}) + + # ### _orphan_data configured properly ### + assert plotly_obj._orphan_data == {'prop1': {'a': 23}} + + # ### _data is mapped to _orphan_data + assert plotly_obj._props is plotly_obj._orphan_data + + # ### validator called properly ### + plotly_obj._validators['prop1'].validate_coerce.assert_called_once_with(v) + + # Value Assertions + # ---------------- + # ### Parent set to plotly_obj + assert v._parent is plotly_obj + + # ### Orphan data cleared ### + v._orphan_data.clear.assert_called_once() + + +# With parent +# ----------- +@pytest.mark.xfail +def test_set_get_property_with_parent(plotly_obj, parent): + + # Setup value + # ----------- + v = mock.Mock() + d = {'a': 23} + type(v)._data = mock.PropertyMock(return_value=d) + + # Setup parent + # ------------ + plotly_obj._parent = parent + + # Perform set_prop + # ---------------- + plotly_obj['prop1'] = v + + # Parent Assertions + # ----------------- + parent._get_child_props.assert_called_with(plotly_obj) + + # Object Assertions + # ----------------- + # ### test get object is a copy ### + assert plotly_obj['prop1'] is not v + + # ### _send_update sent ### + plotly_obj._send_update.assert_called_once_with('prop1', d) + + # ### orphan data cleared ### + assert plotly_obj._orphan_data == {} + + # ### _data bound to parent dict ### + assert parent._get_child_props(plotly_obj) is plotly_obj._props + + # ### validator called properly ### + plotly_obj._validators['prop1'].validate_coerce.assert_called_once_with(v) + + # Value Assertions + # ---------------- + # ### Parent set to plotly_obj + assert v._parent is plotly_obj + + # ### Orphan data cleared ### + v._orphan_data.clear.assert_called_once() diff --git a/ipyplotly/test/datatypes/properties/test_simple_properties.py b/ipyplotly/test/datatypes/properties/test_simple_properties.py new file mode 100644 index 00000000000..4d455fbb951 --- /dev/null +++ b/ipyplotly/test/datatypes/properties/test_simple_properties.py @@ -0,0 +1,91 @@ +from unittest import mock +import pytest +from ipyplotly.basedatatypes import BasePlotlyType +from ipyplotly.basevalidators import StringValidator + +# Fixtures +# -------- +@pytest.fixture() +def plotly_obj(): + # ### Setup plotly obj (make fixture eventually) ### + plotly_obj = BasePlotlyType('plotly_obj') + + # Add validator + validator = mock.Mock(spec=StringValidator, + wraps=StringValidator('prop1', 'plotly_obj')) + plotly_obj._validators['prop1'] = validator + + # Mock out _send_update + plotly_obj._send_update = mock.Mock() + + return plotly_obj + +# Validation +# ---------- +def test_set_invalid_property(plotly_obj): + with pytest.raises(KeyError) as failure: + plotly_obj['bogus'] = 'Hello' + + +def test_get_invalid_property(plotly_obj): + with pytest.raises(KeyError) as failure: + p = plotly_obj['bogus'] + + +# Orphan +# ------ +def test_set_get_property_orphan(plotly_obj): + # Perform set_prop + # ---------------- + plotly_obj['prop1'] = 'Hello' + + # Assertions + # ---------- + # ### test get ### + assert plotly_obj['prop1'] == 'Hello' + + # ### _send_update sent ### + plotly_obj._send_update.assert_called_once_with('prop1', 'Hello') + + # ### _orphan_data configured properly ### + assert plotly_obj._orphan_props == {'prop1': 'Hello'} + + # ### _props is mapped to _orphan_props + assert plotly_obj._props is plotly_obj._orphan_props + + # ### validator called properly ### + plotly_obj._validators['prop1'].validate_coerce.assert_called_once_with('Hello') + + +# With parent +# ----------- +def test_set_get_property_with_parent(plotly_obj, parent): + + # Setup parent + # ------------ + plotly_obj._parent = parent + + # Perform set_prop + # ---------------- + plotly_obj['prop1'] = 'Hello' + + # Parent Assertions + # ----------------- + parent._get_child_props.assert_called_with(plotly_obj) + + # Child Assertions + # ---------------- + # ### test get ### + assert plotly_obj['prop1'] == 'Hello' + + # ### _props bound to parent dict ### + assert parent._get_child_props(plotly_obj) is plotly_obj._props + + # ### _send_update sent ### + plotly_obj._send_update.assert_called_once_with('prop1', 'Hello') + + # ### Orphan data cleared ### + assert plotly_obj._orphan_props == {} + + # ### validator called properly ### + plotly_obj._validators['prop1'].validate_coerce.assert_called_once_with('Hello') diff --git a/ipyplotly/test/resources/1x1-black.png b/ipyplotly/test/resources/1x1-black.png new file mode 100644 index 00000000000..0f6fbd3c209 Binary files /dev/null and b/ipyplotly/test/resources/1x1-black.png differ diff --git a/ipyplotly/test/utils.py b/ipyplotly/test/utils.py new file mode 100644 index 00000000000..378eb5a3c84 --- /dev/null +++ b/ipyplotly/test/utils.py @@ -0,0 +1,6 @@ +# +# def vals_equal(v1, v2): +# if isinstance(v1, np.ndarray) or isinstance(v2, np.ndarray): +# return np.array_equal(v1, v2) +# else: +# return v1 == v2 \ No newline at end of file diff --git a/ipyplotly/test/validators/test_angle_validator.py b/ipyplotly/test/validators/test_angle_validator.py new file mode 100644 index 00000000000..41ff1f7facd --- /dev/null +++ b/ipyplotly/test/validators/test_angle_validator.py @@ -0,0 +1,40 @@ +import pytest +from ipyplotly.basevalidators import AngleValidator +import numpy as np + + +# Fixtures +# -------- +@pytest.fixture() +def validator(): + return AngleValidator('prop', 'parent') + + +# Tests +# ----- +# ### Test acceptance ### +@pytest.mark.parametrize('val', [0] + list(np.linspace(-180, 179.99))) +def test_acceptance(val, validator): + assert validator.validate_coerce(val) == val + + +# ### Test coercion above 180 ### +@pytest.mark.parametrize('val,expected', [ + (180, -180), + (181, -179), + (-180.25, 179.75), + (540, -180), + (-541, 179) +]) +def test_coercion(val, expected, validator): + assert validator.validate_coerce(val) == expected + + +# ### Test rejection ### +@pytest.mark.parametrize('val', + ['hello', (), [], [1, 2, 3], set(), '34']) +def test_rejection(val, validator: AngleValidator): + with pytest.raises(ValueError) as validation_failure: + validator.validate_coerce(val) + + assert 'Invalid value' in str(validation_failure.value) diff --git a/ipyplotly/test/validators/test_any_validator.py b/ipyplotly/test/validators/test_any_validator.py new file mode 100644 index 00000000000..df602891fc5 --- /dev/null +++ b/ipyplotly/test/validators/test_any_validator.py @@ -0,0 +1,35 @@ +import pytest +from ipyplotly.basevalidators import AnyValidator +import numpy as np + + +# Fixtures +# -------- +@pytest.fixture() +def validator(): + return AnyValidator('prop', 'parent') + + +@pytest.fixture() +def validator_aok(): + return AnyValidator('prop', 'parent', array_ok=True) + +# Tests +# ----- +# ### Acceptance ### +@pytest.mark.parametrize('val', [ + set(), 'Hello', 123, np.inf, np.nan, {} +]) +def test_acceptance(val, validator: AnyValidator): + assert validator.validate_coerce(val) is val + + +# ### Acceptance of arrays ### +@pytest.mark.parametrize('val', [ + [], np.array([]), ['Hello', 'World'], [np.pi, np.e, {}] +]) +def test_acceptance_array(val, validator_aok: AnyValidator): + coerce_val = validator_aok.validate_coerce(val) + assert isinstance(coerce_val, np.ndarray) + assert coerce_val.dtype == 'object' + assert np.array_equal(coerce_val, val) diff --git a/ipyplotly/test/validators/test_basetraces_validator.py b/ipyplotly/test/validators/test_basetraces_validator.py new file mode 100644 index 00000000000..08d50430a71 --- /dev/null +++ b/ipyplotly/test/validators/test_basetraces_validator.py @@ -0,0 +1,150 @@ +import pytest +from ipyplotly.basevalidators import BaseTracesValidator + + +# Build test classes +# ------------------ +class Scatter: + def __init__(self, a=None, b=None, c=None, uid=None): + self.type = 'scatter' + self.a = a + self.b = b + self.c = c + self.uid = uid + + +class Bar: + def __init__(self, a=None, b=None, c=None, uid=None): + self.type = 'bar' + self.a = a + self.b = b + self.c = c + self.uid = uid + + +class Box: + def __init__(self, a=None, b=None, c=None, uid=None): + self.type = 'bar' + self.a = a + self.b = b + self.c = c + self.uid = uid + + +# Fixtures +# -------- +@pytest.fixture() +def validator(): + return BaseTracesValidator(class_map={'scatter': Scatter, 'bar': Bar, 'box': Box}) + + +# Tests +# ----- +def test_acceptance(validator: BaseTracesValidator): + val = [Scatter(a=1, c=[3]), Box(b='two')] + res = validator.validate_coerce(val) + + assert isinstance(res, tuple) + assert isinstance(res[0], Scatter) + assert res[0].a == 1 + assert res[0].b is None + assert res[0].c == [3] + assert res[0].uid is not None + + assert isinstance(res[1], Box) + assert res[1].a is None + assert res[1].b == 'two' + assert res[1].c is None + assert res[1].uid is not None + + # Make sure UIDs are actually unique + assert res[0].uid != res[1].uid + + +def test_acceptance_dict(validator: BaseTracesValidator): + val = (dict(type='scatter', a=1, c=[3]), dict(type='box', b='two')) + res = validator.validate_coerce(val) + + assert isinstance(res, tuple) + assert isinstance(res[0], Scatter) + assert res[0].a == 1 + assert res[0].b is None + assert res[0].c == [3] + assert res[0].uid is not None + + assert isinstance(res[1], Box) + assert res[1].a is None + assert res[1].b == 'two' + assert res[1].c is None + assert res[1].uid is not None + + # Make sure UIDs are actually unique + assert res[0].uid != res[1].uid + + +def test_default_is_scatter(validator: BaseTracesValidator): + val = [dict(a=1, c=[3])] + res = validator.validate_coerce(val) + + assert isinstance(res, tuple) + assert isinstance(res[0], Scatter) + assert res[0].a == 1 + assert res[0].b is None + assert res[0].c == [3] + assert res[0].uid is not None + + +def test_uid_preserved(validator: BaseTracesValidator): + uid1 = 'qwerty' + uid2 = 'asdf' + val = (dict(type='scatter', a=1, c=[3], uid=uid1), dict(type='box', b='two', uid=uid2)) + res = validator.validate_coerce(val) + + assert isinstance(res, tuple) + assert isinstance(res[0], Scatter) + assert res[0].a == 1 + assert res[0].b is None + assert res[0].c == [3] + assert res[0].uid == uid1 + + assert isinstance(res[1], Box) + assert res[1].a is None + assert res[1].b == 'two' + assert res[1].c is None + assert res[1].uid == uid2 + + +def test_rejection_type(validator: BaseTracesValidator): + val = 37 + + with pytest.raises(ValueError) as validation_failure: + validator.validate_coerce(val) + + assert "Invalid value" in str(validation_failure.value) + + +def test_rejection_element_type(validator: BaseTracesValidator): + val = [42] + + with pytest.raises(ValueError) as validation_failure: + validator.validate_coerce(val) + + assert "Invalid element(s)" in str(validation_failure.value) + + +def test_rejection_element_attr(validator: BaseTracesValidator): + val = [dict(type='scatter', bogus=99)] + + with pytest.raises(TypeError) as validation_failure: + validator.validate_coerce(val) + + assert "got an unexpected keyword argument 'bogus'" in str(validation_failure.value) + + +def test_rejection_element_tracetype(validator: BaseTracesValidator): + val = [dict(type='bogus', a=4)] + + with pytest.raises(ValueError) as validation_failure: + validator.validate_coerce(val) + + assert "Invalid element(s)" in str(validation_failure.value) diff --git a/ipyplotly/test/validators/test_boolean_validator.py b/ipyplotly/test/validators/test_boolean_validator.py new file mode 100644 index 00000000000..dcc67ddab4a --- /dev/null +++ b/ipyplotly/test/validators/test_boolean_validator.py @@ -0,0 +1,27 @@ +import pytest +from ipyplotly.basevalidators import BooleanValidator +import numpy as np + + +# Boolean Validator +# ================= +# ### Fixtures ### +@pytest.fixture(params=[True, False]) +def validator(request): + return BooleanValidator('prop', 'parent', dflt=request.param) + + +# ### Acceptance ### +@pytest.mark.parametrize('val', [True, False]) +def test_acceptance(val, validator): + assert val == validator.validate_coerce(val) + + +# ### Rejection ### +@pytest.mark.parametrize('val', + [1.0, 0.0, 'True', 'False', [], 0, np.nan]) +def test_rejection(val, validator): + with pytest.raises(ValueError) as validation_failure: + validator.validate_coerce(val) + + assert 'Invalid value' in str(validation_failure.value) diff --git a/ipyplotly/test/validators/test_color_validator.py b/ipyplotly/test/validators/test_color_validator.py new file mode 100644 index 00000000000..fee944e7071 --- /dev/null +++ b/ipyplotly/test/validators/test_color_validator.py @@ -0,0 +1,182 @@ +import pytest +from ipyplotly.basevalidators import ColorValidator +import numpy as np + + +# Fixtures +# -------- +@pytest.fixture() +def validator(): + return ColorValidator('prop', 'parent') + + +@pytest.fixture() +def validator_colorscale(): + return ColorValidator('prop', 'parent', colorscale_path='parent.colorscale') + + +@pytest.fixture() +def validator_aok(): + return ColorValidator('prop', 'parent', array_ok=True) + + +@pytest.fixture() +def validator_aok_colorscale(): + return ColorValidator('prop', 'parent', array_ok=True, colorscale_path='parent.colorscale') + + +# Array not ok, numbers not ok +# ---------------------------- +@pytest.mark.parametrize('val', + ['red', 'BLUE', 'rgb(255, 0, 0)', 'hsl(0, 100%, 50%)', 'hsla(0, 100%, 50%, 100%)', + 'hsv(0, 100%, 100%)', 'hsva(0, 100%, 100%, 50%)']) +def test_acceptance(val, validator: ColorValidator): + if isinstance(val, str): + assert validator.validate_coerce(val) == str.replace(val.lower(), ' ', '') + else: + assert validator.validate_coerce(val) == val + + +# ### Rejection by type ### +@pytest.mark.parametrize('val', + [set(), 23, 0.5, {}, ['red'], [12]]) +def test_rejection(val, validator: ColorValidator): + with pytest.raises(ValueError) as validation_failure: + validator.validate_coerce(val) + + assert 'Invalid value' in str(validation_failure.value) + + +# ### Rejection by value ### +@pytest.mark.parametrize('val', + ['redd', 'rgbbb(255, 0, 0)', 'hsl(0, 1%0000%, 50%)']) +def test_rejection(val, validator: ColorValidator): + with pytest.raises(ValueError) as validation_failure: + validator.validate_coerce(val) + + assert 'Invalid value' in str(validation_failure.value) + + +# Array not ok, numbers ok +# ------------------------ +# ### Acceptance ### +@pytest.mark.parametrize('val', + ['red', 'BLUE', 23, 15, 'rgb(255, 0, 0)', 'hsl(0, 100%, 50%)', 'hsla(0, 100%, 50%, 100%)', + 'hsv(0, 100%, 100%)', 'hsva(0, 100%, 100%, 50%)']) +def test_acceptance_colorscale(val, validator_colorscale: ColorValidator): + if isinstance(val, str): + assert validator_colorscale.validate_coerce(val) == str.replace(val.lower(), ' ', '') + else: + assert validator_colorscale.validate_coerce(val) == val + + +# ### Rejection by type ### +@pytest.mark.parametrize('val', + [set(), {}, ['red'], [12]]) +def test_rejection_colorscale(val, validator_colorscale: ColorValidator): + with pytest.raises(ValueError) as validation_failure: + validator_colorscale.validate_coerce(val) + + assert 'Invalid value' in str(validation_failure.value) + + +# ### Rejection by value ### +@pytest.mark.parametrize('val', + ['redd', 'rgbbb(255, 0, 0)', 'hsl(0, 1%0000%, 50%)']) +def test_rejection_colorscale(val, validator_colorscale: ColorValidator): + with pytest.raises(ValueError) as validation_failure: + validator_colorscale.validate_coerce(val) + + assert 'Invalid value' in str(validation_failure.value) + + +# Array ok, numbers not ok +# ------------------------ +# ### Acceptance ### +@pytest.mark.parametrize('val', + ['blue', + ['red', 'rgb(255, 0, 0)'], + ['hsl(0, 100%, 50%)', 'hsla(0, 100%, 50%, 100%)', 'hsv(0, 100%, 100%)'], + ['hsva(0, 100%, 100%, 50%)']]) +def test_acceptance_aok(val, validator_aok: ColorValidator): + coerce_val = validator_aok.validate_coerce(val) + if isinstance(val, (list, np.ndarray)): + expected = np.array( + [str.replace(v.lower(), ' ', '') if isinstance(v, str) else v for v in val], + dtype=coerce_val.dtype) + assert np.array_equal(coerce_val, expected) + else: + expected = str.replace(val.lower(), ' ', '') if isinstance(val, str) else val + assert coerce_val == expected + + +# ### Rejection ### +@pytest.mark.parametrize('val', + [[23], [0, 1, 2], + ['redd', 'rgb(255, 0, 0)'], + ['hsl(0, 100%, 50_00%)', 'hsla(0, 100%, 50%, 100%)', 'hsv(0, 100%, 100%)'], + ['hsva(0, 1%00%, 100%, 50%)']]) +def test_rejection_aok(val, validator_aok: ColorValidator): + with pytest.raises(ValueError) as validation_failure: + validator_aok.validate_coerce(val) + + assert 'Invalid element(s)' in str(validation_failure.value) + + +# Array ok, numbers ok +# -------------------- +# ### Acceptance ### +@pytest.mark.parametrize('val', + ['blue', 23, [0, 1, 2], + ['red', 0.5, 'rgb(255, 0, 0)'], + ['hsl(0, 100%, 50%)', 'hsla(0, 100%, 50%, 100%)', 'hsv(0, 100%, 100%)'], + ['hsva(0, 100%, 100%, 50%)']]) +def test_acceptance_aok_colorscale(val, validator_aok_colorscale: ColorValidator): + coerce_val = validator_aok_colorscale.validate_coerce(val) + if isinstance(val, (list, np.ndarray)): + expected = np.array( + [str.replace(v.lower(), ' ', '') if isinstance(v, str) else v for v in val], + dtype=coerce_val.dtype) + assert np.array_equal(coerce_val, expected) + else: + expected = str.replace(val.lower(), ' ', '') if isinstance(val, str) else val + assert coerce_val == expected + + +# ### Rejection ### +@pytest.mark.parametrize('val', + [['redd', 0.5, 'rgb(255, 0, 0)'], + ['hsl(0, 100%, 50_00%)', 'hsla(0, 100%, 50%, 100%)', 'hsv(0, 100%, 100%)'], + ['hsva(0, 1%00%, 100%, 50%)']]) +def test_rejection_aok_colorscale(val, validator_aok_colorscale: ColorValidator): + with pytest.raises(ValueError) as validation_failure: + validator_aok_colorscale.validate_coerce(val) + + assert 'Invalid element(s)' in str(validation_failure.value) + + +# Description +# ----------- +# Test dynamic description logic +def test_description(validator: ColorValidator): + desc = validator.description() + assert 'A number that will be interpreted as a color' not in desc + assert 'A list or array of any of the above' not in desc + + +def test_description_aok(validator_aok: ColorValidator): + desc = validator_aok.description() + assert 'A number that will be interpreted as a color' not in desc + assert 'A list or array of any of the above' in desc + + +def test_description_aok(validator_colorscale: ColorValidator): + desc = validator_colorscale.description() + assert 'A number that will be interpreted as a color' in desc + assert 'A list or array of any of the above' not in desc + + +def test_description_aok_colorscale(validator_aok_colorscale: ColorValidator): + desc = validator_aok_colorscale.description() + assert 'A number that will be interpreted as a color' in desc + assert 'A list or array of any of the above' in desc diff --git a/ipyplotly/test/validators/test_colorscale_validator.py b/ipyplotly/test/validators/test_colorscale_validator.py new file mode 100644 index 00000000000..bdf6b4b3a59 --- /dev/null +++ b/ipyplotly/test/validators/test_colorscale_validator.py @@ -0,0 +1,95 @@ +import pytest +from ipyplotly.basevalidators import ColorscaleValidator +import numpy as np + + +# Fixtures +# -------- +@pytest.fixture() +def validator(): + return ColorscaleValidator('prop', 'parent') + + +@pytest.fixture(params=['Greys', 'YlGnBu', 'Greens', 'YlOrRd', 'Bluered', 'RdBu', 'Reds', 'Blues', + 'Picnic', 'Rainbow', 'Portland', 'Jet', 'Hot', 'Blackbody', 'Earth', 'Electric', 'Viridis']) +def named_colorscale(request): + return request.param + + +# Tests +# ----- +# ### Acceptance by name ### +def test_acceptance_named(named_colorscale, validator: ColorscaleValidator): + assert validator.validate_coerce(named_colorscale) == named_colorscale + + +# ### Acceptance as array ### +@pytest.mark.parametrize('val', [ + ((0, 'red'),), + ((0.1, 'rgb(255,0,0)'), (0.3, 'green')), + ((0, 'purple'), (0.2, 'yellow'), (1.0, 'rgba(255,0,0,100)')), +]) +def test_acceptance_array(val, validator: ColorscaleValidator): + assert validator.validate_coerce(val) == val + + +# ### Coercion of scale names ### +def test_coercion_named(named_colorscale, validator: ColorscaleValidator): + # As is + assert validator.validate_coerce(named_colorscale) == named_colorscale + + # Uppercase + assert validator.validate_coerce(named_colorscale.upper()) == named_colorscale + + # Lowercase + assert validator.validate_coerce(named_colorscale.lower()) == named_colorscale + + +# ### Coercion as array ### +@pytest.mark.parametrize('val', [ + ([0, 'red'],), + [(0.1, 'rgb(255, 0, 0)'), (0.3, 'GREEN')], + (np.array([0, 'Purple'], dtype='object'), (0.2, 'yellow'), (1.0, 'RGBA(255,0,0,100)')), +]) +def test_acceptance_array(val, validator: ColorscaleValidator): + # Compute expected (tuple of tuples where color is lowercase with no spaces) + expected = tuple([tuple([e[0], str.replace(e[1].lower(), ' ', '')]) for e in val]) + assert validator.validate_coerce(val) == expected + + +# ### Rejection by type ### +@pytest.mark.parametrize('val', [ + 23, set(), {}, np.pi +]) +def test_rejection_type(val, validator: ColorscaleValidator): + with pytest.raises(ValueError) as validation_failure: + validator.validate_coerce(val) + + assert 'Invalid value' in str(validation_failure.value) + + +# ### Rejection by string value ### +@pytest.mark.parametrize('val', [ + 'Invalid', '' +]) +def test_rejection_str_value(val, validator: ColorscaleValidator): + with pytest.raises(ValueError) as validation_failure: + validator.validate_coerce(val) + + assert 'Invalid value' in str(validation_failure.value) + + +# ### Rejection by array ### +@pytest.mark.parametrize('val', [ + [0, 'red'], # Elements must be tuples + [[0.1, 'rgb(255,0,0)', None], (0.3, 'green')], # length 3 element + ([1.1, 'purple'], [0.2, 'yellow']), # Number > 1 + ([0.1, 'purple'], [-0.2, 'yellow']), # Number < 0 + ([0.1, 'purple'], [0.2, 123]), # Color not a string + ([0.1, 'purple'], [0.2, 'yellowww']), # Invalid color string +]) +def test_rejection_array(val, validator: ColorscaleValidator): + with pytest.raises(ValueError) as validation_failure: + validator.validate_coerce(val) + + assert 'Invalid value' in str(validation_failure.value) diff --git a/ipyplotly/test/validators/test_compound_validator.py b/ipyplotly/test/validators/test_compound_validator.py new file mode 100644 index 00000000000..fda57a8b4e8 --- /dev/null +++ b/ipyplotly/test/validators/test_compound_validator.py @@ -0,0 +1,69 @@ +import pytest +from ipyplotly.basevalidators import CompoundValidator + + +# Build test class +# ---------------- +class CompoundType: + def __init__(self, a=None, b=None, c=None): + self.a = a + self.b = b + self.c = c + self._props = {'a': a, 'b': b, 'c': c} + + +# Fixtures +# -------- +@pytest.fixture() +def validator(): + return CompoundValidator('prop', 'parent', data_class=CompoundType, data_docs='') + + +# Tests +# ----- +def test_acceptance(validator: CompoundValidator): + val = CompoundType(a=1, c=[3]) + res = validator.validate_coerce(val) + + assert isinstance(res, CompoundType) + assert res.a == 1 + assert res.b is None + assert res.c == [3] + + +def test_acceptance_none(validator: CompoundValidator): + val = None + res = validator.validate_coerce(val) + + assert isinstance(res, CompoundType) + assert res.a is None + assert res.b is None + assert res.c is None + + +def test_acceptance_dict(validator: CompoundValidator): + val = dict(a=1, b='two') + res = validator.validate_coerce(val) + + assert isinstance(res, CompoundType) + assert res.a == 1 + assert res.b == 'two' + assert res.c is None + + +def test_rejection_type(validator: CompoundValidator): + val = 37 + + with pytest.raises(ValueError) as validation_failure: + validator.validate_coerce(val) + + assert "Invalid value" in str(validation_failure.value) + + +def test_rejection_value(validator: CompoundValidator): + val = dict(a=1, b='two', bogus=99) + + with pytest.raises(TypeError) as validation_failure: + validator.validate_coerce(val) + + assert "got an unexpected keyword argument 'bogus'" in str(validation_failure.value) diff --git a/ipyplotly/test/validators/test_compoundarray_validator.py b/ipyplotly/test/validators/test_compoundarray_validator.py new file mode 100644 index 00000000000..42e0bb71c11 --- /dev/null +++ b/ipyplotly/test/validators/test_compoundarray_validator.py @@ -0,0 +1,90 @@ +import pytest +from ipyplotly.basevalidators import CompoundArrayValidator + + +# Build test class +# ---------------- +class CompoundType: + def __init__(self, a=None, b=None, c=None): + self.a = a + self.b = b + self.c = c + + +# Fixtures +# -------- +@pytest.fixture() +def validator(): + return CompoundArrayValidator('prop', 'parent', element_class=CompoundType, element_docs='') + + +# Tests +# ----- +def test_acceptance(validator: CompoundArrayValidator): + val = [CompoundType(a=1, c=[3]), CompoundType(b='two')] + res = validator.validate_coerce(val) + + assert isinstance(res, tuple) + assert isinstance(res[0], CompoundType) + assert res[0].a == 1 + assert res[0].b is None + assert res[0].c == [3] + + assert isinstance(res[1], CompoundType) + assert res[1].a is None + assert res[1].b == 'two' + assert res[1].c is None + + +def test_acceptance_empty(validator: CompoundArrayValidator): + val = [{}] + res = validator.validate_coerce(val) + + assert isinstance(res, tuple) + assert isinstance(res[0], CompoundType) + assert res[0].a is None + assert res[0].b is None + assert res[0].c is None + + +def test_acceptance_dict(validator: CompoundArrayValidator): + val = [dict(a=1, c=[3]), dict(b='two')] + res = validator.validate_coerce(val) + + assert isinstance(res, tuple) + assert isinstance(res[0], CompoundType) + assert res[0].a == 1 + assert res[0].b is None + assert res[0].c == [3] + + assert isinstance(res[1], CompoundType) + assert res[1].a is None + assert res[1].b == 'two' + assert res[1].c is None + + +def test_rejection_type(validator: CompoundArrayValidator): + val = 37 + + with pytest.raises(ValueError) as validation_failure: + validator.validate_coerce(val) + + assert "Invalid value" in str(validation_failure.value) + + +def test_rejection_element(validator: CompoundArrayValidator): + val = [{'a': 23}, 37] + + with pytest.raises(ValueError) as validation_failure: + validator.validate_coerce(val) + + assert "Invalid element(s)" in str(validation_failure.value) + + +def test_rejection_value(validator: CompoundArrayValidator): + val = [dict(a=1, b='two', bogus=99)] + + with pytest.raises(TypeError) as validation_failure: + validator.validate_coerce(val) + + assert "got an unexpected keyword argument 'bogus'" in str(validation_failure.value) diff --git a/ipyplotly/test/validators/test_dataarray_validator.py b/ipyplotly/test/validators/test_dataarray_validator.py new file mode 100644 index 00000000000..853db71cc66 --- /dev/null +++ b/ipyplotly/test/validators/test_dataarray_validator.py @@ -0,0 +1,33 @@ +import pytest +from ipyplotly.basevalidators import DataArrayValidator +import numpy as np + + +# Fixtures +# -------- +@pytest.fixture() +def validator(): + return DataArrayValidator('prop', 'parent') + + +# Tests +# ----- +# ### Acceptance ### +@pytest.mark.parametrize('val', [ + [], [1], np.array([2, 3, 4]), [''], (), ('Hello, ', 'world!') +]) +def test_validator_acceptance(val, validator: DataArrayValidator): + coerce_val = validator.validate_coerce(val) + assert isinstance(coerce_val, np.ndarray) + assert np.array_equal(coerce_val, val) + + +# ### Rejection ### +@pytest.mark.parametrize('val', [ + 'Hello', 23, set(), {}, +]) +def test_rejection(val, validator: DataArrayValidator): + with pytest.raises(ValueError) as validation_failure: + validator.validate_coerce(val) + + assert 'Invalid value' in str(validation_failure.value) diff --git a/ipyplotly/test/validators/test_enumerated_validator.py b/ipyplotly/test/validators/test_enumerated_validator.py new file mode 100644 index 00000000000..17e6c4bd54f --- /dev/null +++ b/ipyplotly/test/validators/test_enumerated_validator.py @@ -0,0 +1,131 @@ +import pytest +import numpy as np +from ipyplotly.basevalidators import EnumeratedValidator + + +# Fixtures +# -------- +@pytest.fixture() +def validator(): + values = ['first', 'second', 'third', 4] + return EnumeratedValidator('prop', 'parent', values, array_ok=False) + + +@pytest.fixture() +def validator_re(): + values = ['foo', '/bar(\d)+/', 'baz'] + return EnumeratedValidator('prop', 'parent', values, array_ok=False) + + +@pytest.fixture() +def validator_aok(): + values = ['first', 'second', 'third', 4] + return EnumeratedValidator('prop', 'parent', values, array_ok=True) + + +@pytest.fixture() +def validator_aok_re(): + values = ['foo', '/bar(\d)+/', 'baz'] + return EnumeratedValidator('prop', 'parent', values, array_ok=True) + + +# Array not ok +# ------------ +# ### Acceptance ### +@pytest.mark.parametrize('val', + ['first', 'second', 'third', 4]) +def test_acceptance(val, validator): + # Values should be accepted and returned unchanged + assert validator.validate_coerce(val) == val + + +# ### Value Rejection ### +@pytest.mark.parametrize('val', + [True, 0, 1, 23, np.inf, set(), + ['first', 'second'], [True], ['third', 4], [4]]) +def test_rejection_by_value(val, validator): + with pytest.raises(ValueError) as validation_failure: + validator.validate_coerce(val) + + assert 'Invalid value' in str(validation_failure.value) + + +# Array not ok, regular expression +# -------------------------------- +@pytest.mark.parametrize('val', + ['foo', 'bar0', 'bar1', 'bar234']) +def test_acceptance(val, validator_re): + # Values should be accepted and returned unchanged + assert validator_re.validate_coerce(val) == val + + +# ### Value Rejection ### +@pytest.mark.parametrize('val', + [12, set(), 'bar', 'BAR0', 'FOO']) +def test_rejection_by_value(val, validator_re): + with pytest.raises(ValueError) as validation_failure: + validator_re.validate_coerce(val) + + assert 'Invalid value' in str(validation_failure.value) + + +# Array ok +# -------- +# ### Acceptance ### +@pytest.mark.parametrize('val', + ['first', 'second', 'third', 4, + [], ['first', 4], [4], ['third', 'first'], + ['first', 'second', 'third', 4]]) +def test_acceptance_aok(val, validator_aok): + # Values should be accepted and returned unchanged + coerce_val = validator_aok.validate_coerce(val) + if isinstance(val, (list, np.ndarray)): + assert np.array_equal(coerce_val, np.array(val, dtype=coerce_val.dtype)) + else: + assert coerce_val == val + + +# ### Rejection by value ### +@pytest.mark.parametrize('val', + [True, 0, 1, 23, np.inf, set()]) +def test_rejection_by_value_aok(val, validator_aok): + with pytest.raises(ValueError) as validation_failure: + validator_aok.validate_coerce(val) + + assert 'Invalid value' in str(validation_failure.value) + + +# ### Reject by elements ### +@pytest.mark.parametrize('val', + [[True], [0], [1, 23], [np.inf, set()], + ['ffirstt', 'second', 'third']]) +def test_rejection_by_element_aok(val, validator_aok): + with pytest.raises(ValueError) as validation_failure: + validator_aok.validate_coerce(val) + + assert 'Invalid element(s)' in str(validation_failure.value) + + +# Array ok, regular expression +# ---------------------------- +# ### Acceptance ### +@pytest.mark.parametrize('val', + ['foo', 'bar12', 'bar21', + [], ['bar12'], ['foo', 'bar012', 'baz']]) +def test_acceptance_aok(val, validator_aok_re): + # Values should be accepted and returned unchanged + coerce_val = validator_aok_re.validate_coerce(val) + if isinstance(val, (list, np.ndarray)): + assert np.array_equal(coerce_val, np.array(val, dtype=coerce_val.dtype)) + else: + assert coerce_val == val + + +# ### Reject by elements ### +@pytest.mark.parametrize('val', + [['bar', 'bar0'], ['foo', 123]]) +def test_rejection_by_element_aok(val, validator_aok_re): + with pytest.raises(ValueError) as validation_failure: + validator_aok_re.validate_coerce(val) + + assert 'Invalid element(s)' in str(validation_failure.value) diff --git a/ipyplotly/test/validators/test_flaglist_validator.py b/ipyplotly/test/validators/test_flaglist_validator.py new file mode 100644 index 00000000000..692e4aaed82 --- /dev/null +++ b/ipyplotly/test/validators/test_flaglist_validator.py @@ -0,0 +1,184 @@ +import itertools +import pytest +from ipyplotly.basevalidators import FlaglistValidator +import numpy as np + + +# Fixtures +# -------- +@pytest.fixture(params=[None, ['none', 'all']]) +def validator(request): + # Validator with or without extras + return FlaglistValidator('prop', 'parent', flags=['lines', 'markers', 'text'], extras=request.param) + + +@pytest.fixture() +def validator_extra(): + return FlaglistValidator('prop', 'parent', + flags=['lines', 'markers', 'text'], + extras=['none', 'all']) + + +@pytest.fixture() +def validator_extra_aok(): + return FlaglistValidator('prop', 'parent', + flags=['lines', 'markers', 'text'], + extras=['none', 'all'], + array_ok=True) + + +@pytest.fixture(params= + ["+".join(p) + for i in range(1, 4) + for p in itertools.permutations(['lines', 'markers', 'text'], i)]) +def flaglist(request): + return request.param + + +@pytest.fixture(params=['none', 'all']) +def extra(request): + return request.param + + +# Array not ok (with or without extras) +# ------------------------------------- +# ### Acceptance ### +def test_acceptance(flaglist, validator: FlaglistValidator): + assert validator.validate_coerce(flaglist) == flaglist + + +# ### Coercion ### +@pytest.mark.parametrize('in_val,coerce_val', + [(' lines ', 'lines'), # Strip outer whitespace + (' lines + markers ', 'lines+markers'), # Remove inner whitespace around '+' + ('lines ,markers', 'lines+markers'), # Accept comma separated + ]) +def test_coercion(in_val, coerce_val, validator): + assert validator.validate_coerce(in_val) == coerce_val + + +# ### Rejection by type ### +@pytest.mark.parametrize('val', + [21, (), ['lines'], set(), {}]) +def test_rejection_type(val, validator: FlaglistValidator): + with pytest.raises(ValueError) as validation_failure: + validator.validate_coerce(val) + + assert 'Invalid value' in str(validation_failure.value) + + +# ### Rejection by value ### +@pytest.mark.parametrize('val', + ['', 'line', 'markers+line', 'lin es', 'lin es+markers']) +def test_rejection_val(val, validator: FlaglistValidator): + with pytest.raises(ValueError) as validation_failure: + validator.validate_coerce(val) + + assert 'Invalid value' in str(validation_failure.value) + + +# Array not ok (with extras) +# -------------------------- +# ### Acceptance ### +# Note: Acceptance of flaglists without extras already tested above +def test_acceptance_extra(extra, validator_extra: FlaglistValidator): + assert validator_extra.validate_coerce(extra) == extra + + +# ### Coercion ### +@pytest.mark.parametrize('in_val,coerce_val', + [(' none ', 'none'), + ('all ', 'all'), + ]) +def test_coercion(in_val, coerce_val, validator_extra): + assert validator_extra.validate_coerce(in_val) == coerce_val + + +# ### Rejection by value ### +# Note: Rejection by type already handled above +@pytest.mark.parametrize('val', + ['al l', # Don't remove inner whitespace + 'lines+all', # Extras cannot be combined with flags + 'none+markers', + 'markers+lines+text+none']) +def test_rejection_val(val, validator_extra: FlaglistValidator): + with pytest.raises(ValueError) as validation_failure: + validator_extra.validate_coerce(val) + + assert 'Invalid value' in str(validation_failure.value) + + +# Array OK (with extras) +# ---------------------- +# ### Acceptance (scalars) ### +def test_acceptance_aok_scalar_flaglist(flaglist, validator_extra_aok: FlaglistValidator): + assert validator_extra_aok.validate_coerce(flaglist) == flaglist + + +def test_acceptance_aok_scalar_extra(extra, validator_extra_aok: FlaglistValidator): + assert validator_extra_aok.validate_coerce(extra) == extra + + +# ### Acceptance (lists) ### +def test_acceptance_aok_scalarlist_flaglist(flaglist, validator_extra_aok: FlaglistValidator): + assert np.array_equal(validator_extra_aok.validate_coerce([flaglist]), + np.array([flaglist], dtype='unicode')) + + +@pytest.mark.parametrize('val', [ + ['all', 'markers', 'text+markers'], + ['lines', 'lines+markers', 'markers+lines+text'], + ['all', 'all', 'lines+text', 'none'] +]) +def test_acceptance_aok_list_flaglist(val, validator_extra_aok: FlaglistValidator): + assert np.array_equal(validator_extra_aok.validate_coerce(val), + np.array(val, dtype='unicode')) + + +# ### Coercion ### +@pytest.mark.parametrize('in_val,coerce_val', + [([' lines ', ' lines + markers ', 'lines ,markers'], + np.array(['lines', 'lines+markers', 'lines+markers'], dtype='unicode') + ), + (np.array(['text +lines']), + np.array(['text+lines'], dtype='unicode') + ) + ]) +def test_coercion_aok(in_val, coerce_val, validator_extra_aok): + assert np.array_equal(validator_extra_aok.validate_coerce(in_val), coerce_val) + + +# ### Rejection by type ### +@pytest.mark.parametrize('val', + [21, set(), {}]) +def test_rejection_aok_type(val, validator_extra_aok: FlaglistValidator): + with pytest.raises(ValueError) as validation_failure: + validator_extra_aok.validate_coerce(val) + + assert 'Invalid value' in str(validation_failure.value) + + +# ### Rejection by element type ### +@pytest.mark.parametrize('val', + [[21, 'markers'], + ['lines', ()], + ['none', set()], + ['lines+text', {}, 'markers']]) +def test_rejection_aok_element_type(val, validator_extra_aok: FlaglistValidator): + with pytest.raises(ValueError) as validation_failure: + validator_extra_aok.validate_coerce(val) + + assert 'Invalid element(s)' in str(validation_failure.value) + + +# ### Rejection by element values ### +@pytest.mark.parametrize('val', [ + ['all+markers', 'text+markers'], # extra plus flag + ['line', 'lines+markers', 'markers+lines+text'], # Invalid flag + ['all', '', 'lines+text', 'none'] # Empty string +]) +def test_rejection_aok_element_val(val, validator_extra_aok: FlaglistValidator): + with pytest.raises(ValueError) as validation_failure: + validator_extra_aok.validate_coerce(val) + + assert 'Invalid element(s)' in str(validation_failure.value) diff --git a/ipyplotly/test/validators/test_imageuri_validator.py b/ipyplotly/test/validators/test_imageuri_validator.py new file mode 100644 index 00000000000..93abadb62d8 --- /dev/null +++ b/ipyplotly/test/validators/test_imageuri_validator.py @@ -0,0 +1,49 @@ +import base64 + +import pytest +from ipyplotly.basevalidators import ImageUriValidator +import numpy as np +from PIL import Image + + +# Fixtures +# -------- +@pytest.fixture() +def validator(): + return ImageUriValidator('prop', 'parent') + + +# Tests +# ----- +# ### Acceptance ### +@pytest.mark.parametrize('val', [ + 'http://somewhere.com/images/image12.png', + 'data:image/png;base64,iVBORw0KGgoAAAANSU', +]) +def test_validator_acceptance(val, validator: ImageUriValidator): + assert validator.validate_coerce(val) == val + + +# ### Coercion from PIL Image ### +def test_validator_coercion_PIL(validator: ImageUriValidator): + # Single pixel black png (http://png-pixel.com/) + + img_path = 'test/resources/1x1-black.png' + with open(img_path, 'rb') as f: + hex_bytes = base64.b64encode(f.read()).decode('ascii') + expected_uri = 'data:image/png;base64,' + hex_bytes + + img = Image.open(img_path) + coerce_val = validator.validate_coerce(img) + assert coerce_val == expected_uri + + +# ### Rejection ### +@pytest.mark.parametrize('val', [ + 23, set(), [] +]) +def test_rejection_by_type(val, validator): + with pytest.raises(ValueError) as validation_failure: + validator.validate_coerce(val) + + assert 'Invalid value' in str(validation_failure.value) diff --git a/ipyplotly/test/validators/test_infoarray_validator.py b/ipyplotly/test/validators/test_infoarray_validator.py new file mode 100644 index 00000000000..b3032589ac3 --- /dev/null +++ b/ipyplotly/test/validators/test_infoarray_validator.py @@ -0,0 +1,158 @@ +import pytest +from ipyplotly.basevalidators import InfoArrayValidator, type_str +import numpy as np + + +# Fixtures +# -------- +@pytest.fixture() +def validator_any2(): + return InfoArrayValidator('prop', 'parent', items=[{'valType': 'any'}, {'valType': 'any'}]) + + +@pytest.fixture() +def validator_number3(): + return InfoArrayValidator('prop', 'parent', items=[ + {'valType': 'number', 'min': 0, 'max': 1}, + {'valType': 'number', 'min': 0, 'max': 1}, + {'valType': 'number', 'min': 0, 'max': 1}]) + + +@pytest.fixture() +def validator_number3_free(): + return InfoArrayValidator('prop', 'parent', items=[ + {'valType': 'number', 'min': 0, 'max': 1}, + {'valType': 'number', 'min': 0, 'max': 1}, + {'valType': 'number', 'min': 0, 'max': 1}], free_length=True) + + +# Any2 Tests +# ---------- + +# ### Acceptance ### +@pytest.mark.parametrize('val', [ + [1, 'A'], ('hello', 'world!'), [{}, []], [-1, 1] +]) +def test_validator_acceptance_any2(val, validator_any2: InfoArrayValidator): + coerce_val = validator_any2.validate_coerce(val) + assert np.array_equal(coerce_val, tuple(val)) + + +# ### Rejection by type ### +@pytest.mark.parametrize('val', [ + 'Not a list', 123, set(), {} +]) +def test_validator_rejection_any2_type(val, validator_any2: InfoArrayValidator): + with pytest.raises(ValueError) as validation_failure: + validator_any2.validate_coerce(val) + + assert 'must be a list or tuple.' in str(validation_failure.value) + + +# ### Rejection by length ### +@pytest.mark.parametrize('val', [ + [0, 1, 'A'], ('hello', 'world', '!'), [None, {}, []], [-1, 1, 9] +]) +def test_validator_rejection_any2_length(val, validator_any2: InfoArrayValidator): + with pytest.raises(ValueError) as validation_failure: + validator_any2.validate_coerce(val) + + assert 'Invalid value' in str(validation_failure.value) + + +# Number3 Tests +# ------------- +# ### Acceptance ### +@pytest.mark.parametrize('val', [ + [1, 0, 0.5], (0.1, 0.4, 0.99), [1, 1, 0] +]) +def test_validator_acceptance_number3(val, validator_number3: InfoArrayValidator): + coerce_val = validator_number3.validate_coerce(val) + assert np.array_equal(coerce_val, tuple(val)) + + +# ### Rejection by length ### +@pytest.mark.parametrize('val', [ + [1, 0], (0.1, 0.4, 0.99, 0.4), [1] +]) +def test_validator_rejection_number3_length(val, validator_number3: InfoArrayValidator): + with pytest.raises(ValueError) as validation_failure: + validator_number3.validate_coerce(val) + + assert 'must be a list or tuple of length 3.' in str(validation_failure.value) + + +# ### Rejection by element type ### +@pytest.mark.parametrize('val,first_invalid_ind', [ + ([1, 0, '0.5'], 2), + ((0.1, set(), 0.99), 1), + ([[], '2', {}], 0) +]) +def test_validator_rejection_number3_length(val, first_invalid_ind, validator_number3: InfoArrayValidator): + with pytest.raises(ValueError) as validation_failure: + validator_number3.validate_coerce(val) + + assert 'The prop[%d] property of parent must be a number.' % first_invalid_ind in str(validation_failure.value) + + +# ### Rejection by element value ### +# Elements must be in [0, 1] +@pytest.mark.parametrize('val,first_invalid_ind', [ + ([1, 0, 1.5], 2), + ((0.1, -0.4, 0.99), 1), + ([-1, 1, 0], 0) +]) +def test_validator_rejection_number3_length(val, first_invalid_ind, validator_number3: InfoArrayValidator): + with pytest.raises(ValueError) as validation_failure: + validator_number3.validate_coerce(val) + + assert ('The prop[%d] property of parent must be in the range [0, 1]' % first_invalid_ind + in str(validation_failure.value)) + + +# Number3 Tests (free_length=True) +# -------------------------------- +# ### Acceptance ### +@pytest.mark.parametrize('val', [ + [1, 0, 0.5], (0.1, 0.99), [0], [] +]) +def test_validator_acceptance_number3_free(val, validator_number3_free: InfoArrayValidator): + coerce_val = validator_number3_free.validate_coerce(val) + assert np.array_equal(coerce_val, tuple(val)) + + +# ### Rejection by type ### +@pytest.mark.parametrize('val', [ + 'Not a list', 123, set(), {} +]) +def test_validator_rejection_any2_type(val, validator_number3_free: InfoArrayValidator): + with pytest.raises(ValueError) as validation_failure: + validator_number3_free.validate_coerce(val) + + assert 'Invalid value' in str(validation_failure.value) + + +# ### Rejection by length ### +@pytest.mark.parametrize('val', [ + (0.1, 0.4, 0.99, 0.4), [1, 0, 0, 0, 0, 0, 0] +]) +def test_validator_rejection_number3_free_length(val, validator_number3_free: InfoArrayValidator): + with pytest.raises(ValueError) as validation_failure: + validator_number3_free.validate_coerce(val) + + assert 'Invalid value' in str(validation_failure.value) + + +# ### Rejection by element type ### +@pytest.mark.parametrize('val,first_invalid_ind', [ + ([1, 0, '0.5'], 2), + ((0.1, set()), 1), + ([[]], 0) +]) +def test_validator_rejection_number3_length(val, first_invalid_ind, validator_number3_free: InfoArrayValidator): + with pytest.raises(ValueError) as validation_failure: + validator_number3_free.validate_coerce(val) + + assert ("Invalid value of type {typ} received for the 'prop[{first_invalid_ind}]' property of parent" + .format(typ= type_str(val[first_invalid_ind]), + first_invalid_ind=first_invalid_ind)) in str(validation_failure.value) diff --git a/ipyplotly/test/validators/test_integer_validator.py b/ipyplotly/test/validators/test_integer_validator.py new file mode 100644 index 00000000000..bd34327fc6e --- /dev/null +++ b/ipyplotly/test/validators/test_integer_validator.py @@ -0,0 +1,157 @@ +# Array not ok +# ------------ +import pytest +from pytest import approx +from ipyplotly.basevalidators import IntegerValidator +import numpy as np + + +# ### Fixtures ### +@pytest.fixture() +def validator(): + return IntegerValidator('prop', 'parent') + + +@pytest.fixture +def validator_min_max(): + return IntegerValidator('prop', 'parent', min=-1, max=2) + + +@pytest.fixture +def validator_min(): + return IntegerValidator('prop', 'parent', min=-1) + + +@pytest.fixture +def validator_max(): + return IntegerValidator('prop', 'parent', max=2) + + +@pytest.fixture +def validator_aok(request): + return IntegerValidator('prop', 'parent', min=-2, max=10, array_ok=True) + + +# ### Acceptance ### +@pytest.mark.parametrize('val', + [1, -19, 0, -1234]) +def test_acceptance(val, validator: IntegerValidator): + assert validator.validate_coerce(val) == val + + +# ### Coercion ### +@pytest.mark.parametrize('val,expected', + [(1.0, 1), (-19.1, -19), (0.001, 0), (1234.9, 1234)]) +def test_coercion(val, expected, validator: IntegerValidator): + assert validator.validate_coerce(val) == expected + + +# ### Rejection by value ### +@pytest.mark.parametrize('val', + ['hello', (), [], [1, 2, 3], set(), '34', np.nan, np.inf, -np.inf]) +def test_rejection_by_value(val, validator: IntegerValidator): + with pytest.raises(ValueError) as validation_failure: + validator.validate_coerce(val) + + assert 'Invalid value' in str(validation_failure.value) + + +# ### With min/max ### +# min == -1 and max == 2 +@pytest.mark.parametrize('val', + [0, 1, -1, 2]) +def test_acceptance_min_max(val, validator_min_max: IntegerValidator): + assert validator_min_max.validate_coerce(val) == approx(val) + + +@pytest.mark.parametrize('val', + [-1.01, -10, 2.1, 3, np.iinfo(np.int).max, np.iinfo(np.int).min]) +def test_rejection_min_max(val, validator_min_max: IntegerValidator): + with pytest.raises(ValueError) as validation_failure: + validator_min_max.validate_coerce(val) + + assert 'in the interval [-1, 2]' in str(validation_failure.value) + + +# ### With min only ### +# min == -1 +@pytest.mark.parametrize('val', + [-1, 0, 1, 23, 99999]) +def test_acceptance_min(val, validator_min: IntegerValidator): + assert validator_min.validate_coerce(val) == approx(val) + + +@pytest.mark.parametrize('val', + [-2, -123, np.iinfo(np.int).min]) +def test_rejection_min(val, validator_min: IntegerValidator): + with pytest.raises(ValueError) as validation_failure: + validator_min.validate_coerce(val) + + assert 'in the interval [-1, 2147483647]' in str(validation_failure.value) + + +# ### With max only ### +# max == 2 +@pytest.mark.parametrize('val', + [1, 2, -10, -999999, np.iinfo(np.int32).min]) +def test_acceptance_max(val, validator_max: IntegerValidator): + assert validator_max.validate_coerce(val) == approx(val) + + +@pytest.mark.parametrize('val', + [3, 10, np.iinfo(np.int32).max]) +def test_rejection_max(val, validator_max: IntegerValidator): + with pytest.raises(ValueError) as validation_failure: + validator_max.validate_coerce(val) + + assert 'in the interval [-2147483648, 2]' in str(validation_failure.value) + + +# Array ok +# -------- +# min=-2 and max=10 +# ### Acceptance ### +@pytest.mark.parametrize('val', + [-2, 1, 0, 1, 10]) +def test_acceptance_aok_scalars(val, validator_aok: IntegerValidator): + assert validator_aok.validate_coerce(val) == val + + +@pytest.mark.parametrize('val', + [[1, 0], [1], [-2, 1, 8], np.array([3, 2, -1, 5])]) +def test_acceptance_aok_list(val, validator_aok: IntegerValidator): + assert np.array_equal(validator_aok.validate_coerce(val), val) + + +# ### Coerce ### +# Coerced to general consistent numeric type +@pytest.mark.parametrize('val,expected', + [([1.0, 0], [1, 0]), + (np.array([1.1, -1]), [1, -1]), + ([-1.9, 0, 5.1], [-1, 0, 5]), + (np.array([1, 0], dtype=np.int64), [1, 0])]) +def test_coercion_aok_list(val, expected, validator_aok: IntegerValidator): + v = validator_aok.validate_coerce(val) + assert v.dtype == np.int32 + assert np.array_equal(v, np.array(expected, dtype=np.int32)) + + +# ### Rejection ### +# +@pytest.mark.parametrize('val', + [['a', 4], [[], 3, 4]]) +def test_integer_validator_rejection_aok(val, validator_aok: IntegerValidator): + with pytest.raises(ValueError) as validation_failure: + validator_aok.validate_coerce(val) + + assert 'Invalid value' in str(validation_failure.value) + + +# ### Rejection by element ### +@pytest.mark.parametrize('val', + [[-1, 11], [1.5, -3], [0, np.iinfo(np.int32).max], [0, np.iinfo(np.int32).min]]) +def test_rejection_aok_min_max(val, validator_aok: IntegerValidator): + with pytest.raises(ValueError) as validation_failure: + validator_aok.validate_coerce(val) + + assert 'in the interval [-2, 10]' in str(validation_failure.value) diff --git a/ipyplotly/test/validators/test_number_validator.py b/ipyplotly/test/validators/test_number_validator.py new file mode 100644 index 00000000000..bc927a1ea3e --- /dev/null +++ b/ipyplotly/test/validators/test_number_validator.py @@ -0,0 +1,150 @@ +import pytest +from pytest import approx + +from ipyplotly.basevalidators import NumberValidator +import numpy as np + + +# Fixtures +# -------- +@pytest.fixture +def validator(request): + return NumberValidator('prop', 'parent') + + +@pytest.fixture +def validator_min_max(request): + return NumberValidator('prop', 'parent', min=-1.0, max=2.0) + + +@pytest.fixture +def validator_min(request): + return NumberValidator('prop', 'parent', min=-1.0) + + +@pytest.fixture +def validator_max(request): + return NumberValidator('prop', 'parent', max=2.0) + + +@pytest.fixture +def validator_aok(): + return NumberValidator('prop', 'parent', min=-1, max=1.5, array_ok=True) + + +# Array not ok +# ------------ +# ### Acceptance ### +@pytest.mark.parametrize('val', + [1.0, 0.0, 1, -1234.5678, 54321, np.pi, np.nan, np.inf, -np.inf]) +def test_acceptance(val, validator: NumberValidator): + assert validator.validate_coerce(val) == approx(val, nan_ok=True) + + +# ### Rejection by value ### +@pytest.mark.parametrize('val', + ['hello', (), [], [1, 2, 3], set(), '34']) +def test_rejection_by_value(val, validator: NumberValidator): + with pytest.raises(ValueError) as validation_failure: + validator.validate_coerce(val) + + assert 'Invalid value' in str(validation_failure.value) + + +# ### With min/max ### +@pytest.mark.parametrize('val', + [0, 0.0, -0.5, 1, 1.0, 2, 2.0, np.pi/2.0]) +def test_acceptance_min_max(val, validator_min_max: NumberValidator): + assert validator_min_max.validate_coerce(val) == approx(val) + + +@pytest.mark.parametrize('val', + [-1.01, -10, 2.1, 234, -np.inf, np.nan, np.inf]) +def test_rejection_min_max(val, validator_min_max: NumberValidator): + with pytest.raises(ValueError) as validation_failure: + validator_min_max.validate_coerce(val) + + assert 'in the interval [-1.0, 2.0]' in str(validation_failure.value) + + +# ### With min only ### +@pytest.mark.parametrize('val', + [0, 0.0, -0.5, 99999, np.inf]) +def test_acceptance_min(val, validator_min: NumberValidator): + assert validator_min.validate_coerce(val) == approx(val) + + +@pytest.mark.parametrize('val', + [-1.01, -np.inf, np.nan]) +def test_rejection_min(val, validator_min: NumberValidator): + with pytest.raises(ValueError) as validation_failure: + validator_min.validate_coerce(val) + + assert 'in the interval [-1.0, inf]' in str(validation_failure.value) + + +# ### With max only ### +@pytest.mark.parametrize('val', + [0, 0.0, -np.inf, -123456, np.pi/2]) +def test_acceptance_max(val, validator_max: NumberValidator): + assert validator_max.validate_coerce(val) == approx(val) + + +@pytest.mark.parametrize('val', + [2.01, np.inf, np.nan]) +def test_rejection_max(val, validator_max: NumberValidator): + with pytest.raises(ValueError) as validation_failure: + validator_max.validate_coerce(val) + + assert 'in the interval [-inf, 2.0]' in str(validation_failure.value) + + +# Array ok +# -------- +# ### Acceptance ### +@pytest.mark.parametrize('val', + [1.0, 0.0, 1, 0.4]) +def test_acceptance_aok_scalars(val, validator_aok: NumberValidator): + assert validator_aok.validate_coerce(val) == val + + +@pytest.mark.parametrize('val', + [[1.0, 0.0], [1], [-0.1234, .41, -1.0]]) +def test_acceptance_aok_list(val, validator_aok: NumberValidator): + assert np.array_equal(validator_aok.validate_coerce(val), np.array(val, dtype='float')) + + +# ### Coerce ### +# Coerced to general consistent numeric type +@pytest.mark.parametrize('val,expected', + [([1.0, 0], np.array([1.0, 0.0])), + (np.array([1, -1]), np.array([1.0, -1.0])), + ([-0.1234, 0, -1], np.array([-0.1234, 0.0, -1.0]))]) +def test_coercion_aok_list(val, expected, validator_aok: NumberValidator): + v = validator_aok.validate_coerce(val) + assert isinstance(v, np.ndarray) + assert v.dtype == 'float' + assert np.array_equal(v, expected) + + +# ### Rejection ### +# +@pytest.mark.parametrize('val', + [['a', 4]]) +def test_rejection_aok(val, validator_aok: NumberValidator): + with pytest.raises(ValueError) as validation_failure: + validator_aok.validate_coerce(val) + + assert 'Invalid value' in str(validation_failure.value) + + +# ### Rejection by element ### +@pytest.mark.parametrize('val', + [[-1.6, 0.0], [1, 1.5, 2], [-0.1234, .41, np.nan], + [0, np.inf], [0, -np.inf]]) +def test_rejection_aok_min_max(val, validator_aok: NumberValidator): + with pytest.raises(ValueError) as validation_failure: + validator_aok.validate_coerce(val) + + assert 'Invalid element(s)' in str(validation_failure.value) + assert 'in the interval [-1, 1.5]' in str(validation_failure.value) diff --git a/ipyplotly/test/validators/test_string_validator.py b/ipyplotly/test/validators/test_string_validator.py new file mode 100644 index 00000000000..b7b9125ca9c --- /dev/null +++ b/ipyplotly/test/validators/test_string_validator.py @@ -0,0 +1,148 @@ +import pytest +from ipyplotly.basevalidators import StringValidator +import numpy as np + + +# Fixtures +# -------- +@pytest.fixture() +def validator(): + return StringValidator('prop', 'parent') + + +@pytest.fixture() +def validator_values(): + return StringValidator('prop', 'parent', values=['foo', 'BAR', '']) + + +@pytest.fixture() +def validator_no_blanks(): + return StringValidator('prop', 'parent', no_blank=True) + + +@pytest.fixture +def validator_aok(): + return StringValidator('prop', 'parent', array_ok=True) + + +@pytest.fixture +def validator_aok_values(): + return StringValidator('prop', 'parent', values=['foo', 'BAR', '', 'baz'], array_ok=True) + + +@pytest.fixture() +def validator_no_blanks_aok(): + return StringValidator('prop', 'parent', no_blank=True, array_ok=True) + + +# Array not ok +# ------------ +# ### Acceptance ### +@pytest.mark.parametrize('val', + ['bar', 'HELLO!!!', 'world!@#$%^&*()', '']) +def test_acceptance(val, validator: StringValidator): + assert validator.validate_coerce(val) == val + + +# ### Rejection by value ### +@pytest.mark.parametrize('val', + [(), [], [1, 2, 3], set(), np.nan, np.pi]) +def test_rejection(val, validator: StringValidator): + with pytest.raises(ValueError) as validation_failure: + validator.validate_coerce(val) + + assert 'Invalid value' in str(validation_failure.value) + + +# Valid values +# ------------ +@pytest.mark.parametrize('val', + ['foo', 'BAR', '']) +def test_acceptance_values(val, validator_values: StringValidator): + assert validator_values.validate_coerce(val) == val + + +@pytest.mark.parametrize('val', + ['FOO', 'bar', 'other', '1234']) +def test_rejection_values(val, validator_values: StringValidator): + with pytest.raises(ValueError) as validation_failure: + validator_values.validate_coerce(val) + + assert 'Invalid value'.format(val=val) in str(validation_failure.value) + assert "['foo', 'BAR', '']" in str(validation_failure.value) + + +# ### No blanks ### +@pytest.mark.parametrize('val', + ['bar', 'HELLO!!!', 'world!@#$%^&*()']) +def test_acceptance_no_blanks(val, validator_no_blanks: StringValidator): + assert validator_no_blanks.validate_coerce(val) == val + + +@pytest.mark.parametrize('val', + ['']) +def test_rejection_no_blanks(val, validator_no_blanks: StringValidator): + with pytest.raises(ValueError) as validation_failure: + validator_no_blanks.validate_coerce(val) + + assert 'A non-empty string' in str(validation_failure.value) + + +# Array ok +# -------- +# ### Acceptance ### +@pytest.mark.parametrize('val', + ['foo', 'BAR', '', 'baz']) +def test_acceptance_aok_scalars(val, validator_aok: StringValidator): + assert validator_aok.validate_coerce(val) == val + + +@pytest.mark.parametrize('val', + ['foo', ['foo'], np.array(['BAR', ''], dtype='object'), ['baz', 'baz', 'baz']]) +def test_acceptance_aok_list(val, validator_aok: StringValidator): + coerce_val = validator_aok.validate_coerce(val) + if isinstance(val, (list, np.ndarray)): + assert np.array_equal(coerce_val, np.array(val, dtype=coerce_val.dtype)) + else: + assert coerce_val == val + + +# ### Rejection by type ### +@pytest.mark.parametrize('val', + [['foo', ()], ['foo', 3, 4], [3, 2, 1]]) +def test_rejection_aok(val, validator_aok: StringValidator): + with pytest.raises(ValueError) as validation_failure: + validator_aok.validate_coerce(val) + + assert 'Invalid element(s)' in str(validation_failure.value) + + +# ### Rejection by value ### +@pytest.mark.parametrize('val', + [['foo', 'bar'], ['3', '4'], ['BAR', 'BAR', 'hello!']]) +def test_rejection_aok_values(val, validator_aok_values: StringValidator): + with pytest.raises(ValueError) as validation_failure: + validator_aok_values.validate_coerce(val) + + assert 'Invalid element(s)' in str(validation_failure.value) + + +# ### No blanks ### +@pytest.mark.parametrize('val', + ['123', ['bar', 'HELLO!!!'], ['world!@#$%^&*()']]) +def test_acceptance_no_blanks_aok(val, validator_no_blanks_aok: StringValidator): + coerce_val = validator_no_blanks_aok.validate_coerce(val) + if isinstance(val, (list, np.ndarray)): + assert np.array_equal(coerce_val, np.array(val, dtype=coerce_val.dtype)) + else: + assert coerce_val == val + + +@pytest.mark.parametrize('val', + ['', ['foo', 'bar', ''], ['']]) +def test_rejection_no_blanks_aok(val, validator_no_blanks_aok: StringValidator): + with pytest.raises(ValueError) as validation_failure: + validator_no_blanks_aok.validate_coerce(val) + + assert 'A non-empty string' in str(validation_failure.value) + diff --git a/ipyplotly/test/validators/test_subplotid_validator.py b/ipyplotly/test/validators/test_subplotid_validator.py new file mode 100644 index 00000000000..57f28ee73ef --- /dev/null +++ b/ipyplotly/test/validators/test_subplotid_validator.py @@ -0,0 +1,42 @@ +import pytest +from ipyplotly.basevalidators import SubplotidValidator +import numpy as np + + +# Fixtures +# -------- +@pytest.fixture() +def validator(): + return SubplotidValidator('prop', 'parent', dflt='geo') + + +# Tests +# ----- +# ### Acceptance ### +@pytest.mark.parametrize('val', ['geo'] + ['geo%d' % i for i in range(2, 10)]) +def test_acceptance(val, validator: SubplotidValidator): + assert validator.validate_coerce(val) == val + + +# ### Rejection by type ### +@pytest.mark.parametrize('val', [ + 23, [], {}, set(), np.inf, np.nan +]) +def test_rejection_type(val, validator: SubplotidValidator): + with pytest.raises(ValueError) as validation_failure: + validator.validate_coerce(val) + + assert 'Invalid value' in str(validation_failure.value) + + +# ### Rejection by value ### +@pytest.mark.parametrize('val', [ + '', # Cannot be empty + 'bogus', # Must begin with 'geo' + 'geo0', 'geo1' # If followed by a number the number must be > 1 +]) +def test_rejection_value(val, validator: SubplotidValidator): + with pytest.raises(ValueError) as validation_failure: + validator.validate_coerce(val) + + assert "Invalid value" in str(validation_failure.value) diff --git a/ipyplotly/test/validators/test_validators_common.py b/ipyplotly/test/validators/test_validators_common.py new file mode 100644 index 00000000000..27394e31f00 --- /dev/null +++ b/ipyplotly/test/validators/test_validators_common.py @@ -0,0 +1,7 @@ + +# # ### Accept None ### +# def test_accept_none(validator: NumberValidator): +# assert validator.validate_coerce(None) is None + + +# Test numpy arrays readonly diff --git a/js/README.md b/js/README.md new file mode 100644 index 00000000000..21fa647455a --- /dev/null +++ b/js/README.md @@ -0,0 +1,11 @@ +pythonic plotly API for use in Jupyter + +Package Install +--------------- + +**Prerequisites** +- [node](http://nodejs.org/) + +```bash +npm install --save plotlywidget +``` diff --git a/js/package-lock.json b/js/package-lock.json new file mode 100644 index 00000000000..1b317fd01ca --- /dev/null +++ b/js/package-lock.json @@ -0,0 +1,7405 @@ +{ + "name": "plotlywidget", + "version": "0.1.0", + "lockfileVersion": 1, + "requires": true, + "dependencies": { + "3d-view": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/3d-view/-/3d-view-2.0.0.tgz", + "integrity": "sha1-gxrpQtdQjFCAHj4G+v4ejFdOF74=", + "requires": { + "matrix-camera-controller": "2.1.3", + "orbit-camera-controller": "4.0.0", + "turntable-camera-controller": "3.0.1" + } + }, + "3d-view-controls": { + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/3d-view-controls/-/3d-view-controls-2.2.2.tgz", + "integrity": "sha512-WL0u3PN41lEx/4qvKqV6bJlweUYoW18FXMshW/qHb41AVdZxDReLoJNGYsI7x6jf9bYelEF62BJPQmO7yEnG2w==", + "requires": { + "3d-view": "2.0.0", + "has-passive-events": "1.0.0", + "mouse-change": "1.4.0", + "mouse-event-offset": "3.0.2", + "mouse-wheel": "1.2.0", + "right-now": "1.0.0" + } + }, + "@jupyter-widgets/base": { + "version": "1.1.8", + "resolved": "https://registry.npmjs.org/@jupyter-widgets/base/-/base-1.1.8.tgz", + "integrity": "sha512-IqRyg6tMutHIeV3lzHuQxruwbQCVJ4mOKxqpyLsoMjMK8bqdVZWqYMcFV+TMm+hSLkH1Omkj8heG27Ap+fCY6A==", + "requires": { + "@jupyterlab/services": "1.1.4", + "@phosphor/coreutils": "1.3.0", + "@phosphor/messaging": "1.2.2", + "@phosphor/widgets": "1.5.0", + "@types/backbone": "1.3.42", + "@types/lodash": "4.14.104", + "backbone": "1.2.3", + "base64-js": "1.2.3", + "jquery": "3.3.1", + "lodash": "4.17.5" + } + }, + "@jupyterlab/coreutils": { + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/@jupyterlab/coreutils/-/coreutils-1.0.9.tgz", + "integrity": "sha512-THsDz68RSo94fowgcZjlgsvMm+c+DUUGHlKcVRDCm/tFOCPNj7g1OtZ4VOe5FzC/wfEzo9mWKoy2hHG3XEWglQ==", + "requires": { + "@phosphor/algorithm": "1.1.2", + "@phosphor/coreutils": "1.3.0", + "@phosphor/disposable": "1.1.2", + "@phosphor/signaling": "1.2.2", + "ajv": "5.1.6", + "comment-json": "1.1.3", + "minimist": "1.2.0", + "moment": "2.17.1", + "path-posix": "1.0.0", + "url-parse": "1.1.9" + } + }, + "@jupyterlab/observables": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/@jupyterlab/observables/-/observables-1.0.6.tgz", + "integrity": "sha512-oqrZRlQyBEwlNiZkzD6bWLm1zi4SyY8KTSs/gcH7m0UAptwvDeYmRoCumy7alMdRTXR6IUTnYswY13R4TchI/g==", + "requires": { + "@phosphor/algorithm": "1.1.2", + "@phosphor/coreutils": "1.3.0", + "@phosphor/disposable": "1.1.2", + "@phosphor/messaging": "1.2.2", + "@phosphor/signaling": "1.2.2" + } + }, + "@jupyterlab/services": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/@jupyterlab/services/-/services-1.1.4.tgz", + "integrity": "sha512-1t3UmWU4+ikCVZA7uEfasyof7wMDzY4EWRkaTM0JFJw9DE7sOig4p4q0fD1ra332H/H68aPAoVCyAg+BFnr1Zw==", + "requires": { + "@jupyterlab/coreutils": "1.0.9", + "@jupyterlab/observables": "1.0.6", + "@phosphor/algorithm": "1.1.2", + "@phosphor/coreutils": "1.3.0", + "@phosphor/disposable": "1.1.2", + "@phosphor/signaling": "1.2.2", + "node-fetch": "1.7.3", + "ws": "1.1.5" + } + }, + "@phosphor/algorithm": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@phosphor/algorithm/-/algorithm-1.1.2.tgz", + "integrity": "sha1-/R3pEEyafzTpKGRYbd8ufy53eeg=" + }, + "@phosphor/collections": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@phosphor/collections/-/collections-1.1.2.tgz", + "integrity": "sha1-xMC4uREpkF+zap8kPy273kYtq40=", + "requires": { + "@phosphor/algorithm": "1.1.2" + } + }, + "@phosphor/commands": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/@phosphor/commands/-/commands-1.4.0.tgz", + "integrity": "sha1-fiNqTAFdrzepWG/eKRiMPawgFi8=", + "requires": { + "@phosphor/algorithm": "1.1.2", + "@phosphor/coreutils": "1.3.0", + "@phosphor/disposable": "1.1.2", + "@phosphor/domutils": "1.1.2", + "@phosphor/keyboard": "1.1.2", + "@phosphor/signaling": "1.2.2" + } + }, + "@phosphor/coreutils": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/@phosphor/coreutils/-/coreutils-1.3.0.tgz", + "integrity": "sha1-YyktOBwBLFqw0Blug87YKbfgSkI=" + }, + "@phosphor/disposable": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@phosphor/disposable/-/disposable-1.1.2.tgz", + "integrity": "sha1-oZLdai5sadXQnTns8zTauTd4Bg4=", + "requires": { + "@phosphor/algorithm": "1.1.2" + } + }, + "@phosphor/domutils": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@phosphor/domutils/-/domutils-1.1.2.tgz", + "integrity": "sha1-4u/rBS85jEK5O4npurJq8VzABRQ=" + }, + "@phosphor/dragdrop": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/@phosphor/dragdrop/-/dragdrop-1.3.0.tgz", + "integrity": "sha1-fOatOdbKIW1ipW94EE0Cp3rmcwc=", + "requires": { + "@phosphor/coreutils": "1.3.0", + "@phosphor/disposable": "1.1.2" + } + }, + "@phosphor/keyboard": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@phosphor/keyboard/-/keyboard-1.1.2.tgz", + "integrity": "sha1-PjIjRFF2QkCpjhSANNWoeXQi3R8=" + }, + "@phosphor/messaging": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/@phosphor/messaging/-/messaging-1.2.2.tgz", + "integrity": "sha1-fYlt3TeXuUo0dwje0T2leD23XBQ=", + "requires": { + "@phosphor/algorithm": "1.1.2", + "@phosphor/collections": "1.1.2" + } + }, + "@phosphor/properties": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@phosphor/properties/-/properties-1.1.2.tgz", + "integrity": "sha1-eMx37/RSg52gIlXeSOgUlGzAmig=" + }, + "@phosphor/signaling": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/@phosphor/signaling/-/signaling-1.2.2.tgz", + "integrity": "sha1-P8+Xyojji/s1f+j+a/dRM0elFKk=", + "requires": { + "@phosphor/algorithm": "1.1.2" + } + }, + "@phosphor/virtualdom": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@phosphor/virtualdom/-/virtualdom-1.1.2.tgz", + "integrity": "sha1-zlXIbu8x5dDiax3JbqMr1oRFj0E=", + "requires": { + "@phosphor/algorithm": "1.1.2" + } + }, + "@phosphor/widgets": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/@phosphor/widgets/-/widgets-1.5.0.tgz", + "integrity": "sha1-X5mOhvX9542KpE19wUdobKZhaB4=", + "requires": { + "@phosphor/algorithm": "1.1.2", + "@phosphor/commands": "1.4.0", + "@phosphor/coreutils": "1.3.0", + "@phosphor/disposable": "1.1.2", + "@phosphor/domutils": "1.1.2", + "@phosphor/dragdrop": "1.3.0", + "@phosphor/keyboard": "1.1.2", + "@phosphor/messaging": "1.2.2", + "@phosphor/properties": "1.1.2", + "@phosphor/signaling": "1.2.2", + "@phosphor/virtualdom": "1.1.2" + } + }, + "@plotly/d3-sankey": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/@plotly/d3-sankey/-/d3-sankey-0.5.0.tgz", + "integrity": "sha1-si+up0LlglEzXuXZ+6JIdyYHgA8=", + "requires": { + "d3-array": "1.2.1", + "d3-collection": "1.0.4", + "d3-interpolate": "1.1.6" + } + }, + "@types/backbone": { + "version": "1.3.42", + "resolved": "https://registry.npmjs.org/@types/backbone/-/backbone-1.3.42.tgz", + "integrity": "sha512-sg6WhUW1RorO/Yc0yKqVhekBlweLbQqJciHr70FYL4Z8IFhcZngyXaYdfq8MCv/Rf/Nry5Sbsl9jWGzUN+2Zbg==", + "requires": { + "@types/jquery": "3.3.0", + "@types/underscore": "1.8.7" + } + }, + "@types/jquery": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/@types/jquery/-/jquery-3.3.0.tgz", + "integrity": "sha512-szaKV2OQgwxYTGTY6qd9eeBfGGCaP7n2OGit4JdbOcfGgc9VWjfhMhnu5AVNhIAu8WWDIB36q9dfPVba1fGeIQ==" + }, + "@types/lodash": { + "version": "4.14.104", + "resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.14.104.tgz", + "integrity": "sha512-ufQcVg4daO8xQ5kopxRHanqFdL4AI7ondQkV+2f+7mz3gvp0LkBx2zBRC6hfs3T87mzQFmf5Fck7Fi145Ul6NQ==" + }, + "@types/underscore": { + "version": "1.8.7", + "resolved": "https://registry.npmjs.org/@types/underscore/-/underscore-1.8.7.tgz", + "integrity": "sha512-vMSV6VOWFVBcud1bBUKJVVhXmmx136Run3p1xK00XViC2pQnXXrveU79S13h2+Im/TBhtMtTufid+dbysd3m/g==" + }, + "JSV": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/JSV/-/JSV-4.0.2.tgz", + "integrity": "sha1-0Hf2glVx+CEy+d/67Vh7QCn+/1c=" + }, + "a-big-triangle": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/a-big-triangle/-/a-big-triangle-1.0.3.tgz", + "integrity": "sha1-7v0wsCqPUl6LH3K7a7GwwWdRx5Q=", + "requires": { + "gl-buffer": "2.1.2", + "gl-vao": "1.3.0", + "weak-map": "1.0.5" + } + }, + "abs-svg-path": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/abs-svg-path/-/abs-svg-path-0.1.1.tgz", + "integrity": "sha1-32Acjo0roQ1KdtYl4japo5wnI78=" + }, + "acorn": { + "version": "5.4.1", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-5.4.1.tgz", + "integrity": "sha512-XLmq3H/BVvW6/GbxKryGxWORz1ebilSsUDlyC27bXhWGWAZWkGwS6FLHjOlwFXNFoWFQEO/Df4u0YYd0K3BQgQ==" + }, + "acorn-dynamic-import": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/acorn-dynamic-import/-/acorn-dynamic-import-2.0.2.tgz", + "integrity": "sha1-x1K9IQvvZ5UBtsbLf8hPj0cVjMQ=", + "dev": true, + "requires": { + "acorn": "4.0.13" + }, + "dependencies": { + "acorn": { + "version": "4.0.13", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-4.0.13.tgz", + "integrity": "sha1-EFSVrlNh1pe9GVyCUZLhrX8lN4c=", + "dev": true + } + } + }, + "acorn-jsx": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-3.0.1.tgz", + "integrity": "sha1-r9+UiPsezvyDSPb7IvRk4ypYs2s=", + "requires": { + "acorn": "3.3.0" + }, + "dependencies": { + "acorn": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-3.3.0.tgz", + "integrity": "sha1-ReN/s56No/JbruP/U2niu18iAXo=" + } + } + }, + "acorn5-object-spread": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/acorn5-object-spread/-/acorn5-object-spread-4.0.0.tgz", + "integrity": "sha1-1XWAge7ZcSGrC+R+Mcqu8qo5lpc=", + "requires": { + "acorn": "5.4.1" + } + }, + "add-line-numbers": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/add-line-numbers/-/add-line-numbers-1.0.1.tgz", + "integrity": "sha1-SNu96kfb0jTer+rGyTzqb3C0t+M=", + "requires": { + "pad-left": "1.0.2" + } + }, + "affine-hull": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/affine-hull/-/affine-hull-1.0.0.tgz", + "integrity": "sha1-dj/x040GPOt+Jy8X7k17vK+QXF0=", + "requires": { + "robust-orientation": "1.1.3" + } + }, + "ajv": { + "version": "5.1.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-5.1.6.tgz", + "integrity": "sha1-Sy8aGd7Ok9V6whYDfj6XkcfdFWQ=", + "requires": { + "co": "4.6.0", + "json-schema-traverse": "0.3.1", + "json-stable-stringify": "1.0.1" + } + }, + "ajv-keywords": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.1.0.tgz", + "integrity": "sha1-rCsnk5xUPpXSwG5/f1wnvkqlQ74=", + "dev": true + }, + "align-text": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/align-text/-/align-text-0.1.4.tgz", + "integrity": "sha1-DNkKVhCT810KmSVsIrcGlDP60Rc=", + "requires": { + "kind-of": "3.2.2", + "longest": "1.0.1", + "repeat-string": "1.6.1" + } + }, + "almost-equal": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/almost-equal/-/almost-equal-1.1.0.tgz", + "integrity": "sha1-+FHGMROHV5lCdqou++jfowZszN0=" + }, + "alpha-complex": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/alpha-complex/-/alpha-complex-1.0.0.tgz", + "integrity": "sha1-kIZYcNawVCrnPAwTHU75iWabctI=", + "requires": { + "circumradius": "1.0.0", + "delaunay-triangulate": "1.1.6" + } + }, + "alpha-shape": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/alpha-shape/-/alpha-shape-1.0.0.tgz", + "integrity": "sha1-yDEJkj7P2mZ9IWP+Tyb+JHJvZKk=", + "requires": { + "alpha-complex": "1.0.0", + "simplicial-complex-boundary": "1.0.1" + } + }, + "amdefine": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/amdefine/-/amdefine-1.0.1.tgz", + "integrity": "sha1-SlKCrBZHKek2Gbz9OtFR+BfOkfU=" + }, + "ansi-regex": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", + "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", + "dev": true + }, + "ansi-styles": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.0.tgz", + "integrity": "sha512-NnSOmMEYtVR2JVMIGTzynRkkaxtiq1xnFBcdQD/DnNCYPoEPsVJhM98BDyaoNOQIi7p4okdi3E27eN7GQbsUug==", + "requires": { + "color-convert": "1.9.1" + } + }, + "anymatch": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-1.3.2.tgz", + "integrity": "sha512-0XNayC8lTHQ2OI8aljNCN3sSx6hsr/1+rlcDAotXJR7C1oZZHCNsfpbKwMjRA3Uqb5tF1Rae2oloTr4xpq+WjA==", + "dev": true, + "requires": { + "micromatch": "2.3.11", + "normalize-path": "2.1.1" + } + }, + "arr-diff": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-2.0.0.tgz", + "integrity": "sha1-jzuCf5Vai9ZpaX5KQlasPOrjVs8=", + "dev": true, + "requires": { + "arr-flatten": "1.1.0" + } + }, + "arr-flatten": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/arr-flatten/-/arr-flatten-1.1.0.tgz", + "integrity": "sha512-L3hKV5R/p5o81R7O02IGnwpDmkp6E982XhtbuwSe3O4qOtMMMtodicASA1Cny2U+aCXcNpml+m4dPsvsJ3jatg==", + "dev": true + }, + "array-bounds": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/array-bounds/-/array-bounds-1.0.1.tgz", + "integrity": "sha512-8wdW3ZGk6UjMPJx/glyEt0sLzzwAE1bhToPsO1W2pbpR2gULyxe3BjSiuJFheP50T/GgODVPz2fuMUmIywt8cQ==" + }, + "array-normalize": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/array-normalize/-/array-normalize-1.1.3.tgz", + "integrity": "sha1-c/uDf0gW7BkVHTxejYU6RZDOAb0=", + "requires": { + "array-bounds": "1.0.1" + } + }, + "array-pack-2d": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/array-pack-2d/-/array-pack-2d-0.1.1.tgz", + "integrity": "sha1-vb3PL3+xm/uOBvvwHYvIxmS0aT0=", + "requires": { + "dtype": "1.0.0" + }, + "dependencies": { + "dtype": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/dtype/-/dtype-1.0.0.tgz", + "integrity": "sha1-rjT/ooJnNxUgNYLWG73QqtPLo+c=" + } + } + }, + "array-range": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/array-range/-/array-range-1.0.1.tgz", + "integrity": "sha1-9W5GWRhDYRxqVvd+8C7afFAIm/w=" + }, + "array-unique": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.2.1.tgz", + "integrity": "sha1-odl8yvy8JiXMcPrc6zalDFiwGlM=", + "dev": true + }, + "asn1": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.3.tgz", + "integrity": "sha1-2sh4dxPJlmhJ/IGAd36+nB3fO4Y=" + }, + "asn1.js": { + "version": "4.10.1", + "resolved": "https://registry.npmjs.org/asn1.js/-/asn1.js-4.10.1.tgz", + "integrity": "sha512-p32cOF5q0Zqs9uBiONKYLm6BClCoBCM5O9JfeUSlnQLBTxYdTK+pW+nXflm8UkKd2UYlEbYz5qEi0JuZR9ckSw==", + "dev": true, + "requires": { + "bn.js": "4.11.8", + "inherits": "2.0.3", + "minimalistic-assert": "1.0.0" + } + }, + "assert": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/assert/-/assert-1.4.1.tgz", + "integrity": "sha1-mZEtWRg2tab1s0XA8H7vwI/GXZE=", + "dev": true, + "requires": { + "util": "0.10.3" + } + }, + "assert-plus": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", + "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=" + }, + "async": { + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/async/-/async-2.6.0.tgz", + "integrity": "sha512-xAfGg1/NTLBBKlHFmnd7PlmUW9KhVQIUuSrYem9xzFUZy13ScvtyGGejaae9iAVRiRq9+Cx7DPFaAAhCpyxyPw==", + "dev": true, + "requires": { + "lodash": "4.17.5" + } + }, + "async-each": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/async-each/-/async-each-1.0.1.tgz", + "integrity": "sha1-GdOGodntxufByF04iu28xW0zYC0=", + "dev": true + }, + "asynckit": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", + "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=" + }, + "atob-lite": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/atob-lite/-/atob-lite-1.0.0.tgz", + "integrity": "sha1-uI3KYAaSK5YglPdVaCa6sxxKKWs=" + }, + "aws-sign2": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.7.0.tgz", + "integrity": "sha1-tG6JCTSpWR8tL2+G1+ap8bP+dqg=" + }, + "aws4": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.6.0.tgz", + "integrity": "sha1-g+9cqGCysy5KDe7e6MdxudtXRx4=" + }, + "backbone": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/backbone/-/backbone-1.2.3.tgz", + "integrity": "sha1-wiz9B/yG676uYdGJKe0RXpmdZbk=", + "requires": { + "underscore": "1.8.3" + } + }, + "balanced-match": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", + "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=" + }, + "barycentric": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/barycentric/-/barycentric-1.0.1.tgz", + "integrity": "sha1-8VYruJGyb0/sRjqC7to2V4AOxog=", + "requires": { + "robust-linear-solve": "1.0.0" + } + }, + "base64-js": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.2.3.tgz", + "integrity": "sha512-MsAhsUW1GxCdgYSO6tAfZrNapmUKk7mWx/k5mFY/A1gBtkaCaNapTg+FExCw1r9yeaZhqx/xPg43xgTFH6KL5w==" + }, + "bcrypt-pbkdf": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.1.tgz", + "integrity": "sha1-Y7xdy2EzG5K8Bf1SiVPDNGKgb40=", + "optional": true, + "requires": { + "tweetnacl": "0.14.5" + } + }, + "big-rat": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/big-rat/-/big-rat-1.0.4.tgz", + "integrity": "sha1-do0JO7V5MN0Y7Vdcf8on3FORreo=", + "requires": { + "bit-twiddle": "1.0.2", + "bn.js": "4.11.8", + "double-bits": "1.1.1" + } + }, + "big.js": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/big.js/-/big.js-3.2.0.tgz", + "integrity": "sha512-+hN/Zh2D08Mx65pZ/4g5bsmNiZUuChDiQfTUQ7qJr4/kuopCr88xZsAXv6mBoZEsUI4OuGHlX59qE94K2mMW8Q==", + "dev": true + }, + "binary-extensions": { + "version": "1.11.0", + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-1.11.0.tgz", + "integrity": "sha1-RqoXUftqL5PuXmibsQh9SxTGwgU=", + "dev": true + }, + "binary-search-bounds": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/binary-search-bounds/-/binary-search-bounds-1.0.0.tgz", + "integrity": "sha1-MjyjF+PypA9CRMclX1OEpbIHu2k=" + }, + "bit-twiddle": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/bit-twiddle/-/bit-twiddle-1.0.2.tgz", + "integrity": "sha1-DGwfq+KyPRcXPZpht7cJPrnhdp4=" + }, + "bitmap-sdf": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/bitmap-sdf/-/bitmap-sdf-1.0.3.tgz", + "integrity": "sha512-ojYySSvWTx21cbgntR942zgEgqj38wHctN64vr4vYRFf3GKVmI23YlA94meWGkFslidwLwGCsMy2laJ3g/94Sg==", + "requires": { + "clamp": "1.0.1" + } + }, + "bl": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/bl/-/bl-1.2.1.tgz", + "integrity": "sha1-ysMo977kVzDUBLaSID/LWQ4XLV4=", + "requires": { + "readable-stream": "2.3.4" + }, + "dependencies": { + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=" + }, + "readable-stream": { + "version": "2.3.4", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.4.tgz", + "integrity": "sha512-vuYxeWYM+fde14+rajzqgeohAI7YoJcHE7kXDAc4Nk0EbuKnJfqtY9YtRkLo/tqkuF7MsBQRhPnPeyjYITp3ZQ==", + "requires": { + "core-util-is": "1.0.2", + "inherits": "2.0.3", + "isarray": "1.0.0", + "process-nextick-args": "2.0.0", + "safe-buffer": "5.1.1", + "string_decoder": "1.0.3", + "util-deprecate": "1.0.2" + } + }, + "string_decoder": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.0.3.tgz", + "integrity": "sha512-4AH6Z5fzNNBcH+6XDMfA/BTt87skxqJlO0lAh3Dker5zThcAxG6mKz+iGu308UKoPPQ8Dcqx/4JhujzltRa+hQ==", + "requires": { + "safe-buffer": "5.1.1" + } + } + } + }, + "bn.js": { + "version": "4.11.8", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.8.tgz", + "integrity": "sha512-ItfYfPLkWHUjckQCk8xC+LwxgK8NYcXywGigJgSwOP8Y2iyWT4f2vsZnoOXTTbo+o5yXmIUJ4gn5538SO5S3gA==" + }, + "boom": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/boom/-/boom-4.3.1.tgz", + "integrity": "sha1-T4owBctKfjiJ90kDD9JbluAdLjE=", + "requires": { + "hoek": "4.2.1" + } + }, + "bops": { + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/bops/-/bops-0.0.6.tgz", + "integrity": "sha1-CC0dVfoB5g29wuvC26N/ZZVUzzo=", + "requires": { + "base64-js": "0.0.2", + "to-utf8": "0.0.1" + }, + "dependencies": { + "base64-js": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-0.0.2.tgz", + "integrity": "sha1-Ak8Pcq+iW3X5wO5zzU9V7Bvtl4Q=" + } + } + }, + "boundary-cells": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/boundary-cells/-/boundary-cells-2.0.1.tgz", + "integrity": "sha1-6QWo0UGc9Hyza+Pb9SXbXiTeAEI=", + "requires": { + "tape": "4.8.0" + } + }, + "box-intersect": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/box-intersect/-/box-intersect-1.0.1.tgz", + "integrity": "sha1-tyilnj8aPHPCJJM8JmC5J6oTeQI=", + "requires": { + "bit-twiddle": "1.0.2", + "typedarray-pool": "1.1.0" + } + }, + "brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "requires": { + "balanced-match": "1.0.0", + "concat-map": "0.0.1" + } + }, + "braces": { + "version": "1.8.5", + "resolved": "https://registry.npmjs.org/braces/-/braces-1.8.5.tgz", + "integrity": "sha1-uneWLhLf+WnWt2cR6RS3N4V79qc=", + "dev": true, + "requires": { + "expand-range": "1.8.2", + "preserve": "0.2.0", + "repeat-element": "1.1.2" + } + }, + "brfs": { + "version": "1.4.4", + "resolved": "https://registry.npmjs.org/brfs/-/brfs-1.4.4.tgz", + "integrity": "sha512-rX2qc9hkpLPiwdu1HkLY642rwwo3X6N+ZPyEPdNn3OUKV/B2BRP7dHdnkhGantOJLVoTluNYBi4VecHb2Kq2hw==", + "requires": { + "quote-stream": "1.0.2", + "resolve": "1.4.0", + "static-module": "2.1.1", + "through2": "2.0.3" + }, + "dependencies": { + "duplexer2": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/duplexer2/-/duplexer2-0.1.4.tgz", + "integrity": "sha1-ixLauHjA1p4+eJEFFmKjL8a93ME=", + "requires": { + "readable-stream": "2.3.4" + } + }, + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=" + }, + "object-inspect": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.4.1.tgz", + "integrity": "sha512-wqdhLpfCUbEsoEwl3FXwGyv8ief1k/1aUdIPCqVnupM6e8l63BEJdiF/0swtn04/8p05tG/T0FrpTlfwvljOdw==" + }, + "quote-stream": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/quote-stream/-/quote-stream-1.0.2.tgz", + "integrity": "sha1-hJY/jJwmuULhU/7rU6rnRlK34LI=", + "requires": { + "buffer-equal": "0.0.1", + "minimist": "1.2.0", + "through2": "2.0.3" + } + }, + "readable-stream": { + "version": "2.3.4", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.4.tgz", + "integrity": "sha512-vuYxeWYM+fde14+rajzqgeohAI7YoJcHE7kXDAc4Nk0EbuKnJfqtY9YtRkLo/tqkuF7MsBQRhPnPeyjYITp3ZQ==", + "requires": { + "core-util-is": "1.0.2", + "inherits": "2.0.3", + "isarray": "1.0.0", + "process-nextick-args": "2.0.0", + "safe-buffer": "5.1.1", + "string_decoder": "1.0.3", + "util-deprecate": "1.0.2" + } + }, + "static-eval": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/static-eval/-/static-eval-2.0.0.tgz", + "integrity": "sha512-6flshd3F1Gwm+Ksxq463LtFd1liC77N/PX1FVVc3OzL3hAmo2fwHFbuArkcfi7s9rTNsLEhcRmXGFZhlgy40uw==", + "requires": { + "escodegen": "1.9.0" + } + }, + "static-module": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/static-module/-/static-module-2.1.1.tgz", + "integrity": "sha512-PPLCnxRl74wV38rG1T0rH8Fl2wIktTXFo7/varrZjtSGb/vndZIGkpe4HJVd8hoBYXRkRHW6hlCRAHvmDgrYQQ==", + "requires": { + "concat-stream": "1.6.0", + "duplexer2": "0.1.4", + "escodegen": "1.9.0", + "falafel": "2.1.0", + "has": "1.0.1", + "object-inspect": "1.4.1", + "quote-stream": "1.0.2", + "readable-stream": "2.3.4", + "shallow-copy": "0.0.1", + "static-eval": "2.0.0", + "through2": "2.0.3" + } + }, + "string_decoder": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.0.3.tgz", + "integrity": "sha512-4AH6Z5fzNNBcH+6XDMfA/BTt87skxqJlO0lAh3Dker5zThcAxG6mKz+iGu308UKoPPQ8Dcqx/4JhujzltRa+hQ==", + "requires": { + "safe-buffer": "5.1.1" + } + }, + "through2": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.3.tgz", + "integrity": "sha1-AARWmzfHx0ujnEPzzteNGtlBQL4=", + "requires": { + "readable-stream": "2.3.4", + "xtend": "4.0.1" + } + } + } + }, + "brorand": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/brorand/-/brorand-1.1.0.tgz", + "integrity": "sha1-EsJe/kCkXjwyPrhnWgoM5XsiNx8=", + "dev": true + }, + "browserify-aes": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/browserify-aes/-/browserify-aes-1.1.1.tgz", + "integrity": "sha512-UGnTYAnB2a3YuYKIRy1/4FB2HdM866E0qC46JXvVTYKlBlZlnvfpSfY6OKfXZAkv70eJ2a1SqzpAo5CRhZGDFg==", + "dev": true, + "requires": { + "buffer-xor": "1.0.3", + "cipher-base": "1.0.4", + "create-hash": "1.1.3", + "evp_bytestokey": "1.0.3", + "inherits": "2.0.3", + "safe-buffer": "5.1.1" + } + }, + "browserify-cipher": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/browserify-cipher/-/browserify-cipher-1.0.0.tgz", + "integrity": "sha1-mYgkSHS/XtTijalWZtzWasj8Njo=", + "dev": true, + "requires": { + "browserify-aes": "1.1.1", + "browserify-des": "1.0.0", + "evp_bytestokey": "1.0.3" + } + }, + "browserify-des": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/browserify-des/-/browserify-des-1.0.0.tgz", + "integrity": "sha1-2qJ3cXRwki7S/hhZQRihdUOXId0=", + "dev": true, + "requires": { + "cipher-base": "1.0.4", + "des.js": "1.0.0", + "inherits": "2.0.3" + } + }, + "browserify-rsa": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/browserify-rsa/-/browserify-rsa-4.0.1.tgz", + "integrity": "sha1-IeCr+vbyApzy+vsTNWenAdQTVSQ=", + "dev": true, + "requires": { + "bn.js": "4.11.8", + "randombytes": "2.0.6" + } + }, + "browserify-sign": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/browserify-sign/-/browserify-sign-4.0.4.tgz", + "integrity": "sha1-qk62jl17ZYuqa/alfmMMvXqT0pg=", + "dev": true, + "requires": { + "bn.js": "4.11.8", + "browserify-rsa": "4.0.1", + "create-hash": "1.1.3", + "create-hmac": "1.1.6", + "elliptic": "6.4.0", + "inherits": "2.0.3", + "parse-asn1": "5.1.0" + } + }, + "browserify-zlib": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/browserify-zlib/-/browserify-zlib-0.2.0.tgz", + "integrity": "sha512-Z942RysHXmJrhqk88FmKBVq/v5tqmSkDz7p54G/MGyjMnCFFnC79XWNbg+Vta8W6Wb2qtSZTSxIGkJrRpCFEiA==", + "dev": true, + "requires": { + "pako": "1.0.6" + } + }, + "buble": { + "version": "0.18.0", + "resolved": "https://registry.npmjs.org/buble/-/buble-0.18.0.tgz", + "integrity": "sha512-U3NJxUiSz0H1EB54PEHAuBTxdXgQH4DaQkvkINFXf9kEKCDWSn67EgQfFKbkTzsok4xRrIPsoxWDl2czCHR65g==", + "requires": { + "acorn": "5.4.1", + "acorn-jsx": "3.0.1", + "acorn5-object-spread": "4.0.0", + "chalk": "2.3.1", + "magic-string": "0.22.4", + "minimist": "1.2.0", + "os-homedir": "1.0.2", + "vlq": "0.2.3" + } + }, + "bubleify": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/bubleify/-/bubleify-1.1.0.tgz", + "integrity": "sha512-9FtUiQong0qiDuN/iOtDwqovyDXENTpcvQH9Szyc/wzALPt0tDdP1moIjJqeT5LMwLzvLkMHaL+RohWEeHY6XQ==", + "requires": { + "buble": "0.18.0" + } + }, + "buffer": { + "version": "4.9.1", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-4.9.1.tgz", + "integrity": "sha1-bRu2AbB6TvztlwlBMgkwJ8lbwpg=", + "dev": true, + "requires": { + "base64-js": "1.2.3", + "ieee754": "1.1.8", + "isarray": "1.0.0" + }, + "dependencies": { + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", + "dev": true + } + } + }, + "buffer-equal": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/buffer-equal/-/buffer-equal-0.0.1.tgz", + "integrity": "sha1-kbx0sR6kBbyRa8aqkI+q+ltKrEs=" + }, + "buffer-xor": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/buffer-xor/-/buffer-xor-1.0.3.tgz", + "integrity": "sha1-JuYe0UIvtw3ULm42cp7VHYVf6Nk=", + "dev": true + }, + "builtin-modules": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/builtin-modules/-/builtin-modules-1.1.1.tgz", + "integrity": "sha1-Jw8HbFpywC9bZaR9+Uxf46J4iS8=", + "dev": true + }, + "builtin-status-codes": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/builtin-status-codes/-/builtin-status-codes-3.0.0.tgz", + "integrity": "sha1-hZgoeOIbmOHGZCXgPQF0eI9Wnug=", + "dev": true + }, + "call-matcher": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/call-matcher/-/call-matcher-1.0.1.tgz", + "integrity": "sha1-UTTQd5hPcSpU2tPL9i3ijc5BbKg=", + "requires": { + "core-js": "2.5.3", + "deep-equal": "1.0.1", + "espurify": "1.7.0", + "estraverse": "4.2.0" + } + }, + "camelcase": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-1.2.1.tgz", + "integrity": "sha1-m7UwTS4LVmmLLHWLCKPqqdqlijk=" + }, + "canvas-fit": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/canvas-fit/-/canvas-fit-1.5.0.tgz", + "integrity": "sha1-rhO+Zq3kL1vg5IfjRfzjCl5bXl8=", + "requires": { + "element-size": "1.1.1" + } + }, + "caseless": { + "version": "0.12.0", + "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz", + "integrity": "sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw=" + }, + "cdt2d": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/cdt2d/-/cdt2d-1.0.0.tgz", + "integrity": "sha1-TyEkNLzWe9s9aLj+9KzcLFRBUUE=", + "requires": { + "binary-search-bounds": "2.0.4", + "robust-in-sphere": "1.1.3", + "robust-orientation": "1.1.3" + }, + "dependencies": { + "binary-search-bounds": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/binary-search-bounds/-/binary-search-bounds-2.0.4.tgz", + "integrity": "sha512-2hg5kgdKql5ClF2ErBcSx0U5bnl5hgS4v7wMnLFodyR47yMtj2w+UAZB+0CiqyHct2q543i7Bi4/aMIegorCCg==" + } + } + }, + "cell-orientation": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/cell-orientation/-/cell-orientation-1.0.1.tgz", + "integrity": "sha1-tQStlqZq0obZ7dmFoiU9A7gNKFA=" + }, + "center-align": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/center-align/-/center-align-0.1.3.tgz", + "integrity": "sha1-qg0yYptu6XIgBBHL1EYckHvCt60=", + "requires": { + "align-text": "0.1.4", + "lazy-cache": "1.0.4" + } + }, + "chalk": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.3.1.tgz", + "integrity": "sha512-QUU4ofkDoMIVO7hcx1iPTISs88wsO8jA92RQIm4JAwZvFGGAV2hSAA1NX7oVj2Ej2Q6NDTcRDjPTFrMCRZoJ6g==", + "requires": { + "ansi-styles": "3.2.0", + "escape-string-regexp": "1.0.5", + "supports-color": "5.2.0" + } + }, + "chokidar": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-1.7.0.tgz", + "integrity": "sha1-eY5ol3gVHIB2tLNg5e3SjNortGg=", + "dev": true, + "requires": { + "anymatch": "1.3.2", + "async-each": "1.0.1", + "fsevents": "1.1.3", + "glob-parent": "2.0.0", + "inherits": "2.0.3", + "is-binary-path": "1.0.1", + "is-glob": "2.0.1", + "path-is-absolute": "1.0.1", + "readdirp": "2.1.0" + } + }, + "cipher-base": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/cipher-base/-/cipher-base-1.0.4.tgz", + "integrity": "sha512-Kkht5ye6ZGmwv40uUDZztayT2ThLQGfnj/T71N/XzeZeo3nf8foyW7zGTsPYkEya3m5f3cAypH+qe7YOrM1U2Q==", + "dev": true, + "requires": { + "inherits": "2.0.3", + "safe-buffer": "5.1.1" + } + }, + "circumcenter": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/circumcenter/-/circumcenter-1.0.0.tgz", + "integrity": "sha1-INeqE7F/usUvUtpPVMasi5Bu5Sk=", + "requires": { + "dup": "1.0.0", + "robust-linear-solve": "1.0.0" + } + }, + "circumradius": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/circumradius/-/circumradius-1.0.0.tgz", + "integrity": "sha1-cGxEfj5VzR7T0RvRM+N8JSzDBbU=", + "requires": { + "circumcenter": "1.0.0" + } + }, + "clamp": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/clamp/-/clamp-1.0.1.tgz", + "integrity": "sha1-ZqDmQBGBbjcZaCj9yMjBRzEshjQ=" + }, + "clean-pslg": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/clean-pslg/-/clean-pslg-1.1.2.tgz", + "integrity": "sha1-vTXHRgt+irWp92Gl7VF5aqPIbBE=", + "requires": { + "big-rat": "1.0.4", + "box-intersect": "1.0.1", + "nextafter": "1.0.0", + "rat-vec": "1.1.1", + "robust-segment-intersect": "1.0.1", + "union-find": "1.0.2", + "uniq": "1.0.1" + } + }, + "cliui": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-2.1.0.tgz", + "integrity": "sha1-S0dXYP+AJkx2LDoXGQMukcf+oNE=", + "requires": { + "center-align": "0.1.3", + "right-align": "0.1.3", + "wordwrap": "0.0.2" + }, + "dependencies": { + "wordwrap": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-0.0.2.tgz", + "integrity": "sha1-t5Zpu0LstAn4PVg8rVLKF+qhZD8=" + } + } + }, + "co": { + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz", + "integrity": "sha1-bqa989hTrlTMuOR7+gvz+QMfsYQ=" + }, + "code-point-at": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz", + "integrity": "sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c=", + "dev": true + }, + "color-convert": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.1.tgz", + "integrity": "sha512-mjGanIiwQJskCC18rPR6OmrZ6fm2Lc7PeGFYwCmy5J34wC6F1PzdGL6xeMfmgicfYcNLGuVFA3WzXtIDCQSZxQ==", + "requires": { + "color-name": "1.1.3" + } + }, + "color-id": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/color-id/-/color-id-1.1.0.tgz", + "integrity": "sha512-2iRtAn6dC/6/G7bBIo0uupVrIne1NsQJvJxZOBCzQOfk7jRq97feaDZ3RdzuHakRXXnHGNwglto3pqtRx1sX0g==", + "requires": { + "clamp": "1.0.1" + } + }, + "color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=" + }, + "color-normalize": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/color-normalize/-/color-normalize-1.0.3.tgz", + "integrity": "sha512-bUyyoiyeJSm24u+y5ePwVssNg9zACjHKHUS0thYZEmCafrTg4RX1b43V6M141V2EdlaBoS5OV3VvyAXxdup+YA==", + "requires": { + "clamp": "1.0.1", + "color-rgba": "2.0.0", + "dtype": "2.0.0" + } + }, + "color-parse": { + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/color-parse/-/color-parse-1.3.5.tgz", + "integrity": "sha1-TIEPcugI5Pc7Y/cqzXjaU4pRVWQ=", + "requires": { + "color-name": "1.1.3", + "defined": "1.0.0", + "is-plain-obj": "1.1.0" + } + }, + "color-rgba": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/color-rgba/-/color-rgba-2.0.0.tgz", + "integrity": "sha1-0BURTOPoQ2h5XJ1t3+9Vb5gXOcU=", + "requires": { + "clamp": "1.0.1", + "color-parse": "1.3.5", + "color-space": "1.15.0" + } + }, + "color-space": { + "version": "1.15.0", + "resolved": "https://registry.npmjs.org/color-space/-/color-space-1.15.0.tgz", + "integrity": "sha1-JiP1TBGB4P5uHP8Nh+JOsQQPWw4=", + "requires": { + "husl": "5.0.3", + "mumath": "3.3.4" + } + }, + "colormap": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/colormap/-/colormap-2.3.0.tgz", + "integrity": "sha512-Mkk6mQUMbCleXEeStFm2xLwv5zbRakZMUFB1T1+iNEv58VKBByfPwYIjMQDwSRmXNM1gvo5y3WTYAhmdMn/rbg==", + "requires": { + "lerp": "1.0.3" + } + }, + "colors": { + "version": "0.6.2", + "resolved": "https://registry.npmjs.org/colors/-/colors-0.6.2.tgz", + "integrity": "sha1-JCP+ZnisDF2uiFLl0OW+CMmXq8w=" + }, + "combined-stream": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.6.tgz", + "integrity": "sha1-cj599ugBrFYTETp+RFqbactjKBg=", + "requires": { + "delayed-stream": "1.0.0" + } + }, + "commander": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.1.0.tgz", + "integrity": "sha1-0SG7roYNmZKj1Re6lvVliOR8Z4E=" + }, + "comment-json": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/comment-json/-/comment-json-1.1.3.tgz", + "integrity": "sha1-aYbDMw/uDEyeAMI5jNYa+l2PI54=", + "requires": { + "json-parser": "1.1.5" + } + }, + "compare-angle": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/compare-angle/-/compare-angle-1.0.1.tgz", + "integrity": "sha1-pOtjQW6jx0f8a9bItjZotN5PoSk=", + "requires": { + "robust-orientation": "1.1.3", + "robust-product": "1.0.0", + "robust-sum": "1.0.0", + "signum": "0.0.0", + "two-sum": "1.0.0" + } + }, + "compare-cell": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/compare-cell/-/compare-cell-1.0.0.tgz", + "integrity": "sha1-qetwj24OQa73qlZrEw8ZaNyeGqo=" + }, + "compare-oriented-cell": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/compare-oriented-cell/-/compare-oriented-cell-1.0.1.tgz", + "integrity": "sha1-ahSf7vnfxPj8YjWOUd1C7/u9w54=", + "requires": { + "cell-orientation": "1.0.1", + "compare-cell": "1.0.0" + } + }, + "concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=" + }, + "concat-stream": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.6.0.tgz", + "integrity": "sha1-CqxmL9Ur54lk1VMvaUeE5wEQrPc=", + "requires": { + "inherits": "2.0.3", + "readable-stream": "2.3.4", + "typedarray": "0.0.6" + }, + "dependencies": { + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=" + }, + "readable-stream": { + "version": "2.3.4", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.4.tgz", + "integrity": "sha512-vuYxeWYM+fde14+rajzqgeohAI7YoJcHE7kXDAc4Nk0EbuKnJfqtY9YtRkLo/tqkuF7MsBQRhPnPeyjYITp3ZQ==", + "requires": { + "core-util-is": "1.0.2", + "inherits": "2.0.3", + "isarray": "1.0.0", + "process-nextick-args": "2.0.0", + "safe-buffer": "5.1.1", + "string_decoder": "1.0.3", + "util-deprecate": "1.0.2" + } + }, + "string_decoder": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.0.3.tgz", + "integrity": "sha512-4AH6Z5fzNNBcH+6XDMfA/BTt87skxqJlO0lAh3Dker5zThcAxG6mKz+iGu308UKoPPQ8Dcqx/4JhujzltRa+hQ==", + "requires": { + "safe-buffer": "5.1.1" + } + } + } + }, + "console-browserify": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/console-browserify/-/console-browserify-1.1.0.tgz", + "integrity": "sha1-8CQcRXMKn8YyOyBtvzjtx0HQuxA=", + "dev": true, + "requires": { + "date-now": "0.1.4" + } + }, + "constants-browserify": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/constants-browserify/-/constants-browserify-1.0.0.tgz", + "integrity": "sha1-wguW2MYXdIqvHBYCF2DNJ/y4y3U=", + "dev": true + }, + "convert-source-map": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.5.1.tgz", + "integrity": "sha1-uCeAl7m8IpNl3lxiz1/K7YtVmeU=" + }, + "convex-hull": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/convex-hull/-/convex-hull-1.0.3.tgz", + "integrity": "sha1-IKOqbOh/St6i/30XlxyfwcZ+H/8=", + "requires": { + "affine-hull": "1.0.0", + "incremental-convex-hull": "1.0.1", + "monotone-convex-hull-2d": "1.0.1" + } + }, + "core-js": { + "version": "2.5.3", + "resolved": "https://registry.npmjs.org/core-js/-/core-js-2.5.3.tgz", + "integrity": "sha1-isw4NFgk8W2DZbfJtCWRaOjtYD4=" + }, + "core-util-is": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", + "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=" + }, + "country-regex": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/country-regex/-/country-regex-1.1.0.tgz", + "integrity": "sha1-UcMz3N8Sknt+XuucEKyBEqYSCJY=" + }, + "create-ecdh": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/create-ecdh/-/create-ecdh-4.0.0.tgz", + "integrity": "sha1-iIxyNZbN92EvZJgjPuvXo1MBc30=", + "dev": true, + "requires": { + "bn.js": "4.11.8", + "elliptic": "6.4.0" + } + }, + "create-hash": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/create-hash/-/create-hash-1.1.3.tgz", + "integrity": "sha1-YGBCrIuSYnUPSDyt2rD1gZFy2P0=", + "dev": true, + "requires": { + "cipher-base": "1.0.4", + "inherits": "2.0.3", + "ripemd160": "2.0.1", + "sha.js": "2.4.10" + } + }, + "create-hmac": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/create-hmac/-/create-hmac-1.1.6.tgz", + "integrity": "sha1-rLniIaThe9sHbpBlfEK5PjcmzwY=", + "dev": true, + "requires": { + "cipher-base": "1.0.4", + "create-hash": "1.1.3", + "inherits": "2.0.3", + "ripemd160": "2.0.1", + "safe-buffer": "5.1.1", + "sha.js": "2.4.10" + } + }, + "cross-spawn": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-5.1.0.tgz", + "integrity": "sha1-6L0O/uWPz/b4+UUQoKVUu/ojVEk=", + "dev": true, + "requires": { + "lru-cache": "4.1.1", + "shebang-command": "1.2.0", + "which": "1.3.0" + } + }, + "cryptiles": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/cryptiles/-/cryptiles-3.1.2.tgz", + "integrity": "sha1-qJ+7Ig9c4l7FboxKqKT9e1sNKf4=", + "requires": { + "boom": "5.2.0" + }, + "dependencies": { + "boom": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/boom/-/boom-5.2.0.tgz", + "integrity": "sha512-Z5BTk6ZRe4tXXQlkqftmsAUANpXmuwlsF5Oov8ThoMbQRzdGTA1ngYRW160GexgOgjsFOKJz0LYhoNi+2AMBUw==", + "requires": { + "hoek": "4.2.1" + } + } + } + }, + "crypto-browserify": { + "version": "3.12.0", + "resolved": "https://registry.npmjs.org/crypto-browserify/-/crypto-browserify-3.12.0.tgz", + "integrity": "sha512-fz4spIh+znjO2VjL+IdhEpRJ3YN6sMzITSBijk6FK2UvTqruSQW+/cCZTSNsMiZNvUeq0CqurF+dAbyiGOY6Wg==", + "dev": true, + "requires": { + "browserify-cipher": "1.0.0", + "browserify-sign": "4.0.4", + "create-ecdh": "4.0.0", + "create-hash": "1.1.3", + "create-hmac": "1.1.6", + "diffie-hellman": "5.0.2", + "inherits": "2.0.3", + "pbkdf2": "3.0.14", + "public-encrypt": "4.0.0", + "randombytes": "2.0.6", + "randomfill": "1.0.4" + } + }, + "csscolorparser": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/csscolorparser/-/csscolorparser-1.0.3.tgz", + "integrity": "sha1-s085HupNqPPpgjHizNjfnAQfFxs=" + }, + "cubic-hermite": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/cubic-hermite/-/cubic-hermite-1.0.0.tgz", + "integrity": "sha1-hOOy8nKzFFToOTuZu2rtRRaMFOU=" + }, + "cwise": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/cwise/-/cwise-1.0.10.tgz", + "integrity": "sha1-JO7mBy69/WuMb12tsXCQtkmxK+8=", + "requires": { + "cwise-compiler": "1.1.3", + "cwise-parser": "1.0.3", + "static-module": "1.5.0", + "uglify-js": "2.8.29" + } + }, + "cwise-compiler": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/cwise-compiler/-/cwise-compiler-1.1.3.tgz", + "integrity": "sha1-9NZnQQ6FDToxOn0tt7HlBbsDTMU=", + "requires": { + "uniq": "1.0.1" + } + }, + "cwise-parser": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/cwise-parser/-/cwise-parser-1.0.3.tgz", + "integrity": "sha1-jkk8F9VPl8sDCp6YVLyGyd+zVP4=", + "requires": { + "esprima": "1.2.5", + "uniq": "1.0.1" + }, + "dependencies": { + "esprima": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-1.2.5.tgz", + "integrity": "sha1-CZNQL+r2aBODJXVvMPmlH+7sEek=" + } + } + }, + "d": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/d/-/d-1.0.0.tgz", + "integrity": "sha1-dUu1v+VUUdpppYuU1F9MWwRi1Y8=", + "dev": true, + "requires": { + "es5-ext": "0.10.39" + } + }, + "d3": { + "version": "3.5.17", + "resolved": "https://registry.npmjs.org/d3/-/d3-3.5.17.tgz", + "integrity": "sha1-vEZ0gAQ3iyGjYMn8fPUjF5B2L7g=" + }, + "d3-array": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/d3-array/-/d3-array-1.2.1.tgz", + "integrity": "sha512-CyINJQ0SOUHojDdFDH4JEM0552vCR1utGyLHegJHyYH0JyCpSeTPxi4OBqHMA2jJZq4NH782LtaJWBImqI/HBw==" + }, + "d3-collection": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/d3-collection/-/d3-collection-1.0.4.tgz", + "integrity": "sha1-NC39EoN8kJdPM/HMCnha6lcNzcI=" + }, + "d3-color": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/d3-color/-/d3-color-1.0.3.tgz", + "integrity": "sha1-vHZD/KjlOoNH4vva/6I2eWtYUJs=" + }, + "d3-dispatch": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/d3-dispatch/-/d3-dispatch-1.0.3.tgz", + "integrity": "sha1-RuFJHqqbWMNY/OW+TovtYm54cfg=" + }, + "d3-force": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/d3-force/-/d3-force-1.1.0.tgz", + "integrity": "sha512-2HVQz3/VCQs0QeRNZTYb7GxoUCeb6bOzMp/cGcLa87awY9ZsPvXOGeZm0iaGBjXic6I1ysKwMn+g+5jSAdzwcg==", + "requires": { + "d3-collection": "1.0.4", + "d3-dispatch": "1.0.3", + "d3-quadtree": "1.0.3", + "d3-timer": "1.0.7" + } + }, + "d3-interpolate": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/d3-interpolate/-/d3-interpolate-1.1.6.tgz", + "integrity": "sha512-mOnv5a+pZzkNIHtw/V6I+w9Lqm9L5bG3OTXPM5A+QO0yyVMQ4W1uZhR+VOJmazaOZXri2ppbiZ5BUNWT0pFM9A==", + "requires": { + "d3-color": "1.0.3" + } + }, + "d3-quadtree": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/d3-quadtree/-/d3-quadtree-1.0.3.tgz", + "integrity": "sha1-rHmH4+I/6AWpkPKOG1DTj8uCJDg=" + }, + "d3-timer": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/d3-timer/-/d3-timer-1.0.7.tgz", + "integrity": "sha512-vMZXR88XujmG/L5oB96NNKH5lCWwiLM/S2HyyAQLcjWJCloK5shxta4CwOFYLZoY3AWX73v8Lgv4cCAdWtRmOA==" + }, + "dashdash": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz", + "integrity": "sha1-hTz6D3y+L+1d4gMmuN1YEDX24vA=", + "requires": { + "assert-plus": "1.0.0" + } + }, + "date-now": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/date-now/-/date-now-0.1.4.tgz", + "integrity": "sha1-6vQ5/U1ISK105cx9vvIAZyueNFs=", + "dev": true + }, + "decamelize": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", + "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=" + }, + "deep-equal": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/deep-equal/-/deep-equal-1.0.1.tgz", + "integrity": "sha1-9dJgKStmDghO/0zbyfCK0yR0SLU=" + }, + "deep-is": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.3.tgz", + "integrity": "sha1-s2nW+128E+7PUk+RsHD+7cNXzzQ=" + }, + "define-properties": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.2.tgz", + "integrity": "sha1-g6c/L+pWmJj7c3GTyPhzyvbUXJQ=", + "requires": { + "foreach": "2.0.5", + "object-keys": "1.0.11" + } + }, + "defined": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/defined/-/defined-1.0.0.tgz", + "integrity": "sha1-yY2bzvdWdBiOEQlpFRGZ45sfppM=" + }, + "delaunay-triangulate": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/delaunay-triangulate/-/delaunay-triangulate-1.1.6.tgz", + "integrity": "sha1-W7yiGweBmNS8PHV5ajXLuYwllUw=", + "requires": { + "incremental-convex-hull": "1.0.1", + "uniq": "1.0.1" + } + }, + "delayed-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", + "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=" + }, + "des.js": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/des.js/-/des.js-1.0.0.tgz", + "integrity": "sha1-wHTS4qpqipoH29YfmhXCzYPsjsw=", + "dev": true, + "requires": { + "inherits": "2.0.3", + "minimalistic-assert": "1.0.0" + } + }, + "diffie-hellman": { + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/diffie-hellman/-/diffie-hellman-5.0.2.tgz", + "integrity": "sha1-tYNXOScM/ias9jIJn97SoH8gnl4=", + "dev": true, + "requires": { + "bn.js": "4.11.8", + "miller-rabin": "4.0.1", + "randombytes": "2.0.6" + } + }, + "domain-browser": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/domain-browser/-/domain-browser-1.2.0.tgz", + "integrity": "sha512-jnjyiM6eRyZl2H+W8Q/zLMA481hzi0eszAaBUzIVnmYVDBbnLxVNnfu1HgEBvCbL+71FrxMl3E6lpKH7Ge3OXA==", + "dev": true + }, + "double-bits": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/double-bits/-/double-bits-1.1.1.tgz", + "integrity": "sha1-WKu6RUlNpND6Nrc60RoobJGEscY=" + }, + "draw-svg-path": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/draw-svg-path/-/draw-svg-path-1.0.0.tgz", + "integrity": "sha1-bxFtli3TFLmepTTW9Y3WbNvWk3k=", + "requires": { + "abs-svg-path": "0.1.1", + "normalize-svg-path": "0.1.0" + } + }, + "dtype": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/dtype/-/dtype-2.0.0.tgz", + "integrity": "sha1-zQUjI84GFETs0uj1dI9popvihDQ=" + }, + "dup": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/dup/-/dup-1.0.0.tgz", + "integrity": "sha1-UfxaxoX4GWRp3wuQXpNLIK9bQCk=" + }, + "duplexer2": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/duplexer2/-/duplexer2-0.0.2.tgz", + "integrity": "sha1-xhTc9n4vsUmVqRcR5aYX6KYKMds=", + "requires": { + "readable-stream": "1.1.14" + }, + "dependencies": { + "readable-stream": { + "version": "1.1.14", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz", + "integrity": "sha1-fPTFTvZI44EwhMY23SB54WbAgdk=", + "requires": { + "core-util-is": "1.0.2", + "inherits": "2.0.3", + "isarray": "0.0.1", + "string_decoder": "0.10.31" + } + } + } + }, + "duplexify": { + "version": "3.5.3", + "resolved": "https://registry.npmjs.org/duplexify/-/duplexify-3.5.3.tgz", + "integrity": "sha512-g8ID9OroF9hKt2POf8YLayy+9594PzmM3scI00/uBXocX3TWNgoB67hjzkFe9ITAbQOne/lLdBxHXvYUM4ZgGA==", + "requires": { + "end-of-stream": "1.4.1", + "inherits": "2.0.3", + "readable-stream": "2.3.4", + "stream-shift": "1.0.0" + }, + "dependencies": { + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=" + }, + "readable-stream": { + "version": "2.3.4", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.4.tgz", + "integrity": "sha512-vuYxeWYM+fde14+rajzqgeohAI7YoJcHE7kXDAc4Nk0EbuKnJfqtY9YtRkLo/tqkuF7MsBQRhPnPeyjYITp3ZQ==", + "requires": { + "core-util-is": "1.0.2", + "inherits": "2.0.3", + "isarray": "1.0.0", + "process-nextick-args": "2.0.0", + "safe-buffer": "5.1.1", + "string_decoder": "1.0.3", + "util-deprecate": "1.0.2" + } + }, + "string_decoder": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.0.3.tgz", + "integrity": "sha512-4AH6Z5fzNNBcH+6XDMfA/BTt87skxqJlO0lAh3Dker5zThcAxG6mKz+iGu308UKoPPQ8Dcqx/4JhujzltRa+hQ==", + "requires": { + "safe-buffer": "5.1.1" + } + } + } + }, + "earcut": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/earcut/-/earcut-2.1.3.tgz", + "integrity": "sha512-AxdCdWUk1zzK/NuZ7e1ljj6IGC+VAdC3Qb7QQDsXpfNrc5IM8tL9nNXUmEGE6jRHTfZ10zhzRhtDmWVsR5pd3A==" + }, + "ecc-jsbn": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.1.tgz", + "integrity": "sha1-D8c6ntXw1Tw4GTOYUj735UN3dQU=", + "optional": true, + "requires": { + "jsbn": "0.1.1" + } + }, + "edges-to-adjacency-list": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/edges-to-adjacency-list/-/edges-to-adjacency-list-1.0.0.tgz", + "integrity": "sha1-wUbS4ISt37p0pRKTxuAZmkn3V/E=", + "requires": { + "uniq": "1.0.1" + } + }, + "element-size": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/element-size/-/element-size-1.1.1.tgz", + "integrity": "sha1-ZOXxWdlxIWMYRby67K8nnDm1404=" + }, + "elliptic": { + "version": "6.4.0", + "resolved": "https://registry.npmjs.org/elliptic/-/elliptic-6.4.0.tgz", + "integrity": "sha1-ysmvh2LIWDYYcAPI3+GT5eLq5d8=", + "dev": true, + "requires": { + "bn.js": "4.11.8", + "brorand": "1.1.0", + "hash.js": "1.1.3", + "hmac-drbg": "1.0.1", + "inherits": "2.0.3", + "minimalistic-assert": "1.0.0", + "minimalistic-crypto-utils": "1.0.1" + } + }, + "emojis-list": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/emojis-list/-/emojis-list-2.1.0.tgz", + "integrity": "sha1-TapNnbAPmBmIDHn6RXrlsJof04k=", + "dev": true + }, + "encoding": { + "version": "0.1.12", + "resolved": "https://registry.npmjs.org/encoding/-/encoding-0.1.12.tgz", + "integrity": "sha1-U4tm8+5izRq1HsMjgp0flIDHS+s=", + "requires": { + "iconv-lite": "0.4.19" + } + }, + "end-of-stream": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.1.tgz", + "integrity": "sha512-1MkrZNvWTKCaigbn+W15elq2BB/L22nqrSY5DKlo3X6+vclJm8Bb5djXJBmEX6fS3+zCh/F4VBK5Z2KxJt4s2Q==", + "requires": { + "once": "1.4.0" + } + }, + "enhanced-resolve": { + "version": "3.4.1", + "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-3.4.1.tgz", + "integrity": "sha1-BCHjOf1xQZs9oT0Smzl5BAIwR24=", + "dev": true, + "requires": { + "graceful-fs": "4.1.11", + "memory-fs": "0.4.1", + "object-assign": "4.1.1", + "tapable": "0.2.8" + } + }, + "errno": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/errno/-/errno-0.1.7.tgz", + "integrity": "sha512-MfrRBDWzIWifgq6tJj60gkAwtLNb6sQPlcFrSOflcP1aFmmruKQ2wRnze/8V6kgyz7H3FF8Npzv78mZ7XLLflg==", + "dev": true, + "requires": { + "prr": "1.0.1" + } + }, + "error-ex": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.1.tgz", + "integrity": "sha1-+FWobOYa3E6GIcPNoh56dhLDqNw=", + "dev": true, + "requires": { + "is-arrayish": "0.2.1" + } + }, + "es-abstract": { + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.10.0.tgz", + "integrity": "sha512-/uh/DhdqIOSkAWifU+8nG78vlQxdLckUdI/sPgy0VhuXi2qJ7T8czBmqIYtLQVpCIFYafChnsRsB5pyb1JdmCQ==", + "requires": { + "es-to-primitive": "1.1.1", + "function-bind": "1.1.1", + "has": "1.0.1", + "is-callable": "1.1.3", + "is-regex": "1.0.4" + } + }, + "es-to-primitive": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.1.1.tgz", + "integrity": "sha1-RTVSSKiJeQNLZ5Lhm7gfK3l13Q0=", + "requires": { + "is-callable": "1.1.3", + "is-date-object": "1.0.1", + "is-symbol": "1.0.1" + } + }, + "es5-ext": { + "version": "0.10.39", + "resolved": "https://registry.npmjs.org/es5-ext/-/es5-ext-0.10.39.tgz", + "integrity": "sha512-AlaXZhPHl0po/uxMx1tyrlt1O86M6D5iVaDH8UgLfgek4kXTX6vzsRfJQWC2Ku+aG8pkw1XWzh9eTkwfVrsD5g==", + "dev": true, + "requires": { + "es6-iterator": "2.0.3", + "es6-symbol": "3.1.1" + } + }, + "es6-iterator": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/es6-iterator/-/es6-iterator-2.0.3.tgz", + "integrity": "sha1-p96IkUGgWpSwhUQDstCg+/qY87c=", + "dev": true, + "requires": { + "d": "1.0.0", + "es5-ext": "0.10.39", + "es6-symbol": "3.1.1" + } + }, + "es6-map": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/es6-map/-/es6-map-0.1.5.tgz", + "integrity": "sha1-kTbgUD3MBqMBaQ8LsU/042TpSfA=", + "dev": true, + "requires": { + "d": "1.0.0", + "es5-ext": "0.10.39", + "es6-iterator": "2.0.3", + "es6-set": "0.1.5", + "es6-symbol": "3.1.1", + "event-emitter": "0.3.5" + } + }, + "es6-promise": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/es6-promise/-/es6-promise-3.3.1.tgz", + "integrity": "sha1-oIzd6EzNvzTQJ6FFG8kdS80ophM=" + }, + "es6-set": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/es6-set/-/es6-set-0.1.5.tgz", + "integrity": "sha1-0rPsXU2ADO2BjbU40ol02wpzzLE=", + "dev": true, + "requires": { + "d": "1.0.0", + "es5-ext": "0.10.39", + "es6-iterator": "2.0.3", + "es6-symbol": "3.1.1", + "event-emitter": "0.3.5" + } + }, + "es6-symbol": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/es6-symbol/-/es6-symbol-3.1.1.tgz", + "integrity": "sha1-vwDvT9q2uhtG7Le2KbTH7VcVzHc=", + "dev": true, + "requires": { + "d": "1.0.0", + "es5-ext": "0.10.39" + } + }, + "es6-weak-map": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/es6-weak-map/-/es6-weak-map-2.0.2.tgz", + "integrity": "sha1-XjqzIlH/0VOKH45f+hNXdy+S2W8=", + "dev": true, + "requires": { + "d": "1.0.0", + "es5-ext": "0.10.39", + "es6-iterator": "2.0.3", + "es6-symbol": "3.1.1" + } + }, + "escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=" + }, + "escodegen": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/escodegen/-/escodegen-1.9.0.tgz", + "integrity": "sha512-v0MYvNQ32bzwoG2OSFzWAkuahDQHK92JBN0pTAALJ4RIxEZe766QJPDR8Hqy7XNUy5K3fnVL76OqYAdc4TZEIw==", + "requires": { + "esprima": "3.1.3", + "estraverse": "4.2.0", + "esutils": "2.0.2", + "optionator": "0.8.2", + "source-map": "0.5.7" + }, + "dependencies": { + "esprima": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-3.1.3.tgz", + "integrity": "sha1-/cpRzuYTOJXjyI1TXOSdv/YqRjM=" + } + } + }, + "escope": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/escope/-/escope-3.6.0.tgz", + "integrity": "sha1-4Bl16BJ4GhY6ba392AOY3GTIicM=", + "dev": true, + "requires": { + "es6-map": "0.1.5", + "es6-weak-map": "2.0.2", + "esrecurse": "4.2.0", + "estraverse": "4.2.0" + } + }, + "esprima": { + "version": "2.7.3", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-2.7.3.tgz", + "integrity": "sha1-luO3DVd59q1JzQMmc9HDEnZ7pYE=" + }, + "espurify": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/espurify/-/espurify-1.7.0.tgz", + "integrity": "sha1-HFz2y8zDLm9jk4C9T5kfq5up0iY=", + "requires": { + "core-js": "2.5.3" + } + }, + "esrecurse": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.2.0.tgz", + "integrity": "sha1-+pVo2Y04I/mkHZHpAtyrnqblsWM=", + "dev": true, + "requires": { + "estraverse": "4.2.0", + "object-assign": "4.1.1" + } + }, + "estraverse": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.2.0.tgz", + "integrity": "sha1-De4/7TH81GlhjOc0IJn8GvoL2xM=" + }, + "esutils": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.2.tgz", + "integrity": "sha1-Cr9PHKpbyx96nYrMbepPqqBLrJs=" + }, + "event-emitter": { + "version": "0.3.5", + "resolved": "https://registry.npmjs.org/event-emitter/-/event-emitter-0.3.5.tgz", + "integrity": "sha1-34xp7vFkeSPHFXuc6DhAYQsCzDk=", + "dev": true, + "requires": { + "d": "1.0.0", + "es5-ext": "0.10.39" + } + }, + "events": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/events/-/events-1.1.1.tgz", + "integrity": "sha1-nr23Y1rQmccNzEwqH1AEKI6L2SQ=" + }, + "evp_bytestokey": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/evp_bytestokey/-/evp_bytestokey-1.0.3.tgz", + "integrity": "sha512-/f2Go4TognH/KvCISP7OUsHn85hT9nUkxxA9BEWxFn+Oj9o8ZNLm/40hdlgSLyuOimsrTKLUMEorQexp/aPQeA==", + "dev": true, + "requires": { + "md5.js": "1.3.4", + "safe-buffer": "5.1.1" + } + }, + "execa": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/execa/-/execa-0.7.0.tgz", + "integrity": "sha1-lEvs00zEHuMqY6n68nrVpl/Fl3c=", + "dev": true, + "requires": { + "cross-spawn": "5.1.0", + "get-stream": "3.0.0", + "is-stream": "1.1.0", + "npm-run-path": "2.0.2", + "p-finally": "1.0.0", + "signal-exit": "3.0.2", + "strip-eof": "1.0.0" + } + }, + "expand-brackets": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-0.1.5.tgz", + "integrity": "sha1-3wcoTjQqgHzXM6xa9yQR5YHRF3s=", + "dev": true, + "requires": { + "is-posix-bracket": "0.1.1" + } + }, + "expand-range": { + "version": "1.8.2", + "resolved": "https://registry.npmjs.org/expand-range/-/expand-range-1.8.2.tgz", + "integrity": "sha1-opnv/TNf4nIeuujiV+x5ZE/IUzc=", + "dev": true, + "requires": { + "fill-range": "2.2.3" + } + }, + "extend": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.1.tgz", + "integrity": "sha1-p1Xqe8Gt/MWjHOfnYtuq3F5jZEQ=" + }, + "extglob": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/extglob/-/extglob-0.3.2.tgz", + "integrity": "sha1-Lhj/PS9JqydlzskCPwEdqo2DSaE=", + "dev": true, + "requires": { + "is-extglob": "1.0.0" + } + }, + "extract-frustum-planes": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/extract-frustum-planes/-/extract-frustum-planes-1.0.0.tgz", + "integrity": "sha1-l9VwP/BWTIw8aDjKxF+ee8UsnvU=" + }, + "extsprintf": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz", + "integrity": "sha1-lpGEQOMEGnpBT4xS48V06zw+HgU=" + }, + "falafel": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/falafel/-/falafel-2.1.0.tgz", + "integrity": "sha1-lrsXdh2rqU9G0AFzizzt86Z/4Gw=", + "requires": { + "acorn": "5.4.1", + "foreach": "2.0.5", + "isarray": "0.0.1", + "object-keys": "1.0.11" + } + }, + "fast-deep-equal": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-1.0.0.tgz", + "integrity": "sha1-liVqO8l1WV6zbYLpkp0GDYk0Of8=", + "dev": true + }, + "fast-isnumeric": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/fast-isnumeric/-/fast-isnumeric-1.1.1.tgz", + "integrity": "sha1-V7gcB6PAnLnsO++cFhgYmS2JNkM=" + }, + "fast-json-stable-stringify": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.0.0.tgz", + "integrity": "sha1-1RQsDK7msRifh9OnYREGT4bIu/I=", + "dev": true + }, + "fast-levenshtein": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", + "integrity": "sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc=" + }, + "feature-filter": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/feature-filter/-/feature-filter-2.2.0.tgz", + "integrity": "sha1-PMNWAV6WjDYq+99/8bt0Td9/wuA=" + }, + "filename-regex": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/filename-regex/-/filename-regex-2.0.1.tgz", + "integrity": "sha1-wcS5vuPglyXdsQa3XB4wH+LxiyY=", + "dev": true + }, + "fill-range": { + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-2.2.3.tgz", + "integrity": "sha1-ULd9/X5Gm8dJJHCWNpn+eoSFpyM=", + "dev": true, + "requires": { + "is-number": "2.1.0", + "isobject": "2.1.0", + "randomatic": "1.1.7", + "repeat-element": "1.1.2", + "repeat-string": "1.6.1" + } + }, + "filtered-vector": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/filtered-vector/-/filtered-vector-1.2.4.tgz", + "integrity": "sha1-VkU8A030MC0pPKjs3qw/kKvGeNM=", + "requires": { + "binary-search-bounds": "1.0.0", + "cubic-hermite": "1.0.0" + } + }, + "find-up": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-2.1.0.tgz", + "integrity": "sha1-RdG35QbHF93UgndaK3eSCjwMV6c=", + "dev": true, + "requires": { + "locate-path": "2.0.0" + } + }, + "findup": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/findup/-/findup-0.1.5.tgz", + "integrity": "sha1-itkpozk7rGJ5V6fl3kYjsGsOLOs=", + "requires": { + "colors": "0.6.2", + "commander": "2.1.0" + } + }, + "flatten-vertex-data": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/flatten-vertex-data/-/flatten-vertex-data-1.0.0.tgz", + "integrity": "sha1-1hyU8qZWTzAdZni3JhYWrwAEcIw=", + "requires": { + "array-pack-2d": "0.1.1", + "dtype": "2.0.0", + "is-typedarray": "1.0.0" + } + }, + "font-atlas-sdf": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/font-atlas-sdf/-/font-atlas-sdf-1.3.3.tgz", + "integrity": "sha512-GxUpcdkdoHgC3UrpMuA7JmG1Ty/MY0BhfmV8r7ZSv3bkqBY5vmRIjcj7Pg8iqj20B03vlU6fUhdpyIgEo/Z35w==", + "requires": { + "optical-properties": "1.0.0", + "tiny-sdf": "1.0.2" + } + }, + "for-each": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.2.tgz", + "integrity": "sha1-LEBFC5NI6X8oEyJZO6lnBLmr1NQ=", + "requires": { + "is-function": "1.0.1" + } + }, + "for-in": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/for-in/-/for-in-1.0.2.tgz", + "integrity": "sha1-gQaNKVqBQuwKxybG4iAMMPttXoA=", + "dev": true + }, + "for-own": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/for-own/-/for-own-0.1.5.tgz", + "integrity": "sha1-UmXGgaTylNq78XyVCbZ2OqhFEM4=", + "dev": true, + "requires": { + "for-in": "1.0.2" + } + }, + "foreach": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/foreach/-/foreach-2.0.5.tgz", + "integrity": "sha1-C+4AUBiusmDQo6865ljdATbsG5k=" + }, + "forever-agent": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz", + "integrity": "sha1-+8cfDEGt6zf5bFd60e1C2P2sypE=" + }, + "form-data": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.3.2.tgz", + "integrity": "sha1-SXBJi+YEwgwAXU9cI67NIda0kJk=", + "requires": { + "asynckit": "0.4.0", + "combined-stream": "1.0.6", + "mime-types": "2.1.18" + } + }, + "from2": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/from2/-/from2-2.3.0.tgz", + "integrity": "sha1-i/tVAr3kpNNs/e6gB/zKIdfjgq8=", + "requires": { + "inherits": "2.0.3", + "readable-stream": "2.3.4" + }, + "dependencies": { + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=" + }, + "readable-stream": { + "version": "2.3.4", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.4.tgz", + "integrity": "sha512-vuYxeWYM+fde14+rajzqgeohAI7YoJcHE7kXDAc4Nk0EbuKnJfqtY9YtRkLo/tqkuF7MsBQRhPnPeyjYITp3ZQ==", + "requires": { + "core-util-is": "1.0.2", + "inherits": "2.0.3", + "isarray": "1.0.0", + "process-nextick-args": "2.0.0", + "safe-buffer": "5.1.1", + "string_decoder": "1.0.3", + "util-deprecate": "1.0.2" + } + }, + "string_decoder": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.0.3.tgz", + "integrity": "sha512-4AH6Z5fzNNBcH+6XDMfA/BTt87skxqJlO0lAh3Dker5zThcAxG6mKz+iGu308UKoPPQ8Dcqx/4JhujzltRa+hQ==", + "requires": { + "safe-buffer": "5.1.1" + } + } + } + }, + "from2-array": { + "version": "0.0.4", + "resolved": "https://registry.npmjs.org/from2-array/-/from2-array-0.0.4.tgz", + "integrity": "sha1-6vwWtl9uJxm81X/cGGkAWsEzLNY=", + "dev": true, + "requires": { + "from2": "2.3.0" + } + }, + "fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=" + }, + "fsevents": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-1.1.3.tgz", + "integrity": "sha512-WIr7iDkdmdbxu/Gh6eKEZJL6KPE74/5MEsf2whTOFNxbIoIixogroLdKYqB6FDav4Wavh/lZdzzd3b2KxIXC5Q==", + "dev": true, + "optional": true, + "requires": { + "nan": "2.8.0", + "node-pre-gyp": "0.6.39" + }, + "dependencies": { + "abbrev": { + "version": "1.1.0", + "bundled": true, + "dev": true, + "optional": true + }, + "ajv": { + "version": "4.11.8", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "co": "4.6.0", + "json-stable-stringify": "1.0.1" + } + }, + "ansi-regex": { + "version": "2.1.1", + "bundled": true, + "dev": true + }, + "aproba": { + "version": "1.1.1", + "bundled": true, + "dev": true, + "optional": true + }, + "are-we-there-yet": { + "version": "1.1.4", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "delegates": "1.0.0", + "readable-stream": "2.2.9" + } + }, + "asn1": { + "version": "0.2.3", + "bundled": true, + "dev": true, + "optional": true + }, + "assert-plus": { + "version": "0.2.0", + "bundled": true, + "dev": true, + "optional": true + }, + "asynckit": { + "version": "0.4.0", + "bundled": true, + "dev": true, + "optional": true + }, + "aws-sign2": { + "version": "0.6.0", + "bundled": true, + "dev": true, + "optional": true + }, + "aws4": { + "version": "1.6.0", + "bundled": true, + "dev": true, + "optional": true + }, + "balanced-match": { + "version": "0.4.2", + "bundled": true, + "dev": true + }, + "bcrypt-pbkdf": { + "version": "1.0.1", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "tweetnacl": "0.14.5" + } + }, + "block-stream": { + "version": "0.0.9", + "bundled": true, + "dev": true, + "requires": { + "inherits": "2.0.3" + } + }, + "boom": { + "version": "2.10.1", + "bundled": true, + "dev": true, + "requires": { + "hoek": "2.16.3" + } + }, + "brace-expansion": { + "version": "1.1.7", + "bundled": true, + "dev": true, + "requires": { + "balanced-match": "0.4.2", + "concat-map": "0.0.1" + } + }, + "buffer-shims": { + "version": "1.0.0", + "bundled": true, + "dev": true + }, + "caseless": { + "version": "0.12.0", + "bundled": true, + "dev": true, + "optional": true + }, + "co": { + "version": "4.6.0", + "bundled": true, + "dev": true, + "optional": true + }, + "code-point-at": { + "version": "1.1.0", + "bundled": true, + "dev": true + }, + "combined-stream": { + "version": "1.0.5", + "bundled": true, + "dev": true, + "requires": { + "delayed-stream": "1.0.0" + } + }, + "concat-map": { + "version": "0.0.1", + "bundled": true, + "dev": true + }, + "console-control-strings": { + "version": "1.1.0", + "bundled": true, + "dev": true + }, + "core-util-is": { + "version": "1.0.2", + "bundled": true, + "dev": true + }, + "cryptiles": { + "version": "2.0.5", + "bundled": true, + "dev": true, + "requires": { + "boom": "2.10.1" + } + }, + "dashdash": { + "version": "1.14.1", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "assert-plus": "1.0.0" + }, + "dependencies": { + "assert-plus": { + "version": "1.0.0", + "bundled": true, + "dev": true, + "optional": true + } + } + }, + "debug": { + "version": "2.6.8", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "ms": "2.0.0" + } + }, + "deep-extend": { + "version": "0.4.2", + "bundled": true, + "dev": true, + "optional": true + }, + "delayed-stream": { + "version": "1.0.0", + "bundled": true, + "dev": true + }, + "delegates": { + "version": "1.0.0", + "bundled": true, + "dev": true, + "optional": true + }, + "detect-libc": { + "version": "1.0.2", + "bundled": true, + "dev": true, + "optional": true + }, + "ecc-jsbn": { + "version": "0.1.1", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "jsbn": "0.1.1" + } + }, + "extend": { + "version": "3.0.1", + "bundled": true, + "dev": true, + "optional": true + }, + "extsprintf": { + "version": "1.0.2", + "bundled": true, + "dev": true + }, + "forever-agent": { + "version": "0.6.1", + "bundled": true, + "dev": true, + "optional": true + }, + "form-data": { + "version": "2.1.4", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "asynckit": "0.4.0", + "combined-stream": "1.0.5", + "mime-types": "2.1.15" + } + }, + "fs.realpath": { + "version": "1.0.0", + "bundled": true, + "dev": true + }, + "fstream": { + "version": "1.0.11", + "bundled": true, + "dev": true, + "requires": { + "graceful-fs": "4.1.11", + "inherits": "2.0.3", + "mkdirp": "0.5.1", + "rimraf": "2.6.1" + } + }, + "fstream-ignore": { + "version": "1.0.5", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "fstream": "1.0.11", + "inherits": "2.0.3", + "minimatch": "3.0.4" + } + }, + "gauge": { + "version": "2.7.4", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "aproba": "1.1.1", + "console-control-strings": "1.1.0", + "has-unicode": "2.0.1", + "object-assign": "4.1.1", + "signal-exit": "3.0.2", + "string-width": "1.0.2", + "strip-ansi": "3.0.1", + "wide-align": "1.1.2" + } + }, + "getpass": { + "version": "0.1.7", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "assert-plus": "1.0.0" + }, + "dependencies": { + "assert-plus": { + "version": "1.0.0", + "bundled": true, + "dev": true, + "optional": true + } + } + }, + "glob": { + "version": "7.1.2", + "bundled": true, + "dev": true, + "requires": { + "fs.realpath": "1.0.0", + "inflight": "1.0.6", + "inherits": "2.0.3", + "minimatch": "3.0.4", + "once": "1.4.0", + "path-is-absolute": "1.0.1" + } + }, + "graceful-fs": { + "version": "4.1.11", + "bundled": true, + "dev": true + }, + "har-schema": { + "version": "1.0.5", + "bundled": true, + "dev": true, + "optional": true + }, + "har-validator": { + "version": "4.2.1", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "ajv": "4.11.8", + "har-schema": "1.0.5" + } + }, + "has-unicode": { + "version": "2.0.1", + "bundled": true, + "dev": true, + "optional": true + }, + "hawk": { + "version": "3.1.3", + "bundled": true, + "dev": true, + "requires": { + "boom": "2.10.1", + "cryptiles": "2.0.5", + "hoek": "2.16.3", + "sntp": "1.0.9" + } + }, + "hoek": { + "version": "2.16.3", + "bundled": true, + "dev": true + }, + "http-signature": { + "version": "1.1.1", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "assert-plus": "0.2.0", + "jsprim": "1.4.0", + "sshpk": "1.13.0" + } + }, + "inflight": { + "version": "1.0.6", + "bundled": true, + "dev": true, + "requires": { + "once": "1.4.0", + "wrappy": "1.0.2" + } + }, + "inherits": { + "version": "2.0.3", + "bundled": true, + "dev": true + }, + "ini": { + "version": "1.3.4", + "bundled": true, + "dev": true, + "optional": true + }, + "is-fullwidth-code-point": { + "version": "1.0.0", + "bundled": true, + "dev": true, + "requires": { + "number-is-nan": "1.0.1" + } + }, + "is-typedarray": { + "version": "1.0.0", + "bundled": true, + "dev": true, + "optional": true + }, + "isarray": { + "version": "1.0.0", + "bundled": true, + "dev": true + }, + "isstream": { + "version": "0.1.2", + "bundled": true, + "dev": true, + "optional": true + }, + "jodid25519": { + "version": "1.0.2", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "jsbn": "0.1.1" + } + }, + "jsbn": { + "version": "0.1.1", + "bundled": true, + "dev": true, + "optional": true + }, + "json-schema": { + "version": "0.2.3", + "bundled": true, + "dev": true, + "optional": true + }, + "json-stable-stringify": { + "version": "1.0.1", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "jsonify": "0.0.0" + } + }, + "json-stringify-safe": { + "version": "5.0.1", + "bundled": true, + "dev": true, + "optional": true + }, + "jsonify": { + "version": "0.0.0", + "bundled": true, + "dev": true, + "optional": true + }, + "jsprim": { + "version": "1.4.0", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "assert-plus": "1.0.0", + "extsprintf": "1.0.2", + "json-schema": "0.2.3", + "verror": "1.3.6" + }, + "dependencies": { + "assert-plus": { + "version": "1.0.0", + "bundled": true, + "dev": true, + "optional": true + } + } + }, + "mime-db": { + "version": "1.27.0", + "bundled": true, + "dev": true + }, + "mime-types": { + "version": "2.1.15", + "bundled": true, + "dev": true, + "requires": { + "mime-db": "1.27.0" + } + }, + "minimatch": { + "version": "3.0.4", + "bundled": true, + "dev": true, + "requires": { + "brace-expansion": "1.1.7" + } + }, + "minimist": { + "version": "0.0.8", + "bundled": true, + "dev": true + }, + "mkdirp": { + "version": "0.5.1", + "bundled": true, + "dev": true, + "requires": { + "minimist": "0.0.8" + } + }, + "ms": { + "version": "2.0.0", + "bundled": true, + "dev": true, + "optional": true + }, + "node-pre-gyp": { + "version": "0.6.39", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "detect-libc": "1.0.2", + "hawk": "3.1.3", + "mkdirp": "0.5.1", + "nopt": "4.0.1", + "npmlog": "4.1.0", + "rc": "1.2.1", + "request": "2.81.0", + "rimraf": "2.6.1", + "semver": "5.3.0", + "tar": "2.2.1", + "tar-pack": "3.4.0" + } + }, + "nopt": { + "version": "4.0.1", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "abbrev": "1.1.0", + "osenv": "0.1.4" + } + }, + "npmlog": { + "version": "4.1.0", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "are-we-there-yet": "1.1.4", + "console-control-strings": "1.1.0", + "gauge": "2.7.4", + "set-blocking": "2.0.0" + } + }, + "number-is-nan": { + "version": "1.0.1", + "bundled": true, + "dev": true + }, + "oauth-sign": { + "version": "0.8.2", + "bundled": true, + "dev": true, + "optional": true + }, + "object-assign": { + "version": "4.1.1", + "bundled": true, + "dev": true, + "optional": true + }, + "once": { + "version": "1.4.0", + "bundled": true, + "dev": true, + "requires": { + "wrappy": "1.0.2" + } + }, + "os-homedir": { + "version": "1.0.2", + "bundled": true, + "dev": true, + "optional": true + }, + "os-tmpdir": { + "version": "1.0.2", + "bundled": true, + "dev": true, + "optional": true + }, + "osenv": { + "version": "0.1.4", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "os-homedir": "1.0.2", + "os-tmpdir": "1.0.2" + } + }, + "path-is-absolute": { + "version": "1.0.1", + "bundled": true, + "dev": true + }, + "performance-now": { + "version": "0.2.0", + "bundled": true, + "dev": true, + "optional": true + }, + "process-nextick-args": { + "version": "1.0.7", + "bundled": true, + "dev": true + }, + "punycode": { + "version": "1.4.1", + "bundled": true, + "dev": true, + "optional": true + }, + "qs": { + "version": "6.4.0", + "bundled": true, + "dev": true, + "optional": true + }, + "rc": { + "version": "1.2.1", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "deep-extend": "0.4.2", + "ini": "1.3.4", + "minimist": "1.2.0", + "strip-json-comments": "2.0.1" + }, + "dependencies": { + "minimist": { + "version": "1.2.0", + "bundled": true, + "dev": true, + "optional": true + } + } + }, + "readable-stream": { + "version": "2.2.9", + "bundled": true, + "dev": true, + "requires": { + "buffer-shims": "1.0.0", + "core-util-is": "1.0.2", + "inherits": "2.0.3", + "isarray": "1.0.0", + "process-nextick-args": "1.0.7", + "string_decoder": "1.0.1", + "util-deprecate": "1.0.2" + } + }, + "request": { + "version": "2.81.0", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "aws-sign2": "0.6.0", + "aws4": "1.6.0", + "caseless": "0.12.0", + "combined-stream": "1.0.5", + "extend": "3.0.1", + "forever-agent": "0.6.1", + "form-data": "2.1.4", + "har-validator": "4.2.1", + "hawk": "3.1.3", + "http-signature": "1.1.1", + "is-typedarray": "1.0.0", + "isstream": "0.1.2", + "json-stringify-safe": "5.0.1", + "mime-types": "2.1.15", + "oauth-sign": "0.8.2", + "performance-now": "0.2.0", + "qs": "6.4.0", + "safe-buffer": "5.0.1", + "stringstream": "0.0.5", + "tough-cookie": "2.3.2", + "tunnel-agent": "0.6.0", + "uuid": "3.0.1" + } + }, + "rimraf": { + "version": "2.6.1", + "bundled": true, + "dev": true, + "requires": { + "glob": "7.1.2" + } + }, + "safe-buffer": { + "version": "5.0.1", + "bundled": true, + "dev": true + }, + "semver": { + "version": "5.3.0", + "bundled": true, + "dev": true, + "optional": true + }, + "set-blocking": { + "version": "2.0.0", + "bundled": true, + "dev": true, + "optional": true + }, + "signal-exit": { + "version": "3.0.2", + "bundled": true, + "dev": true, + "optional": true + }, + "sntp": { + "version": "1.0.9", + "bundled": true, + "dev": true, + "requires": { + "hoek": "2.16.3" + } + }, + "sshpk": { + "version": "1.13.0", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "asn1": "0.2.3", + "assert-plus": "1.0.0", + "bcrypt-pbkdf": "1.0.1", + "dashdash": "1.14.1", + "ecc-jsbn": "0.1.1", + "getpass": "0.1.7", + "jodid25519": "1.0.2", + "jsbn": "0.1.1", + "tweetnacl": "0.14.5" + }, + "dependencies": { + "assert-plus": { + "version": "1.0.0", + "bundled": true, + "dev": true, + "optional": true + } + } + }, + "string-width": { + "version": "1.0.2", + "bundled": true, + "dev": true, + "requires": { + "code-point-at": "1.1.0", + "is-fullwidth-code-point": "1.0.0", + "strip-ansi": "3.0.1" + } + }, + "string_decoder": { + "version": "1.0.1", + "bundled": true, + "dev": true, + "requires": { + "safe-buffer": "5.0.1" + } + }, + "stringstream": { + "version": "0.0.5", + "bundled": true, + "dev": true, + "optional": true + }, + "strip-ansi": { + "version": "3.0.1", + "bundled": true, + "dev": true, + "requires": { + "ansi-regex": "2.1.1" + } + }, + "strip-json-comments": { + "version": "2.0.1", + "bundled": true, + "dev": true, + "optional": true + }, + "tar": { + "version": "2.2.1", + "bundled": true, + "dev": true, + "requires": { + "block-stream": "0.0.9", + "fstream": "1.0.11", + "inherits": "2.0.3" + } + }, + "tar-pack": { + "version": "3.4.0", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "debug": "2.6.8", + "fstream": "1.0.11", + "fstream-ignore": "1.0.5", + "once": "1.4.0", + "readable-stream": "2.2.9", + "rimraf": "2.6.1", + "tar": "2.2.1", + "uid-number": "0.0.6" + } + }, + "tough-cookie": { + "version": "2.3.2", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "punycode": "1.4.1" + } + }, + "tunnel-agent": { + "version": "0.6.0", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "safe-buffer": "5.0.1" + } + }, + "tweetnacl": { + "version": "0.14.5", + "bundled": true, + "dev": true, + "optional": true + }, + "uid-number": { + "version": "0.0.6", + "bundled": true, + "dev": true, + "optional": true + }, + "util-deprecate": { + "version": "1.0.2", + "bundled": true, + "dev": true + }, + "uuid": { + "version": "3.0.1", + "bundled": true, + "dev": true, + "optional": true + }, + "verror": { + "version": "1.3.6", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "extsprintf": "1.0.2" + } + }, + "wide-align": { + "version": "1.1.2", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "string-width": "1.0.2" + } + }, + "wrappy": { + "version": "1.0.2", + "bundled": true, + "dev": true + } + } + }, + "function-bind": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", + "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==" + }, + "functional-red-black-tree": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz", + "integrity": "sha1-GwqzvVU7Kg1jmdKcDj6gslIHgyc=" + }, + "gamma": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/gamma/-/gamma-0.1.0.tgz", + "integrity": "sha1-MxVkNAO/J5BsqAqzfDbs6UQO8zA=" + }, + "geojson-area": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/geojson-area/-/geojson-area-0.1.0.tgz", + "integrity": "sha1-1I2AcILPrfSnjfE0m+UPOL8YlK4=", + "requires": { + "wgs84": "0.0.0" + } + }, + "geojson-rewind": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/geojson-rewind/-/geojson-rewind-0.1.0.tgz", + "integrity": "sha1-VwIqBUsZZmDXVTVP5dJmhNkM0Bk=", + "requires": { + "concat-stream": "1.2.1", + "geojson-area": "0.1.0", + "minimist": "0.0.5" + }, + "dependencies": { + "concat-stream": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.2.1.tgz", + "integrity": "sha1-81EAtsRjeL+6i2uA+fDQzN8T3GA=", + "requires": { + "bops": "0.0.6" + } + }, + "minimist": { + "version": "0.0.5", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.5.tgz", + "integrity": "sha1-16oye87PUY+RBqxrjwA/o7zqhWY=" + } + } + }, + "geojson-vt": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/geojson-vt/-/geojson-vt-2.4.0.tgz", + "integrity": "sha1-PBz0RJPzXrTSxwyV2mVQ3mYHLAU=" + }, + "get-caller-file": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-1.0.2.tgz", + "integrity": "sha1-9wLmMSfn4jHBYKgMFVSstw1QR+U=", + "dev": true + }, + "get-canvas-context": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/get-canvas-context/-/get-canvas-context-1.0.2.tgz", + "integrity": "sha1-1ue1C8TkyGNXzTnyJkeoS3NgHpM=" + }, + "get-stream": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-3.0.0.tgz", + "integrity": "sha1-jpQ9E1jcN1VQVOy+LtsFqhdO3hQ=", + "dev": true + }, + "getpass": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz", + "integrity": "sha1-Xv+OPmhNVprkyysSgmBOi6YhSfo=", + "requires": { + "assert-plus": "1.0.0" + } + }, + "gl-axes3d": { + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/gl-axes3d/-/gl-axes3d-1.2.7.tgz", + "integrity": "sha512-PXyLDQR3+shlvmJg8At0bdsA1FdsotA1fRAz1zktsPhx8dwghE2aGKZ2bLLppYRndbXAgMmBhz+dz+wlZltLsw==", + "requires": { + "bit-twiddle": "1.0.2", + "dup": "1.0.0", + "extract-frustum-planes": "1.0.0", + "gl-buffer": "2.1.2", + "gl-mat4": "1.1.4", + "gl-shader": "4.2.1", + "gl-state": "1.0.0", + "gl-vao": "1.3.0", + "gl-vec4": "1.0.1", + "glslify": "6.1.0", + "robust-orientation": "1.1.3", + "split-polygon": "1.0.0", + "vectorize-text": "3.0.2" + } + }, + "gl-buffer": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/gl-buffer/-/gl-buffer-2.1.2.tgz", + "integrity": "sha1-LbjZwaVSf7oM25EonCBuiCuInNs=", + "requires": { + "ndarray": "1.0.18", + "ndarray-ops": "1.2.2", + "typedarray-pool": "1.1.0" + } + }, + "gl-constants": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/gl-constants/-/gl-constants-1.0.0.tgz", + "integrity": "sha1-WXpQTjZHUP9QJTqjX43qevSl0jM=" + }, + "gl-contour2d": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/gl-contour2d/-/gl-contour2d-1.1.4.tgz", + "integrity": "sha512-deoY6k5ZcQfh5brlF3nXKs8FqhMNejlxIqWcK+bKenLcThJF94OR7DtQDwLwNXsYAZlsoDt+G01efXid6Modkg==", + "requires": { + "binary-search-bounds": "2.0.4", + "cdt2d": "1.0.0", + "clean-pslg": "1.1.2", + "gl-buffer": "2.1.2", + "gl-shader": "4.2.1", + "glslify": "6.1.0", + "iota-array": "1.0.0", + "ndarray": "1.0.18", + "surface-nets": "1.0.2" + }, + "dependencies": { + "binary-search-bounds": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/binary-search-bounds/-/binary-search-bounds-2.0.4.tgz", + "integrity": "sha512-2hg5kgdKql5ClF2ErBcSx0U5bnl5hgS4v7wMnLFodyR47yMtj2w+UAZB+0CiqyHct2q543i7Bi4/aMIegorCCg==" + } + } + }, + "gl-error3d": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/gl-error3d/-/gl-error3d-1.0.7.tgz", + "integrity": "sha512-otIih1SAh7Fo8DaaGQXOrg307cVpOjtTOwgiJzmmHAglD2EaKVSzNHONI5RVVVP+bBaObZz+wW18Mpeasij9pA==", + "requires": { + "gl-buffer": "2.1.2", + "gl-shader": "4.2.1", + "gl-vao": "1.3.0", + "glslify": "6.1.0" + } + }, + "gl-fbo": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/gl-fbo/-/gl-fbo-2.0.5.tgz", + "integrity": "sha1-D6daSXz3h2lVMGkcjwSrtvtV+iI=", + "requires": { + "gl-texture2d": "2.1.0" + } + }, + "gl-format-compiler-error": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/gl-format-compiler-error/-/gl-format-compiler-error-1.0.3.tgz", + "integrity": "sha1-DHmxdRiZzpcy6GJA8JCqQemEcag=", + "requires": { + "add-line-numbers": "1.0.1", + "gl-constants": "1.0.0", + "glsl-shader-name": "1.0.0", + "sprintf-js": "1.1.1" + } + }, + "gl-heatmap2d": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/gl-heatmap2d/-/gl-heatmap2d-1.0.4.tgz", + "integrity": "sha512-AWJykMTbCM0ZT20jiFaauRVmLv9dxtNNuTS1NQlKD8yBD0iZ62mgWLeYLUMjil6XN8K3P9EpUCBolvcx1Wf0kA==", + "requires": { + "binary-search-bounds": "2.0.4", + "gl-buffer": "2.1.2", + "gl-shader": "4.2.1", + "glslify": "6.1.0", + "iota-array": "1.0.0", + "typedarray-pool": "1.1.0" + }, + "dependencies": { + "binary-search-bounds": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/binary-search-bounds/-/binary-search-bounds-2.0.4.tgz", + "integrity": "sha512-2hg5kgdKql5ClF2ErBcSx0U5bnl5hgS4v7wMnLFodyR47yMtj2w+UAZB+0CiqyHct2q543i7Bi4/aMIegorCCg==" + } + } + }, + "gl-line3d": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/gl-line3d/-/gl-line3d-1.1.2.tgz", + "integrity": "sha512-OEkE5dsTunz0JApcx/+T57kOXWY+jNUS4nntnhEy14OcRCb4K6gz53HB+Oi8Cz9nb/95f805QLNgnkhDpdz8uw==", + "requires": { + "binary-search-bounds": "1.0.0", + "gl-buffer": "2.1.2", + "gl-shader": "4.2.1", + "gl-texture2d": "2.1.0", + "gl-vao": "1.3.0", + "glsl-read-float": "1.1.0", + "glslify": "6.1.0", + "ndarray": "1.0.18" + } + }, + "gl-mat2": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/gl-mat2/-/gl-mat2-1.0.1.tgz", + "integrity": "sha1-FCUFcwpcL+Hp8l2ezj0NbMJxCjA=" + }, + "gl-mat3": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/gl-mat3/-/gl-mat3-1.0.0.tgz", + "integrity": "sha1-iWMyGcpCk3mha5GF2V1BcTRTuRI=" + }, + "gl-mat4": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/gl-mat4/-/gl-mat4-1.1.4.tgz", + "integrity": "sha1-HolbVYkuVqiWhnq9g30483oXgIY=" + }, + "gl-matrix": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/gl-matrix/-/gl-matrix-2.4.0.tgz", + "integrity": "sha1-IImxMwGinuyCLZ2Z3/wfeO6aPFA=" + }, + "gl-matrix-invert": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/gl-matrix-invert/-/gl-matrix-invert-1.0.0.tgz", + "integrity": "sha1-o2173jZUxFkKEn7nxo9uE/6oxj0=", + "requires": { + "gl-mat2": "1.0.1", + "gl-mat3": "1.0.0", + "gl-mat4": "1.1.4" + } + }, + "gl-mesh3d": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/gl-mesh3d/-/gl-mesh3d-1.3.2.tgz", + "integrity": "sha512-sxqKOQA8T2V1CaNefC7X2FTbTPRXWlmzyPd+UOmeUoUYypanFufnDoNLjMEmD5Njq8M5DBg4G7POzf4Jd8272w==", + "requires": { + "barycentric": "1.0.1", + "colormap": "2.3.0", + "gl-buffer": "2.1.2", + "gl-mat4": "1.1.4", + "gl-shader": "4.2.1", + "gl-texture2d": "2.1.0", + "gl-vao": "1.3.0", + "glsl-specular-cook-torrance": "2.0.1", + "glslify": "6.1.0", + "ndarray": "1.0.18", + "normals": "1.1.0", + "polytope-closest-point": "1.0.0", + "simplicial-complex-contour": "1.0.2", + "typedarray-pool": "1.1.0" + } + }, + "gl-plot2d": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/gl-plot2d/-/gl-plot2d-1.3.1.tgz", + "integrity": "sha512-wmZC1ztzkWP03J/1W6yenHwu9c3YzBslIoj/qywkrtO8BXsZeXNAQUidJ2Iq9yvphbOWB3dV0IByNVKKUh3CWw==", + "requires": { + "binary-search-bounds": "2.0.4", + "gl-buffer": "2.1.2", + "gl-select-static": "2.0.2", + "gl-shader": "4.2.1", + "glsl-inverse": "1.0.0", + "glslify": "6.1.0", + "text-cache": "4.1.0" + }, + "dependencies": { + "binary-search-bounds": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/binary-search-bounds/-/binary-search-bounds-2.0.4.tgz", + "integrity": "sha512-2hg5kgdKql5ClF2ErBcSx0U5bnl5hgS4v7wMnLFodyR47yMtj2w+UAZB+0CiqyHct2q543i7Bi4/aMIegorCCg==" + } + } + }, + "gl-plot3d": { + "version": "1.5.5", + "resolved": "https://registry.npmjs.org/gl-plot3d/-/gl-plot3d-1.5.5.tgz", + "integrity": "sha512-pmpIVJ/otokKSdUrpT0a0YjT1B0qdrH3qFO7LcuCSV/8YIo0ybYbXAoYacksgbiJehVVxvnN1ZMCkDIl1uFh4w==", + "requires": { + "3d-view-controls": "2.2.2", + "a-big-triangle": "1.0.3", + "gl-axes3d": "1.2.7", + "gl-fbo": "2.0.5", + "gl-mat4": "1.1.4", + "gl-select-static": "2.0.2", + "gl-shader": "4.2.1", + "gl-spikes3d": "1.0.6", + "glslify": "6.1.0", + "is-mobile": "0.2.2", + "mouse-change": "1.4.0", + "ndarray": "1.0.18" + } + }, + "gl-pointcloud2d": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/gl-pointcloud2d/-/gl-pointcloud2d-1.0.1.tgz", + "integrity": "sha512-bCNaPSrZjBiKRrlbhHdipnmTc5xteubksevbPrmdlk2R6PTwQlQ38TDxuRYan02j0uDtem9wEp8etYYMjZFMhA==", + "requires": { + "gl-buffer": "2.1.2", + "gl-shader": "4.2.1", + "glslify": "6.1.0", + "typedarray-pool": "1.1.0" + } + }, + "gl-quat": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/gl-quat/-/gl-quat-1.0.0.tgz", + "integrity": "sha1-CUXskjOG9FMpvl3DV7HIwtR1hsU=", + "requires": { + "gl-mat3": "1.0.0", + "gl-vec3": "1.0.3", + "gl-vec4": "1.0.1" + } + }, + "gl-scatter3d": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/gl-scatter3d/-/gl-scatter3d-1.0.11.tgz", + "integrity": "sha512-fKpIBm6QHuw3RVzM3fjYgpigQuHIDj5tXbbGx8whWIx7S3ureiZgTxsM2Mtwo+OLsm1lUEryGf2YbFf3NQ9CiQ==", + "requires": { + "gl-buffer": "2.1.2", + "gl-mat4": "1.1.4", + "gl-shader": "4.2.1", + "gl-vao": "1.3.0", + "glslify": "6.1.0", + "typedarray-pool": "1.1.0", + "vectorize-text": "3.0.2" + } + }, + "gl-select-box": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/gl-select-box/-/gl-select-box-1.0.2.tgz", + "integrity": "sha512-QCheTcyHiamTgOQ92P9swHgJoR25T8GGRCANASRtjdMXndlAbQG4qxBP15MRJx7RFWlOVvEeUzCvPn7r116orA==", + "requires": { + "gl-buffer": "2.1.2", + "gl-shader": "4.2.1", + "glslify": "6.1.0" + } + }, + "gl-select-static": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/gl-select-static/-/gl-select-static-2.0.2.tgz", + "integrity": "sha1-8+GQHfAxgdUy55WFMjBnnUr1fuk=", + "requires": { + "bit-twiddle": "1.0.2", + "cwise": "1.0.10", + "gl-fbo": "2.0.5", + "ndarray": "1.0.18", + "typedarray-pool": "1.1.0" + } + }, + "gl-shader": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/gl-shader/-/gl-shader-4.2.1.tgz", + "integrity": "sha1-vJuAjpKTxRtmjojeYVsMETcI3C8=", + "requires": { + "gl-format-compiler-error": "1.0.3", + "weakmap-shim": "1.1.1" + } + }, + "gl-spikes2d": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/gl-spikes2d/-/gl-spikes2d-1.0.1.tgz", + "integrity": "sha1-ys2y09vNICuFNFLoUAqLB3lJzAM=" + }, + "gl-spikes3d": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/gl-spikes3d/-/gl-spikes3d-1.0.6.tgz", + "integrity": "sha512-mXRG+3iCs4bDH7if2aOr1G5UpbNqKxfWpy7GR/afOHDSNsrq2ZjnWAwPmIJG7KdClPNPgiK30cVo7XisLt8PCQ==", + "requires": { + "gl-buffer": "2.1.2", + "gl-shader": "4.2.1", + "gl-vao": "1.3.0", + "glslify": "6.1.0" + } + }, + "gl-state": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/gl-state/-/gl-state-1.0.0.tgz", + "integrity": "sha1-Ji+qdYNbC5xTLBLzitxCXR0wzRc=", + "requires": { + "uniq": "1.0.1" + } + }, + "gl-surface3d": { + "version": "1.3.4", + "resolved": "https://registry.npmjs.org/gl-surface3d/-/gl-surface3d-1.3.4.tgz", + "integrity": "sha512-qQ8DeyPzB6u+EosBTNQ0WVQ63mBKoUtXtWcHhmMTCHG8k9iyHGMdtkXtp63vFaB0C1YIIMeYxtkrkqmqrptHBg==", + "requires": { + "binary-search-bounds": "1.0.0", + "bit-twiddle": "1.0.2", + "colormap": "2.3.0", + "dup": "1.0.0", + "gl-buffer": "2.1.2", + "gl-mat4": "1.1.4", + "gl-shader": "4.2.1", + "gl-texture2d": "2.1.0", + "gl-vao": "1.3.0", + "glsl-specular-beckmann": "1.1.2", + "glslify": "6.1.0", + "ndarray": "1.0.18", + "ndarray-gradient": "1.0.0", + "ndarray-ops": "1.2.2", + "ndarray-pack": "1.2.1", + "ndarray-scratch": "1.2.0", + "surface-nets": "1.0.2", + "typedarray-pool": "1.1.0" + } + }, + "gl-texture2d": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/gl-texture2d/-/gl-texture2d-2.1.0.tgz", + "integrity": "sha1-/2gk5+fDGoum/c2+nlxpXX4hh8c=", + "requires": { + "ndarray": "1.0.18", + "ndarray-ops": "1.2.2", + "typedarray-pool": "1.1.0" + } + }, + "gl-vao": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/gl-vao/-/gl-vao-1.3.0.tgz", + "integrity": "sha1-6ekqqVWIyrnVwvBLaTRAw99pGSM=" + }, + "gl-vec3": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/gl-vec3/-/gl-vec3-1.0.3.tgz", + "integrity": "sha1-EQ/Yl9Byn2OYMHOBVn0JRJQb8is=" + }, + "gl-vec4": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/gl-vec4/-/gl-vec4-1.0.1.tgz", + "integrity": "sha1-l9loeCgbFLUyy84QF4Xf0cs0CWQ=" + }, + "glob": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.2.tgz", + "integrity": "sha512-MJTUg1kjuLeQCJ+ccE4Vpa6kKVXkPYJ2mOCQyUuKLcLQsdrMCpBPUi8qVE6+YuaJkozeA9NusTAw3hLr8Xe5EQ==", + "requires": { + "fs.realpath": "1.0.0", + "inflight": "1.0.6", + "inherits": "2.0.3", + "minimatch": "3.0.4", + "once": "1.4.0", + "path-is-absolute": "1.0.1" + } + }, + "glob-base": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/glob-base/-/glob-base-0.3.0.tgz", + "integrity": "sha1-27Fk9iIbHAscz4Kuoyi0l98Oo8Q=", + "dev": true, + "requires": { + "glob-parent": "2.0.0", + "is-glob": "2.0.1" + } + }, + "glob-parent": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-2.0.0.tgz", + "integrity": "sha1-gTg9ctsFT8zPUzbaqQLxgvbtuyg=", + "dev": true, + "requires": { + "is-glob": "2.0.1" + } + }, + "glsl-inject-defines": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/glsl-inject-defines/-/glsl-inject-defines-1.0.3.tgz", + "integrity": "sha1-3RqswsF/yyvT/DJBHGYz0Ne2D9Q=", + "requires": { + "glsl-token-inject-block": "1.1.0", + "glsl-token-string": "1.0.1", + "glsl-tokenizer": "2.1.2" + } + }, + "glsl-inverse": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/glsl-inverse/-/glsl-inverse-1.0.0.tgz", + "integrity": "sha1-EsCx0GX1WERNHm/q95td34qRiuY=" + }, + "glsl-read-float": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/glsl-read-float/-/glsl-read-float-1.1.0.tgz", + "integrity": "sha1-37CIsBYtz8xW/E7d0vhuGMrDLyY=" + }, + "glsl-resolve": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/glsl-resolve/-/glsl-resolve-0.0.1.tgz", + "integrity": "sha1-iUvvc5ENeSyBtRQxgANdCnivdtM=", + "requires": { + "resolve": "0.6.3", + "xtend": "2.2.0" + }, + "dependencies": { + "resolve": { + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-0.6.3.tgz", + "integrity": "sha1-3ZV5gufnNt699TtYpN2RdUV13UY=" + }, + "xtend": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-2.2.0.tgz", + "integrity": "sha1-7vax8ZjByN6vrYsXZaBNrUoBxak=" + } + } + }, + "glsl-shader-name": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/glsl-shader-name/-/glsl-shader-name-1.0.0.tgz", + "integrity": "sha1-osMLO6c0mb77DMcYTXx3M91LSH0=", + "requires": { + "atob-lite": "1.0.0", + "glsl-tokenizer": "2.1.2" + } + }, + "glsl-specular-beckmann": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/glsl-specular-beckmann/-/glsl-specular-beckmann-1.1.2.tgz", + "integrity": "sha1-/OkFaTPs3yRWJ4N2pU0IKJPndfE=" + }, + "glsl-specular-cook-torrance": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/glsl-specular-cook-torrance/-/glsl-specular-cook-torrance-2.0.1.tgz", + "integrity": "sha1-qJHMBsjHtPRyhwK0gk/ay7ln148=", + "requires": { + "glsl-specular-beckmann": "1.1.2" + } + }, + "glsl-token-assignments": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/glsl-token-assignments/-/glsl-token-assignments-2.0.2.tgz", + "integrity": "sha1-pdgqt4SZwuimuDy2lJXm5mXOAZ8=" + }, + "glsl-token-defines": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/glsl-token-defines/-/glsl-token-defines-1.0.0.tgz", + "integrity": "sha1-y4kqqVmTYjFyhHDU90AySJaX+p0=", + "requires": { + "glsl-tokenizer": "2.1.2" + } + }, + "glsl-token-depth": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/glsl-token-depth/-/glsl-token-depth-1.1.2.tgz", + "integrity": "sha1-I8XjDuK9JViEtKKLyFC495HpXYQ=" + }, + "glsl-token-descope": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/glsl-token-descope/-/glsl-token-descope-1.0.2.tgz", + "integrity": "sha1-D8kKsyYYa4L1l7LnfcniHvzTIHY=", + "requires": { + "glsl-token-assignments": "2.0.2", + "glsl-token-depth": "1.1.2", + "glsl-token-properties": "1.0.1", + "glsl-token-scope": "1.1.2" + } + }, + "glsl-token-inject-block": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/glsl-token-inject-block/-/glsl-token-inject-block-1.1.0.tgz", + "integrity": "sha1-4QFfWYDBCRgkraomJfHf3ovQADQ=" + }, + "glsl-token-properties": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/glsl-token-properties/-/glsl-token-properties-1.0.1.tgz", + "integrity": "sha1-SD3D2Dnw1LXGFx0VkfJJvlPCip4=" + }, + "glsl-token-scope": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/glsl-token-scope/-/glsl-token-scope-1.1.2.tgz", + "integrity": "sha1-oXKOeN8kRE+cuT/RjvD3VQOmQ7E=" + }, + "glsl-token-string": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/glsl-token-string/-/glsl-token-string-1.0.1.tgz", + "integrity": "sha1-WUQdL4V958NEnJRWZgIezjWOSOw=" + }, + "glsl-token-whitespace-trim": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/glsl-token-whitespace-trim/-/glsl-token-whitespace-trim-1.0.0.tgz", + "integrity": "sha1-RtHf6Yx1vX1QTAXX0RsbPpzJOxA=" + }, + "glsl-tokenizer": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/glsl-tokenizer/-/glsl-tokenizer-2.1.2.tgz", + "integrity": "sha1-cgMHUi4DxXrzXABVGVDEpw7y37k=", + "requires": { + "through2": "0.6.5" + } + }, + "glslify": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/glslify/-/glslify-6.1.0.tgz", + "integrity": "sha1-zf/P0qZXFyISjT0TNWwTbebOl0I=", + "requires": { + "bl": "1.2.1", + "concat-stream": "1.6.0", + "duplexify": "3.5.3", + "falafel": "2.1.0", + "from2": "2.3.0", + "glsl-resolve": "0.0.1", + "glsl-token-whitespace-trim": "1.0.0", + "glslify-bundle": "5.0.0", + "glslify-deps": "1.3.0", + "minimist": "1.2.0", + "resolve": "1.4.0", + "stack-trace": "0.0.9", + "static-eval": "1.1.1", + "tape": "4.8.0", + "through2": "2.0.3", + "xtend": "4.0.1" + }, + "dependencies": { + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=" + }, + "readable-stream": { + "version": "2.3.4", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.4.tgz", + "integrity": "sha512-vuYxeWYM+fde14+rajzqgeohAI7YoJcHE7kXDAc4Nk0EbuKnJfqtY9YtRkLo/tqkuF7MsBQRhPnPeyjYITp3ZQ==", + "requires": { + "core-util-is": "1.0.2", + "inherits": "2.0.3", + "isarray": "1.0.0", + "process-nextick-args": "2.0.0", + "safe-buffer": "5.1.1", + "string_decoder": "1.0.3", + "util-deprecate": "1.0.2" + } + }, + "string_decoder": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.0.3.tgz", + "integrity": "sha512-4AH6Z5fzNNBcH+6XDMfA/BTt87skxqJlO0lAh3Dker5zThcAxG6mKz+iGu308UKoPPQ8Dcqx/4JhujzltRa+hQ==", + "requires": { + "safe-buffer": "5.1.1" + } + }, + "through2": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.3.tgz", + "integrity": "sha1-AARWmzfHx0ujnEPzzteNGtlBQL4=", + "requires": { + "readable-stream": "2.3.4", + "xtend": "4.0.1" + } + } + } + }, + "glslify-bundle": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/glslify-bundle/-/glslify-bundle-5.0.0.tgz", + "integrity": "sha1-AlKtoe+d8wtmAAbguyH9EwtIbkI=", + "requires": { + "glsl-inject-defines": "1.0.3", + "glsl-token-defines": "1.0.0", + "glsl-token-depth": "1.1.2", + "glsl-token-descope": "1.0.2", + "glsl-token-scope": "1.1.2", + "glsl-token-string": "1.0.1", + "glsl-token-whitespace-trim": "1.0.0", + "glsl-tokenizer": "2.1.2", + "murmurhash-js": "1.0.0", + "shallow-copy": "0.0.1" + } + }, + "glslify-deps": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/glslify-deps/-/glslify-deps-1.3.0.tgz", + "integrity": "sha1-CyI0yOqePT/X9rPLfwOuWea1Glk=", + "requires": { + "events": "1.1.1", + "findup": "0.1.5", + "glsl-resolve": "0.0.1", + "glsl-tokenizer": "2.1.2", + "graceful-fs": "4.1.11", + "inherits": "2.0.3", + "map-limit": "0.0.1", + "resolve": "1.4.0" + } + }, + "graceful-fs": { + "version": "4.1.11", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.11.tgz", + "integrity": "sha1-Dovf5NHduIVNZOBOp8AOKgJuVlg=" + }, + "grid-index": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/grid-index/-/grid-index-1.0.0.tgz", + "integrity": "sha1-rSxdVM5bNUN/r/HXCprrPR0mERA=" + }, + "har-schema": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/har-schema/-/har-schema-2.0.0.tgz", + "integrity": "sha1-qUwiJOvKwEeCoNkDVSHyRzW37JI=" + }, + "har-validator": { + "version": "5.0.3", + "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-5.0.3.tgz", + "integrity": "sha1-ukAsJmGU8VlW7xXg/PJCmT9qff0=", + "requires": { + "ajv": "5.1.6", + "har-schema": "2.0.0" + } + }, + "has": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/has/-/has-1.0.1.tgz", + "integrity": "sha1-hGFzP1OLCDfJNh45qauelwTcLyg=", + "requires": { + "function-bind": "1.1.1" + } + }, + "has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=" + }, + "has-hover": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/has-hover/-/has-hover-1.0.1.tgz", + "integrity": "sha1-PZdDeusZnGK4rAisvcU9O8UsF/c=", + "requires": { + "is-browser": "2.0.1" + } + }, + "has-passive-events": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-passive-events/-/has-passive-events-1.0.0.tgz", + "integrity": "sha512-2vSj6IeIsgvsRMyeQ0JaCX5Q3lX4zMn5HpoVc7MEhQ6pv8Iq9rsXjsp+E5ZwaT7T0xhMT0KmU8gtt1EFVdbJiw==", + "requires": { + "is-browser": "2.0.1" + } + }, + "hash-base": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/hash-base/-/hash-base-2.0.2.tgz", + "integrity": "sha1-ZuodhW206KVHDK32/OI65SRO8uE=", + "dev": true, + "requires": { + "inherits": "2.0.3" + } + }, + "hash.js": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/hash.js/-/hash.js-1.1.3.tgz", + "integrity": "sha512-/UETyP0W22QILqS+6HowevwhEFJ3MBJnwTf75Qob9Wz9t0DPuisL8kW8YZMK62dHAKE1c1p+gY1TtOLY+USEHA==", + "dev": true, + "requires": { + "inherits": "2.0.3", + "minimalistic-assert": "1.0.0" + } + }, + "hawk": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/hawk/-/hawk-6.0.2.tgz", + "integrity": "sha512-miowhl2+U7Qle4vdLqDdPt9m09K6yZhkLDTWGoUiUzrQCn+mHHSmfJgAyGaLRZbPmTqfFFjRV1QWCW0VWUJBbQ==", + "requires": { + "boom": "4.3.1", + "cryptiles": "3.1.2", + "hoek": "4.2.1", + "sntp": "2.1.0" + } + }, + "hmac-drbg": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/hmac-drbg/-/hmac-drbg-1.0.1.tgz", + "integrity": "sha1-0nRXAQJabHdabFRXk+1QL8DGSaE=", + "dev": true, + "requires": { + "hash.js": "1.1.3", + "minimalistic-assert": "1.0.0", + "minimalistic-crypto-utils": "1.0.1" + } + }, + "hoek": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/hoek/-/hoek-4.2.1.tgz", + "integrity": "sha512-QLg82fGkfnJ/4iy1xZ81/9SIJiq1NGFUMGs6ParyjBZr6jW2Ufj/snDqTHixNlHdPNwN2RLVD0Pi3igeK9+JfA==" + }, + "hosted-git-info": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.5.0.tgz", + "integrity": "sha512-pNgbURSuab90KbTqvRPsseaTxOJCZBD0a7t+haSN33piP9cCM4l0CqdzAif2hUqm716UovKB2ROmiabGAKVXyg==", + "dev": true + }, + "http-signature": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.2.0.tgz", + "integrity": "sha1-muzZJRFHcvPZW2WmCruPfBj7rOE=", + "requires": { + "assert-plus": "1.0.0", + "jsprim": "1.4.1", + "sshpk": "1.13.1" + } + }, + "https-browserify": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/https-browserify/-/https-browserify-1.0.0.tgz", + "integrity": "sha1-7AbBDgo0wPL68Zn3/X/Hj//QPHM=", + "dev": true + }, + "husl": { + "version": "5.0.3", + "resolved": "https://registry.npmjs.org/husl/-/husl-5.0.3.tgz", + "integrity": "sha1-7icqr/G+vkDfNYjtAHtw3n5nl4g=" + }, + "iconv-lite": { + "version": "0.4.19", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.19.tgz", + "integrity": "sha512-oTZqweIP51xaGPI4uPa56/Pri/480R+mo7SeU+YETByQNhDG55ycFyNLIgta9vXhILrxXDmF7ZGhqZIcuN0gJQ==" + }, + "ieee754": { + "version": "1.1.8", + "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.1.8.tgz", + "integrity": "sha1-vjPUCsEO8ZJnAfbwii2G+/0a0+Q=" + }, + "ify-loader": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/ify-loader/-/ify-loader-1.1.0.tgz", + "integrity": "sha512-EiyC45FRIs+z4g98+jBzuYCfoM6TKG9p7Ek5YZUeM7rucNucaMZIseRj/5Q3I4ypkZXyC2wnU1RcYrVmshe2xw==", + "dev": true, + "requires": { + "bl": "1.2.1", + "findup": "0.1.5", + "from2-array": "0.0.4", + "map-limit": "0.0.1", + "multipipe": "0.3.1", + "read-package-json": "2.0.12", + "resolve": "1.4.0" + } + }, + "incremental-convex-hull": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/incremental-convex-hull/-/incremental-convex-hull-1.0.1.tgz", + "integrity": "sha1-UUKMFMudmmFEv+abKFH7N3M0vh4=", + "requires": { + "robust-orientation": "1.1.3", + "simplicial-complex": "1.0.0" + } + }, + "indexof": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/indexof/-/indexof-0.0.1.tgz", + "integrity": "sha1-gtwzbSMrkGIXnQWrMpOmYFn9Q10=", + "dev": true + }, + "inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", + "requires": { + "once": "1.4.0", + "wrappy": "1.0.2" + } + }, + "inherits": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", + "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=" + }, + "interpret": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/interpret/-/interpret-1.1.0.tgz", + "integrity": "sha1-ftGxQQxqDg94z5XTuEQMY/eLhhQ=", + "dev": true + }, + "interval-tree-1d": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/interval-tree-1d/-/interval-tree-1d-1.0.3.tgz", + "integrity": "sha1-j9veArayx9verWNry+2OCHENhcE=", + "requires": { + "binary-search-bounds": "1.0.0" + } + }, + "invert-kv": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/invert-kv/-/invert-kv-1.0.0.tgz", + "integrity": "sha1-EEqOSqym09jNFXqO+L+rLXo//bY=", + "dev": true + }, + "invert-permutation": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/invert-permutation/-/invert-permutation-1.0.0.tgz", + "integrity": "sha1-oKeAQurbNrwXVR54fv0UOa3VSTM=" + }, + "iota-array": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/iota-array/-/iota-array-1.0.0.tgz", + "integrity": "sha1-ge9X/l0FgUzVjCSDYyqZwwoOgIc=" + }, + "is-arrayish": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", + "integrity": "sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0=", + "dev": true + }, + "is-binary-path": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-1.0.1.tgz", + "integrity": "sha1-dfFmQrSA8YenEcgUFh/TpKdlWJg=", + "dev": true, + "requires": { + "binary-extensions": "1.11.0" + } + }, + "is-browser": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-browser/-/is-browser-2.0.1.tgz", + "integrity": "sha1-i/C695mpxi/Z3lvO5M8zl8PnUpo=" + }, + "is-buffer": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", + "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==" + }, + "is-builtin-module": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-builtin-module/-/is-builtin-module-1.0.0.tgz", + "integrity": "sha1-VAVy0096wxGfj3bDDLwbHgN6/74=", + "dev": true, + "requires": { + "builtin-modules": "1.1.1" + } + }, + "is-callable": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.1.3.tgz", + "integrity": "sha1-hut1OSgF3cM69xySoO7fdO52BLI=" + }, + "is-date-object": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.1.tgz", + "integrity": "sha1-mqIOtq7rv/d/vTPnTKAbM1gdOhY=" + }, + "is-dotfile": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/is-dotfile/-/is-dotfile-1.0.3.tgz", + "integrity": "sha1-pqLzL/0t+wT1yiXs0Pa4PPeYoeE=", + "dev": true + }, + "is-equal-shallow": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/is-equal-shallow/-/is-equal-shallow-0.1.3.tgz", + "integrity": "sha1-IjgJj8Ih3gvPpdnqxMRdY4qhxTQ=", + "dev": true, + "requires": { + "is-primitive": "2.0.0" + } + }, + "is-extendable": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz", + "integrity": "sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik=", + "dev": true + }, + "is-extglob": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-1.0.0.tgz", + "integrity": "sha1-rEaBd8SUNAWgkvyPKXYMb/xiBsA=", + "dev": true + }, + "is-fullwidth-code-point": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", + "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", + "dev": true, + "requires": { + "number-is-nan": "1.0.1" + } + }, + "is-function": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-function/-/is-function-1.0.1.tgz", + "integrity": "sha1-Es+5i2W1fdPRk6MSH19uL0N2ArU=" + }, + "is-glob": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-2.0.1.tgz", + "integrity": "sha1-0Jb5JqPe1WAPP9/ZEZjLCIjC2GM=", + "dev": true, + "requires": { + "is-extglob": "1.0.0" + } + }, + "is-iexplorer": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-iexplorer/-/is-iexplorer-1.0.0.tgz", + "integrity": "sha1-HXK8ZtP+Iur2Fw3ajPEJQySM/HY=" + }, + "is-mobile": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/is-mobile/-/is-mobile-0.2.2.tgz", + "integrity": "sha1-Di4AbZntLCFVt2HfgPKjYZrirZ8=" + }, + "is-number": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-2.1.0.tgz", + "integrity": "sha1-Afy7s5NGOlSPL0ZszhbezknbkI8=", + "dev": true, + "requires": { + "kind-of": "3.2.2" + } + }, + "is-plain-obj": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-1.1.0.tgz", + "integrity": "sha1-caUMhCnfync8kqOQpKA7OfzVHT4=" + }, + "is-posix-bracket": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/is-posix-bracket/-/is-posix-bracket-0.1.1.tgz", + "integrity": "sha1-MzTceXdDaOkvAW5vvAqI9c1ua8Q=", + "dev": true + }, + "is-primitive": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-primitive/-/is-primitive-2.0.0.tgz", + "integrity": "sha1-IHurkWOEmcB7Kt8kCkGochADRXU=", + "dev": true + }, + "is-regex": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.0.4.tgz", + "integrity": "sha1-VRdIm1RwkbCTDglWVM7SXul+lJE=", + "requires": { + "has": "1.0.1" + } + }, + "is-stream": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz", + "integrity": "sha1-EtSj3U5o4Lec6428hBc66A2RykQ=" + }, + "is-svg-path": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-svg-path/-/is-svg-path-1.0.2.tgz", + "integrity": "sha1-d6tZDBKz0gNI5cehPQBAyHeE3aA=" + }, + "is-symbol": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.1.tgz", + "integrity": "sha1-PMWfAAJRlLarLjjbrmaJJWtmBXI=" + }, + "is-typedarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", + "integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=" + }, + "isarray": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", + "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=" + }, + "isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=", + "dev": true + }, + "isobject": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-2.1.0.tgz", + "integrity": "sha1-8GVWEJaj8dou9GJy+BXIQNh+DIk=", + "dev": true, + "requires": { + "isarray": "1.0.0" + }, + "dependencies": { + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", + "dev": true + } + } + }, + "isstream": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz", + "integrity": "sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo=" + }, + "jquery": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/jquery/-/jquery-3.3.1.tgz", + "integrity": "sha512-Ubldcmxp5np52/ENotGxlLe6aGMvmF4R8S6tZjsP6Knsaxd/xp3Zrh50cG93lR6nPXyUFwzN3ZSOQI0wRJNdGg==" + }, + "jsbn": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz", + "integrity": "sha1-peZUwuWi3rXyAdls77yoDA7y9RM=", + "optional": true + }, + "json-loader": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/json-loader/-/json-loader-0.5.7.tgz", + "integrity": "sha512-QLPs8Dj7lnf3e3QYS1zkCo+4ZwqOiF9d/nZnYozTISxXWCfNs9yuky5rJw4/W34s7POaNlbZmQGaB5NiXCbP4w==", + "dev": true + }, + "json-parse-better-errors": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json-parse-better-errors/-/json-parse-better-errors-1.0.1.tgz", + "integrity": "sha512-xyQpxeWWMKyJps9CuGJYeng6ssI5bpqS9ltQpdVQ90t4ql6NdnxFKh95JcRt2cun/DjMVNrdjniLPuMA69xmCw==", + "dev": true + }, + "json-parser": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/json-parser/-/json-parser-1.1.5.tgz", + "integrity": "sha1-5i7FJh0aal/CDoEqMgdAxtkAVnc=", + "requires": { + "esprima": "2.7.3" + } + }, + "json-schema": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.2.3.tgz", + "integrity": "sha1-tIDIkuWaLwWVTOcnvT8qTogvnhM=" + }, + "json-schema-traverse": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.3.1.tgz", + "integrity": "sha1-NJptRMU6Ud6JtAgFxdXlm0F9M0A=" + }, + "json-stable-stringify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json-stable-stringify/-/json-stable-stringify-1.0.1.tgz", + "integrity": "sha1-mnWdOcXy/1A/1TAGRu1EX4jE+a8=", + "requires": { + "jsonify": "0.0.0" + } + }, + "json-stringify-safe": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", + "integrity": "sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus=" + }, + "json5": { + "version": "0.5.1", + "resolved": "https://registry.npmjs.org/json5/-/json5-0.5.1.tgz", + "integrity": "sha1-Hq3nrMASA0rYTiOWdn6tn6VJWCE=", + "dev": true + }, + "jsonify": { + "version": "0.0.0", + "resolved": "https://registry.npmjs.org/jsonify/-/jsonify-0.0.0.tgz", + "integrity": "sha1-LHS27kHZPKUbe1qu6PUDYx0lKnM=" + }, + "jsonlint-lines-primitives": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/jsonlint-lines-primitives/-/jsonlint-lines-primitives-1.6.0.tgz", + "integrity": "sha1-u4n2DIubYS/ZE92qI2ZJuEDYZhE=", + "requires": { + "JSV": "4.0.2", + "nomnom": "2.0.0" + } + }, + "jsprim": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.1.tgz", + "integrity": "sha1-MT5mvB5cwG5Di8G3SZwuXFastqI=", + "requires": { + "assert-plus": "1.0.0", + "extsprintf": "1.3.0", + "json-schema": "0.2.3", + "verror": "1.10.0" + } + }, + "kdbush": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/kdbush/-/kdbush-1.0.1.tgz", + "integrity": "sha1-PL0D6d6tnA9vZszblkUOXOzGQOA=" + }, + "kdgrass": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/kdgrass/-/kdgrass-1.0.1.tgz", + "integrity": "sha512-2sfleTaNfu4AQdL9Om42i7D+NnnIwTd+MJYkbCdyv1DvFtHkLLBc8ZwrM2nD1zp4AuSBzCfoDSWcba4c7iHodQ==" + }, + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "requires": { + "is-buffer": "1.1.6" + } + }, + "lazy-cache": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/lazy-cache/-/lazy-cache-1.0.4.tgz", + "integrity": "sha1-odePw6UEdMuAhF07O24dpJpEbo4=" + }, + "lcid": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/lcid/-/lcid-1.0.0.tgz", + "integrity": "sha1-MIrMr6C8SDo4Z7S28rlQYlHRuDU=", + "dev": true, + "requires": { + "invert-kv": "1.0.0" + } + }, + "lerp": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/lerp/-/lerp-1.0.3.tgz", + "integrity": "sha1-oYyJaPkXiW3hXM/MKNVaa3Med24=" + }, + "levn": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/levn/-/levn-0.3.0.tgz", + "integrity": "sha1-OwmSTt+fCDwEkP3UwLxEIeBHZO4=", + "requires": { + "prelude-ls": "1.1.2", + "type-check": "0.3.2" + } + }, + "load-json-file": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-2.0.0.tgz", + "integrity": "sha1-eUfkIUmvgNaWy/eXvKq8/h/inKg=", + "dev": true, + "requires": { + "graceful-fs": "4.1.11", + "parse-json": "2.2.0", + "pify": "2.3.0", + "strip-bom": "3.0.0" + } + }, + "loader-runner": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/loader-runner/-/loader-runner-2.3.0.tgz", + "integrity": "sha1-9IKuqC1UPgeSFwDVpG7yb9rGuKI=", + "dev": true + }, + "loader-utils": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-1.1.0.tgz", + "integrity": "sha1-yYrvSIvM7aL/teLeZG1qdUQp9c0=", + "dev": true, + "requires": { + "big.js": "3.2.0", + "emojis-list": "2.1.0", + "json5": "0.5.1" + } + }, + "locate-path": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-2.0.0.tgz", + "integrity": "sha1-K1aLJl7slExtnA3pw9u7ygNUzY4=", + "dev": true, + "requires": { + "p-locate": "2.0.0", + "path-exists": "3.0.0" + } + }, + "lodash": { + "version": "4.17.5", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.5.tgz", + "integrity": "sha512-svL3uiZf1RwhH+cWrfZn3A4+U58wbP0tGVTLQPbjplZxZ8ROD9VLuNgsRniTlLe7OlSqR79RUehXgpBW/s0IQw==" + }, + "lodash._baseisequal": { + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/lodash._baseisequal/-/lodash._baseisequal-3.0.7.tgz", + "integrity": "sha1-2AJfdjOdKTQnZ9zIh85cuVpbUfE=", + "requires": { + "lodash.isarray": "3.0.4", + "lodash.istypedarray": "3.0.6", + "lodash.keys": "3.1.2" + } + }, + "lodash._bindcallback": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/lodash._bindcallback/-/lodash._bindcallback-3.0.1.tgz", + "integrity": "sha1-5THCdkTPi1epnhftlbNcdIeJOS4=" + }, + "lodash._getnative": { + "version": "3.9.1", + "resolved": "https://registry.npmjs.org/lodash._getnative/-/lodash._getnative-3.9.1.tgz", + "integrity": "sha1-VwvH3t5G1hzc3mh9ZdPuy6o6r/U=" + }, + "lodash.isarguments": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/lodash.isarguments/-/lodash.isarguments-3.1.0.tgz", + "integrity": "sha1-L1c9hcaiQon/AGY7SRwdM4/zRYo=" + }, + "lodash.isarray": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/lodash.isarray/-/lodash.isarray-3.0.4.tgz", + "integrity": "sha1-eeTriMNqgSKvhvhEqpvNhRtfu1U=" + }, + "lodash.isequal": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/lodash.isequal/-/lodash.isequal-3.0.4.tgz", + "integrity": "sha1-HDXrO27wzR/1F0Pj6jz3/f/ay2Q=", + "requires": { + "lodash._baseisequal": "3.0.7", + "lodash._bindcallback": "3.0.1" + } + }, + "lodash.istypedarray": { + "version": "3.0.6", + "resolved": "https://registry.npmjs.org/lodash.istypedarray/-/lodash.istypedarray-3.0.6.tgz", + "integrity": "sha1-yaR3SYYHUB2OhJTSg7h8OSgc72I=" + }, + "lodash.keys": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/lodash.keys/-/lodash.keys-3.1.2.tgz", + "integrity": "sha1-TbwEcrFWvlCgsoaFXRvQsMZWCYo=", + "requires": { + "lodash._getnative": "3.9.1", + "lodash.isarguments": "3.1.0", + "lodash.isarray": "3.0.4" + } + }, + "longest": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/longest/-/longest-1.0.1.tgz", + "integrity": "sha1-MKCy2jj3N3DoKUoNIuZiXtd9AJc=" + }, + "lru-cache": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-4.1.1.tgz", + "integrity": "sha512-q4spe4KTfsAS1SUHLO0wz8Qiyf1+vMIAgpRYioFYDMNqKfHQbg+AVDH3i4fvpl71/P1L0dBl+fQi+P37UYf0ew==", + "dev": true, + "requires": { + "pseudomap": "1.0.2", + "yallist": "2.1.2" + } + }, + "magic-string": { + "version": "0.22.4", + "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.22.4.tgz", + "integrity": "sha512-kxBL06p6iO2qPBHsqGK2b3cRwiRGpnmSuVWNhwHcMX7qJOUr1HvricYP1LZOCdkQBUp0jiWg2d6WJwR3vYgByw==", + "requires": { + "vlq": "0.2.3" + } + }, + "map-limit": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/map-limit/-/map-limit-0.0.1.tgz", + "integrity": "sha1-63lhAxwPDo0AG/LVb6toXViCLzg=", + "requires": { + "once": "1.3.3" + }, + "dependencies": { + "once": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/once/-/once-1.3.3.tgz", + "integrity": "sha1-suJhVXzkwxTsgwTz+oJmPkKXyiA=", + "requires": { + "wrappy": "1.0.2" + } + } + } + }, + "mapbox-gl": { + "version": "0.22.1", + "resolved": "https://registry.npmjs.org/mapbox-gl/-/mapbox-gl-0.22.1.tgz", + "integrity": "sha1-kqllVH1MLyTCLLxIfu2khpTLYno=", + "requires": { + "csscolorparser": "1.0.3", + "earcut": "2.1.3", + "feature-filter": "2.2.0", + "geojson-rewind": "0.1.0", + "geojson-vt": "2.4.0", + "gl-matrix": "2.4.0", + "grid-index": "1.0.0", + "mapbox-gl-function": "1.3.0", + "mapbox-gl-shaders": "github:mapbox/mapbox-gl-shaders#de2ab007455aa2587c552694c68583f94c9f2747", + "mapbox-gl-style-spec": "github:mapbox/mapbox-gl-style-spec#83b1a3e5837d785af582efd5ed1a212f2df6a4ae", + "mapbox-gl-supported": "1.2.0", + "pbf": "1.3.7", + "pngjs": "2.3.1", + "point-geometry": "0.0.0", + "quickselect": "1.0.1", + "request": "2.83.0", + "resolve-url": "0.2.1", + "shelf-pack": "1.1.0", + "supercluster": "2.3.0", + "unassertify": "2.1.0", + "unitbezier": "0.0.0", + "vector-tile": "1.3.0", + "vt-pbf": "2.1.4", + "webworkify": "1.5.0", + "whoots-js": "2.1.0" + } + }, + "mapbox-gl-function": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/mapbox-gl-function/-/mapbox-gl-function-1.3.0.tgz", + "integrity": "sha1-zuPZV1DBidReg6tBoKV/wqilCbw=" + }, + "mapbox-gl-shaders": { + "version": "github:mapbox/mapbox-gl-shaders#de2ab007455aa2587c552694c68583f94c9f2747", + "requires": { + "brfs": "1.4.4" + } + }, + "mapbox-gl-style-spec": { + "version": "github:mapbox/mapbox-gl-style-spec#83b1a3e5837d785af582efd5ed1a212f2df6a4ae", + "requires": { + "csscolorparser": "1.0.3", + "jsonlint-lines-primitives": "1.6.0", + "lodash.isequal": "3.0.4", + "minimist": "0.0.8", + "rw": "0.1.4", + "sort-object": "0.3.2" + }, + "dependencies": { + "minimist": { + "version": "0.0.8", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz", + "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=" + } + } + }, + "mapbox-gl-supported": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/mapbox-gl-supported/-/mapbox-gl-supported-1.2.0.tgz", + "integrity": "sha1-y9NN+JQgbK3amjPI2aRgnya7GYk=" + }, + "marching-simplex-table": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/marching-simplex-table/-/marching-simplex-table-1.0.0.tgz", + "integrity": "sha1-vBYlbg+Pm1WKqbKHL4gy2UM/Uuo=", + "requires": { + "convex-hull": "1.0.3" + } + }, + "mat4-decompose": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/mat4-decompose/-/mat4-decompose-1.0.4.tgz", + "integrity": "sha1-ZetP451wh496RE60Yk1S9+frL68=", + "requires": { + "gl-mat4": "1.1.4", + "gl-vec3": "1.0.3" + } + }, + "mat4-interpolate": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/mat4-interpolate/-/mat4-interpolate-1.0.4.tgz", + "integrity": "sha1-Vf/p6zw1KV4sDVqfdyXZBoqJ/3Q=", + "requires": { + "gl-mat4": "1.1.4", + "gl-vec3": "1.0.3", + "mat4-decompose": "1.0.4", + "mat4-recompose": "1.0.4", + "quat-slerp": "1.0.1" + } + }, + "mat4-recompose": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/mat4-recompose/-/mat4-recompose-1.0.4.tgz", + "integrity": "sha1-OVPCMP8kc9x3LuAUpSySXPgbDk0=", + "requires": { + "gl-mat4": "1.1.4" + } + }, + "matrix-camera-controller": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/matrix-camera-controller/-/matrix-camera-controller-2.1.3.tgz", + "integrity": "sha1-NeUmDMHNVQliunmfLY1OlLGjk3A=", + "requires": { + "binary-search-bounds": "1.0.0", + "gl-mat4": "1.1.4", + "gl-vec3": "1.0.3", + "mat4-interpolate": "1.0.4" + } + }, + "md5.js": { + "version": "1.3.4", + "resolved": "https://registry.npmjs.org/md5.js/-/md5.js-1.3.4.tgz", + "integrity": "sha1-6b296UogpawYsENA/Fdk1bCdkB0=", + "dev": true, + "requires": { + "hash-base": "3.0.4", + "inherits": "2.0.3" + }, + "dependencies": { + "hash-base": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/hash-base/-/hash-base-3.0.4.tgz", + "integrity": "sha1-X8hoaEfs1zSZQDMZprCj8/auSRg=", + "dev": true, + "requires": { + "inherits": "2.0.3", + "safe-buffer": "5.1.1" + } + } + } + }, + "mem": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/mem/-/mem-1.1.0.tgz", + "integrity": "sha1-Xt1StIXKHZAP5kiVUFOZoN+kX3Y=", + "dev": true, + "requires": { + "mimic-fn": "1.2.0" + } + }, + "memory-fs": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/memory-fs/-/memory-fs-0.4.1.tgz", + "integrity": "sha1-OpoguEYlI+RHz7x+i7gO1me/xVI=", + "dev": true, + "requires": { + "errno": "0.1.7", + "readable-stream": "2.3.4" + }, + "dependencies": { + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", + "dev": true + }, + "readable-stream": { + "version": "2.3.4", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.4.tgz", + "integrity": "sha512-vuYxeWYM+fde14+rajzqgeohAI7YoJcHE7kXDAc4Nk0EbuKnJfqtY9YtRkLo/tqkuF7MsBQRhPnPeyjYITp3ZQ==", + "dev": true, + "requires": { + "core-util-is": "1.0.2", + "inherits": "2.0.3", + "isarray": "1.0.0", + "process-nextick-args": "2.0.0", + "safe-buffer": "5.1.1", + "string_decoder": "1.0.3", + "util-deprecate": "1.0.2" + } + }, + "string_decoder": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.0.3.tgz", + "integrity": "sha512-4AH6Z5fzNNBcH+6XDMfA/BTt87skxqJlO0lAh3Dker5zThcAxG6mKz+iGu308UKoPPQ8Dcqx/4JhujzltRa+hQ==", + "dev": true, + "requires": { + "safe-buffer": "5.1.1" + } + } + } + }, + "micromatch": { + "version": "2.3.11", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-2.3.11.tgz", + "integrity": "sha1-hmd8l9FyCzY0MdBNDRUpO9OMFWU=", + "dev": true, + "requires": { + "arr-diff": "2.0.0", + "array-unique": "0.2.1", + "braces": "1.8.5", + "expand-brackets": "0.1.5", + "extglob": "0.3.2", + "filename-regex": "2.0.1", + "is-extglob": "1.0.0", + "is-glob": "2.0.1", + "kind-of": "3.2.2", + "normalize-path": "2.1.1", + "object.omit": "2.0.1", + "parse-glob": "3.0.4", + "regex-cache": "0.4.4" + } + }, + "miller-rabin": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/miller-rabin/-/miller-rabin-4.0.1.tgz", + "integrity": "sha512-115fLhvZVqWwHPbClyntxEVfVDfl9DLLTuJvq3g2O/Oxi8AiNouAHvDSzHS0viUJc+V5vm3eq91Xwqn9dp4jRA==", + "dev": true, + "requires": { + "bn.js": "4.11.8", + "brorand": "1.1.0" + } + }, + "mime-db": { + "version": "1.33.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.33.0.tgz", + "integrity": "sha512-BHJ/EKruNIqJf/QahvxwQZXKygOQ256myeN/Ew+THcAa5q+PjyTTMMeNQC4DZw5AwfvelsUrA6B67NKMqXDbzQ==" + }, + "mime-types": { + "version": "2.1.18", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.18.tgz", + "integrity": "sha512-lc/aahn+t4/SWV/qcmumYjymLsWfN3ELhpmVuUFjgsORruuZPVSwAQryq+HHGvO/SI2KVX26bx+En+zhM8g8hQ==", + "requires": { + "mime-db": "1.33.0" + } + }, + "mimic-fn": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-1.2.0.tgz", + "integrity": "sha512-jf84uxzwiuiIVKiOLpfYk7N46TSy8ubTonmneY9vrpHNAnp0QBt2BxWV9dO3/j+BoVAb+a5G6YDPW3M5HOdMWQ==", + "dev": true + }, + "minimalistic-assert": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/minimalistic-assert/-/minimalistic-assert-1.0.0.tgz", + "integrity": "sha1-cCvi3aazf0g2vLP121ZkG2Sh09M=", + "dev": true + }, + "minimalistic-crypto-utils": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/minimalistic-crypto-utils/-/minimalistic-crypto-utils-1.0.1.tgz", + "integrity": "sha1-9sAMHAsIIkblxNmd+4x8CDsrWCo=", + "dev": true + }, + "minimatch": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", + "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", + "requires": { + "brace-expansion": "1.1.11" + } + }, + "minimist": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", + "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=" + }, + "mkdirp": { + "version": "0.5.1", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz", + "integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=", + "dev": true, + "requires": { + "minimist": "0.0.8" + }, + "dependencies": { + "minimist": { + "version": "0.0.8", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz", + "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=", + "dev": true + } + } + }, + "moment": { + "version": "2.17.1", + "resolved": "https://registry.npmjs.org/moment/-/moment-2.17.1.tgz", + "integrity": "sha1-/tlQYGPzaxDwZsi1mhRNf66+HYI=" + }, + "monotone-convex-hull-2d": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/monotone-convex-hull-2d/-/monotone-convex-hull-2d-1.0.1.tgz", + "integrity": "sha1-R/Xa6t88Sv03dkuqGqh4ekDu4Iw=", + "requires": { + "robust-orientation": "1.1.3" + } + }, + "mouse-change": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/mouse-change/-/mouse-change-1.4.0.tgz", + "integrity": "sha1-wrd+W/o0pDzhRFyBV6Tk3JiVwU8=", + "requires": { + "mouse-event": "1.0.5" + } + }, + "mouse-event": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/mouse-event/-/mouse-event-1.0.5.tgz", + "integrity": "sha1-s3ie23EJmX1aky0dAdqhVDpQFzI=" + }, + "mouse-event-offset": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/mouse-event-offset/-/mouse-event-offset-3.0.2.tgz", + "integrity": "sha1-39hqbiSMa6jK1TuQXVA3ogY+mYQ=" + }, + "mouse-wheel": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/mouse-wheel/-/mouse-wheel-1.2.0.tgz", + "integrity": "sha1-bSkDseqPtI5h8bU7kDZ3PwQs21w=", + "requires": { + "right-now": "1.0.0", + "signum": "1.0.0", + "to-px": "1.0.1" + }, + "dependencies": { + "signum": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/signum/-/signum-1.0.0.tgz", + "integrity": "sha1-dKfSvyogtA66FqkrFSEk8dVZ+nc=" + } + } + }, + "multi-stage-sourcemap": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/multi-stage-sourcemap/-/multi-stage-sourcemap-0.2.1.tgz", + "integrity": "sha1-sJ/IWG6qF/gdV1xK0C4Pej9rEQU=", + "requires": { + "source-map": "0.1.43" + }, + "dependencies": { + "source-map": { + "version": "0.1.43", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.1.43.tgz", + "integrity": "sha1-wkvBRspRfBRx9drL4lcbK3+eM0Y=", + "requires": { + "amdefine": "1.0.1" + } + } + } + }, + "multipipe": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/multipipe/-/multipipe-0.3.1.tgz", + "integrity": "sha1-kmJVJXYboE/qoJYFtjgrziyR8R8=", + "dev": true, + "requires": { + "duplexer2": "0.1.4" + }, + "dependencies": { + "duplexer2": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/duplexer2/-/duplexer2-0.1.4.tgz", + "integrity": "sha1-ixLauHjA1p4+eJEFFmKjL8a93ME=", + "dev": true, + "requires": { + "readable-stream": "2.3.4" + } + }, + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", + "dev": true + }, + "readable-stream": { + "version": "2.3.4", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.4.tgz", + "integrity": "sha512-vuYxeWYM+fde14+rajzqgeohAI7YoJcHE7kXDAc4Nk0EbuKnJfqtY9YtRkLo/tqkuF7MsBQRhPnPeyjYITp3ZQ==", + "dev": true, + "requires": { + "core-util-is": "1.0.2", + "inherits": "2.0.3", + "isarray": "1.0.0", + "process-nextick-args": "2.0.0", + "safe-buffer": "5.1.1", + "string_decoder": "1.0.3", + "util-deprecate": "1.0.2" + } + }, + "string_decoder": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.0.3.tgz", + "integrity": "sha512-4AH6Z5fzNNBcH+6XDMfA/BTt87skxqJlO0lAh3Dker5zThcAxG6mKz+iGu308UKoPPQ8Dcqx/4JhujzltRa+hQ==", + "dev": true, + "requires": { + "safe-buffer": "5.1.1" + } + } + } + }, + "mumath": { + "version": "3.3.4", + "resolved": "https://registry.npmjs.org/mumath/-/mumath-3.3.4.tgz", + "integrity": "sha1-SNSg8P2MrU57Mglu6JsWGmPTC78=", + "requires": { + "almost-equal": "1.1.0" + } + }, + "murmurhash-js": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/murmurhash-js/-/murmurhash-js-1.0.0.tgz", + "integrity": "sha1-sGJ44h/Gw3+lMTcysEEry2rhX1E=" + }, + "nan": { + "version": "2.8.0", + "resolved": "https://registry.npmjs.org/nan/-/nan-2.8.0.tgz", + "integrity": "sha1-7XFfP+neArV6XmJS2QqWZ14fCFo=", + "dev": true, + "optional": true + }, + "ndarray": { + "version": "1.0.18", + "resolved": "https://registry.npmjs.org/ndarray/-/ndarray-1.0.18.tgz", + "integrity": "sha1-tg06cyJOxVXQ+qeXEeUCRI/T95M=", + "requires": { + "iota-array": "1.0.0", + "is-buffer": "1.1.6" + } + }, + "ndarray-extract-contour": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/ndarray-extract-contour/-/ndarray-extract-contour-1.0.1.tgz", + "integrity": "sha1-Cu4ROjozsia5DEiIz4d79HUTBeQ=", + "requires": { + "typedarray-pool": "1.1.0" + } + }, + "ndarray-fill": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/ndarray-fill/-/ndarray-fill-1.0.2.tgz", + "integrity": "sha1-owpg9xiODJWC/N1YiWrNy1IqHtY=", + "requires": { + "cwise": "1.0.10" + } + }, + "ndarray-gradient": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/ndarray-gradient/-/ndarray-gradient-1.0.0.tgz", + "integrity": "sha1-t0kaUVxqZJ8ZpiMk//byf8jCU5M=", + "requires": { + "cwise-compiler": "1.1.3", + "dup": "1.0.0" + } + }, + "ndarray-homography": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/ndarray-homography/-/ndarray-homography-1.0.0.tgz", + "integrity": "sha1-w1UW6oa8KGK06ASiNqJwcwn+KWs=", + "requires": { + "gl-matrix-invert": "1.0.0", + "ndarray-warp": "1.0.1" + } + }, + "ndarray-linear-interpolate": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/ndarray-linear-interpolate/-/ndarray-linear-interpolate-1.0.0.tgz", + "integrity": "sha1-eLySuFuavBW25n7mWCj54hN65ys=" + }, + "ndarray-ops": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/ndarray-ops/-/ndarray-ops-1.2.2.tgz", + "integrity": "sha1-WeiNLDKn7ryxvGkPrhQVeVV6YU4=", + "requires": { + "cwise-compiler": "1.1.3" + } + }, + "ndarray-pack": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/ndarray-pack/-/ndarray-pack-1.2.1.tgz", + "integrity": "sha1-jK6+qqJNXs9w/4YCBjeXfajuWFo=", + "requires": { + "cwise-compiler": "1.1.3", + "ndarray": "1.0.18" + } + }, + "ndarray-scratch": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/ndarray-scratch/-/ndarray-scratch-1.2.0.tgz", + "integrity": "sha1-YwRjbWLrqT20cnrBPGkzQdulDgE=", + "requires": { + "ndarray": "1.0.18", + "ndarray-ops": "1.2.2", + "typedarray-pool": "1.1.0" + } + }, + "ndarray-sort": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/ndarray-sort/-/ndarray-sort-1.0.1.tgz", + "integrity": "sha1-/qBbTLg0x/TgIWo1TzynUTAN/Wo=", + "requires": { + "typedarray-pool": "1.1.0" + } + }, + "ndarray-warp": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/ndarray-warp/-/ndarray-warp-1.0.1.tgz", + "integrity": "sha1-qKElqqu6C+v5O9bKg+ar1oIqNOA=", + "requires": { + "cwise": "1.0.10", + "ndarray-linear-interpolate": "1.0.0" + } + }, + "nextafter": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/nextafter/-/nextafter-1.0.0.tgz", + "integrity": "sha1-t9d7U1MQ4+CX5gJauwqQNHfsGjo=", + "requires": { + "double-bits": "1.1.1" + } + }, + "node-fetch": { + "version": "1.7.3", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-1.7.3.tgz", + "integrity": "sha512-NhZ4CsKx7cYm2vSrBAr2PvFOe6sWDf0UYLRqA6svUYg7+/TSfVAu49jYC4BvQ4Sms9SZgdqGBgroqfDhJdTyKQ==", + "requires": { + "encoding": "0.1.12", + "is-stream": "1.1.0" + } + }, + "node-libs-browser": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/node-libs-browser/-/node-libs-browser-2.1.0.tgz", + "integrity": "sha512-5AzFzdoIMb89hBGMZglEegffzgRg+ZFoUmisQ8HI4j1KDdpx13J0taNp2y9xPbur6W61gepGDDotGBVQ7mfUCg==", + "dev": true, + "requires": { + "assert": "1.4.1", + "browserify-zlib": "0.2.0", + "buffer": "4.9.1", + "console-browserify": "1.1.0", + "constants-browserify": "1.0.0", + "crypto-browserify": "3.12.0", + "domain-browser": "1.2.0", + "events": "1.1.1", + "https-browserify": "1.0.0", + "os-browserify": "0.3.0", + "path-browserify": "0.0.0", + "process": "0.11.10", + "punycode": "1.4.1", + "querystring-es3": "0.2.1", + "readable-stream": "2.3.4", + "stream-browserify": "2.0.1", + "stream-http": "2.8.0", + "string_decoder": "1.0.3", + "timers-browserify": "2.0.6", + "tty-browserify": "0.0.0", + "url": "0.11.0", + "util": "0.10.3", + "vm-browserify": "0.0.4" + }, + "dependencies": { + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", + "dev": true + }, + "readable-stream": { + "version": "2.3.4", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.4.tgz", + "integrity": "sha512-vuYxeWYM+fde14+rajzqgeohAI7YoJcHE7kXDAc4Nk0EbuKnJfqtY9YtRkLo/tqkuF7MsBQRhPnPeyjYITp3ZQ==", + "dev": true, + "requires": { + "core-util-is": "1.0.2", + "inherits": "2.0.3", + "isarray": "1.0.0", + "process-nextick-args": "2.0.0", + "safe-buffer": "5.1.1", + "string_decoder": "1.0.3", + "util-deprecate": "1.0.2" + } + }, + "string_decoder": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.0.3.tgz", + "integrity": "sha512-4AH6Z5fzNNBcH+6XDMfA/BTt87skxqJlO0lAh3Dker5zThcAxG6mKz+iGu308UKoPPQ8Dcqx/4JhujzltRa+hQ==", + "dev": true, + "requires": { + "safe-buffer": "5.1.1" + } + } + } + }, + "nomnom": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/nomnom/-/nomnom-2.0.0.tgz", + "integrity": "sha512-frks+w18/6p+nAJ+zd6DdPpBytjt4tdTVnRY9nK4GoiCtG4gVgLs4MR+LCm83Bq4JtN6ol7a10BSPsS/qE+2dA==" + }, + "normalize-package-data": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.4.0.tgz", + "integrity": "sha512-9jjUFbTPfEy3R/ad/2oNbKtW9Hgovl5O1FvFWKkKblNXoN/Oou6+9+KKohPK13Yc3/TyunyWhJp6gvRNR/PPAw==", + "dev": true, + "requires": { + "hosted-git-info": "2.5.0", + "is-builtin-module": "1.0.0", + "semver": "5.5.0", + "validate-npm-package-license": "3.0.1" + } + }, + "normalize-path": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-2.1.1.tgz", + "integrity": "sha1-GrKLVW4Zg2Oowab35vogE3/mrtk=", + "dev": true, + "requires": { + "remove-trailing-separator": "1.1.0" + } + }, + "normalize-svg-path": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/normalize-svg-path/-/normalize-svg-path-0.1.0.tgz", + "integrity": "sha1-RWNg5g7Odfvve11+FgSA5//Rb+U=" + }, + "normals": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/normals/-/normals-1.1.0.tgz", + "integrity": "sha1-MltZXtNK/kZ6bFWhT9kIV4f/WcA=" + }, + "npm-run-path": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-2.0.2.tgz", + "integrity": "sha1-NakjLfo11wZ7TLLd8jV7GHFTbF8=", + "dev": true, + "requires": { + "path-key": "2.0.1" + } + }, + "number-is-nan": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz", + "integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=", + "dev": true + }, + "numeric": { + "version": "1.2.6", + "resolved": "https://registry.npmjs.org/numeric/-/numeric-1.2.6.tgz", + "integrity": "sha1-dlsCvvl5iPz4gNTrPza4D6MTNao=" + }, + "oauth-sign": { + "version": "0.8.2", + "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.8.2.tgz", + "integrity": "sha1-Rqarfwrq2N6unsBWV4C31O/rnUM=" + }, + "object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=" + }, + "object-inspect": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.3.0.tgz", + "integrity": "sha512-OHHnLgLNXpM++GnJRyyhbr2bwl3pPVm4YvaraHrRvDt/N3r+s/gDVHciA7EJBTkijKXj61ssgSAikq1fb0IBRg==" + }, + "object-keys": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.0.11.tgz", + "integrity": "sha1-xUYBd4rVYPEULODgG8yotW0TQm0=" + }, + "object.omit": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/object.omit/-/object.omit-2.0.1.tgz", + "integrity": "sha1-Gpx0SCnznbuFjHbKNXmuKlTr0fo=", + "dev": true, + "requires": { + "for-own": "0.1.5", + "is-extendable": "0.1.1" + } + }, + "once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", + "requires": { + "wrappy": "1.0.2" + } + }, + "optical-properties": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/optical-properties/-/optical-properties-1.0.0.tgz", + "integrity": "sha512-XnBQYbIIzDVr7U3L7d3xyAEqp1W+HTkqmw/G4L/Ae/+dq57bT1jqW2uDwV0wCUzO8gsTDIZhGQsGrMb17VSkEA==" + }, + "optionator": { + "version": "0.8.2", + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.8.2.tgz", + "integrity": "sha1-NkxeQJ0/TWMB1sC0wFu6UBgK62Q=", + "requires": { + "deep-is": "0.1.3", + "fast-levenshtein": "2.0.6", + "levn": "0.3.0", + "prelude-ls": "1.1.2", + "type-check": "0.3.2", + "wordwrap": "1.0.0" + } + }, + "options": { + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/options/-/options-0.0.6.tgz", + "integrity": "sha1-7CLTEoBrtT5zF3Pnza788cZDEo8=" + }, + "orbit-camera-controller": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/orbit-camera-controller/-/orbit-camera-controller-4.0.0.tgz", + "integrity": "sha1-bis28OeHhmPDMPUNqbfOaGwncAU=", + "requires": { + "filtered-vector": "1.2.4", + "gl-mat4": "1.1.4" + } + }, + "os-browserify": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/os-browserify/-/os-browserify-0.3.0.tgz", + "integrity": "sha1-hUNzx/XCMVkU/Jv8a9gjj92h7Cc=", + "dev": true + }, + "os-homedir": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/os-homedir/-/os-homedir-1.0.2.tgz", + "integrity": "sha1-/7xJiDNuDoM94MFox+8VISGqf7M=" + }, + "os-locale": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/os-locale/-/os-locale-2.1.0.tgz", + "integrity": "sha512-3sslG3zJbEYcaC4YVAvDorjGxc7tv6KVATnLPZONiljsUncvihe9BQoVCEs0RZ1kmf4Hk9OBqlZfJZWI4GanKA==", + "dev": true, + "requires": { + "execa": "0.7.0", + "lcid": "1.0.0", + "mem": "1.1.0" + } + }, + "p-finally": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/p-finally/-/p-finally-1.0.0.tgz", + "integrity": "sha1-P7z7FbiZpEEjs0ttzBi3JDNqLK4=", + "dev": true + }, + "p-limit": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-1.2.0.tgz", + "integrity": "sha512-Y/OtIaXtUPr4/YpMv1pCL5L5ed0rumAaAeBSj12F+bSlMdys7i8oQF/GUJmfpTS/QoaRrS/k6pma29haJpsMng==", + "dev": true, + "requires": { + "p-try": "1.0.0" + } + }, + "p-locate": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-2.0.0.tgz", + "integrity": "sha1-IKAQOyIqcMj9OcwuWAaA893l7EM=", + "dev": true, + "requires": { + "p-limit": "1.2.0" + } + }, + "p-try": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/p-try/-/p-try-1.0.0.tgz", + "integrity": "sha1-y8ec26+P1CKOE/Yh8rGiN8GyB7M=", + "dev": true + }, + "pad-left": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/pad-left/-/pad-left-1.0.2.tgz", + "integrity": "sha1-GeVzXqmDlaJs7carkm6tEPMQDUw=", + "requires": { + "repeat-string": "1.6.1" + } + }, + "pako": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/pako/-/pako-1.0.6.tgz", + "integrity": "sha512-lQe48YPsMJAig+yngZ87Lus+NF+3mtu7DVOBu6b/gHO1YpKwIj5AWjZ/TOS7i46HD/UixzWb1zeWDZfGZ3iYcg==", + "dev": true + }, + "parse-asn1": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/parse-asn1/-/parse-asn1-5.1.0.tgz", + "integrity": "sha1-N8T5t+06tlx0gXtfJICTf7+XxxI=", + "dev": true, + "requires": { + "asn1.js": "4.10.1", + "browserify-aes": "1.1.1", + "create-hash": "1.1.3", + "evp_bytestokey": "1.0.3", + "pbkdf2": "3.0.14" + } + }, + "parse-glob": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/parse-glob/-/parse-glob-3.0.4.tgz", + "integrity": "sha1-ssN2z7EfNVE7rdFz7wu246OIORw=", + "dev": true, + "requires": { + "glob-base": "0.3.0", + "is-dotfile": "1.0.3", + "is-extglob": "1.0.0", + "is-glob": "2.0.1" + } + }, + "parse-json": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-2.2.0.tgz", + "integrity": "sha1-9ID0BDTvgHQfhGkJn43qGPVaTck=", + "dev": true, + "requires": { + "error-ex": "1.3.1" + } + }, + "parse-rect": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/parse-rect/-/parse-rect-1.1.1.tgz", + "integrity": "sha512-SjynuO1UNvW9EvQJa5arv5edLkdf6lzTVTBmTW+FPACLaYahRCam8jJeICoOyLv27e3lY7Mo6m3qh6ASxxfR1A==", + "requires": { + "pick-by-alias": "1.2.0" + } + }, + "parse-svg-path": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/parse-svg-path/-/parse-svg-path-0.1.2.tgz", + "integrity": "sha1-en7A0esG+lMlx9PgCbhZoJtdSes=" + }, + "parse-unit": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/parse-unit/-/parse-unit-1.0.1.tgz", + "integrity": "sha1-fhu21b7zh0wo45JSaiVBFwKR7s8=" + }, + "path-browserify": { + "version": "0.0.0", + "resolved": "https://registry.npmjs.org/path-browserify/-/path-browserify-0.0.0.tgz", + "integrity": "sha1-oLhwcpquIUAFt9UDLsLLuw+0RRo=", + "dev": true + }, + "path-exists": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", + "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=", + "dev": true + }, + "path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=" + }, + "path-key": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-2.0.1.tgz", + "integrity": "sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A=", + "dev": true + }, + "path-parse": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.5.tgz", + "integrity": "sha1-PBrfhx6pzWyUMbbqK9dKD/BVxME=" + }, + "path-posix": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/path-posix/-/path-posix-1.0.0.tgz", + "integrity": "sha1-BrJhE/Vr6rBCVFojv6iAA8ysJg8=" + }, + "path-type": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-2.0.0.tgz", + "integrity": "sha1-8BLMuEFbcJb8LaoQVMPXI4lZTHM=", + "dev": true, + "requires": { + "pify": "2.3.0" + } + }, + "pbf": { + "version": "1.3.7", + "resolved": "https://registry.npmjs.org/pbf/-/pbf-1.3.7.tgz", + "integrity": "sha1-Hj0Ee6PL6Ahq6FSiVQOrRTfUM10=", + "requires": { + "ieee754": "1.1.8", + "resolve-protobuf-schema": "2.0.0" + } + }, + "pbkdf2": { + "version": "3.0.14", + "resolved": "https://registry.npmjs.org/pbkdf2/-/pbkdf2-3.0.14.tgz", + "integrity": "sha512-gjsZW9O34fm0R7PaLHRJmLLVfSoesxztjPjE9o6R+qtVJij90ltg1joIovN9GKrRW3t1PzhDDG3UMEMFfZ+1wA==", + "dev": true, + "requires": { + "create-hash": "1.1.3", + "create-hmac": "1.1.6", + "ripemd160": "2.0.1", + "safe-buffer": "5.1.1", + "sha.js": "2.4.10" + } + }, + "performance-now": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz", + "integrity": "sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns=" + }, + "permutation-parity": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/permutation-parity/-/permutation-parity-1.0.0.tgz", + "integrity": "sha1-AXTVH8pwSxG5pLFSsj1Tf9xrXvQ=", + "requires": { + "typedarray-pool": "1.1.0" + } + }, + "permutation-rank": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/permutation-rank/-/permutation-rank-1.0.0.tgz", + "integrity": "sha1-n9mLvOzwj79ZlLXq3JSmLmeUg7U=", + "requires": { + "invert-permutation": "1.0.0", + "typedarray-pool": "1.1.0" + } + }, + "pick-by-alias": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/pick-by-alias/-/pick-by-alias-1.2.0.tgz", + "integrity": "sha1-X3yysfIabh6ISgyHhVqko3NhEHs=" + }, + "pify": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", + "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", + "dev": true + }, + "planar-dual": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/planar-dual/-/planar-dual-1.0.2.tgz", + "integrity": "sha1-tqQjVSOxsMt55fkm+OozXdmC1WM=", + "requires": { + "compare-angle": "1.0.1", + "dup": "1.0.0" + } + }, + "planar-graph-to-polyline": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/planar-graph-to-polyline/-/planar-graph-to-polyline-1.0.5.tgz", + "integrity": "sha1-iCuGBRmbqIv9RkyVUzA1VsUrmIo=", + "requires": { + "edges-to-adjacency-list": "1.0.0", + "planar-dual": "1.0.2", + "point-in-big-polygon": "2.0.0", + "robust-orientation": "1.1.3", + "robust-sum": "1.0.0", + "two-product": "1.0.2", + "uniq": "1.0.1" + } + }, + "plotly.js": { + "version": "1.34.0", + "resolved": "https://registry.npmjs.org/plotly.js/-/plotly.js-1.34.0.tgz", + "integrity": "sha512-lnASrrjm1MniJtuL30x8XGGH8eD3umuFF4nzVG0Aw5HHTPmhmmdKkBXlPpyLy0JlAHsrGb9ZYLCBbtb9LHqvHg==", + "requires": { + "3d-view": "2.0.0", + "@plotly/d3-sankey": "0.5.0", + "alpha-shape": "1.0.0", + "array-range": "1.0.1", + "bubleify": "1.1.0", + "canvas-fit": "1.5.0", + "color-normalize": "1.0.3", + "color-rgba": "2.0.0", + "convex-hull": "1.0.3", + "country-regex": "1.1.0", + "d3": "3.5.17", + "d3-force": "1.1.0", + "delaunay-triangulate": "1.1.6", + "es6-promise": "3.3.1", + "fast-isnumeric": "1.1.1", + "font-atlas-sdf": "1.3.3", + "gl-contour2d": "1.1.4", + "gl-error3d": "1.0.7", + "gl-heatmap2d": "1.0.4", + "gl-line3d": "1.1.2", + "gl-mat4": "1.1.4", + "gl-mesh3d": "1.3.2", + "gl-plot2d": "1.3.1", + "gl-plot3d": "1.5.5", + "gl-pointcloud2d": "1.0.1", + "gl-scatter3d": "1.0.11", + "gl-select-box": "1.0.2", + "gl-spikes2d": "1.0.1", + "gl-surface3d": "1.3.4", + "glslify": "6.1.0", + "has-hover": "1.0.1", + "has-passive-events": "1.0.0", + "kdgrass": "1.0.1", + "mapbox-gl": "0.22.1", + "matrix-camera-controller": "2.1.3", + "mouse-change": "1.4.0", + "mouse-event-offset": "3.0.2", + "mouse-wheel": "1.2.0", + "ndarray": "1.0.18", + "ndarray-fill": "1.0.2", + "ndarray-homography": "1.0.0", + "ndarray-ops": "1.2.2", + "polybooljs": "1.2.0", + "regl": "1.3.1", + "regl-error2d": "2.0.4", + "regl-line2d": "2.1.4", + "regl-scatter2d": "2.1.16", + "right-now": "1.0.0", + "robust-orientation": "1.1.3", + "sane-topojson": "2.0.0", + "strongly-connected-components": "1.0.1", + "superscript-text": "1.0.0", + "svg-path-sdf": "1.1.1", + "tinycolor2": "1.4.1", + "topojson-client": "2.1.0", + "webgl-context": "2.2.0", + "world-calendars": "1.0.3" + } + }, + "pngjs": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/pngjs/-/pngjs-2.3.1.tgz", + "integrity": "sha1-EdHhK5y2TWPjDBQ6Mw9MH1Z9qF8=" + }, + "point-geometry": { + "version": "0.0.0", + "resolved": "https://registry.npmjs.org/point-geometry/-/point-geometry-0.0.0.tgz", + "integrity": "sha1-b8vK16gDtkGCR91uScKFPFhNr/c=" + }, + "point-in-big-polygon": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/point-in-big-polygon/-/point-in-big-polygon-2.0.0.tgz", + "integrity": "sha1-ObYT6mzxfWtD4Yj3fzTETGszulU=", + "requires": { + "binary-search-bounds": "1.0.0", + "interval-tree-1d": "1.0.3", + "robust-orientation": "1.1.3", + "slab-decomposition": "1.0.2" + } + }, + "polybooljs": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/polybooljs/-/polybooljs-1.2.0.tgz", + "integrity": "sha1-tDkMLgedTCYtOyUExiiNlbp6R1g=" + }, + "polytope-closest-point": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/polytope-closest-point/-/polytope-closest-point-1.0.0.tgz", + "integrity": "sha1-5uV/QIGrXox3i4Ee8G4sSK4zjD8=", + "requires": { + "numeric": "1.2.6" + } + }, + "prelude-ls": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.1.2.tgz", + "integrity": "sha1-IZMqVJ9eUv/ZqCf1cOBL5iqX2lQ=" + }, + "preserve": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/preserve/-/preserve-0.2.0.tgz", + "integrity": "sha1-gV7R9uvGWSb4ZbMQwHE7yzMVzks=", + "dev": true + }, + "process": { + "version": "0.11.10", + "resolved": "https://registry.npmjs.org/process/-/process-0.11.10.tgz", + "integrity": "sha1-czIwDoQBYb2j5podHZGn1LwW8YI=", + "dev": true + }, + "process-nextick-args": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.0.tgz", + "integrity": "sha512-MtEC1TqN0EU5nephaJ4rAtThHtC86dNN9qCuEhtshvpVBkAW5ZO7BASN9REnF9eoXGcRub+pFuKEpOHE+HbEMw==" + }, + "protocol-buffers-schema": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/protocol-buffers-schema/-/protocol-buffers-schema-2.2.0.tgz", + "integrity": "sha1-0pxs1z+2VZePtpiWkRgNuEQRn2E=" + }, + "prr": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/prr/-/prr-1.0.1.tgz", + "integrity": "sha1-0/wRS6BplaRexok/SEzrHXj19HY=", + "dev": true + }, + "pseudomap": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/pseudomap/-/pseudomap-1.0.2.tgz", + "integrity": "sha1-8FKijacOYYkX7wqKw0wa5aaChrM=", + "dev": true + }, + "public-encrypt": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/public-encrypt/-/public-encrypt-4.0.0.tgz", + "integrity": "sha1-OfaZ86RlYN1eusvKaTyvfGXBjMY=", + "dev": true, + "requires": { + "bn.js": "4.11.8", + "browserify-rsa": "4.0.1", + "create-hash": "1.1.3", + "parse-asn1": "5.1.0", + "randombytes": "2.0.6" + } + }, + "punycode": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz", + "integrity": "sha1-wNWmOycYgArY4esPpSachN1BhF4=" + }, + "qs": { + "version": "6.5.1", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.1.tgz", + "integrity": "sha512-eRzhrN1WSINYCDCbrz796z37LOe3m5tmW7RQf6oBntukAG1nmovJvhnwHHRMAfeoItc1m2Hk02WER2aQ/iqs+A==" + }, + "quat-slerp": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/quat-slerp/-/quat-slerp-1.0.1.tgz", + "integrity": "sha1-K6oVzjprvcMkHZcusXKDE57Wnyk=", + "requires": { + "gl-quat": "1.0.0" + } + }, + "querystring": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/querystring/-/querystring-0.2.0.tgz", + "integrity": "sha1-sgmEkgO7Jd+CDadW50cAWHhSFiA=", + "dev": true + }, + "querystring-es3": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/querystring-es3/-/querystring-es3-0.2.1.tgz", + "integrity": "sha1-nsYfeQSYdXB9aUFFlv2Qek1xHnM=", + "dev": true + }, + "querystringify": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/querystringify/-/querystringify-1.0.0.tgz", + "integrity": "sha1-YoYkIRLFtxL6ZU5SZlK/ahP/Bcs=" + }, + "quickselect": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/quickselect/-/quickselect-1.0.1.tgz", + "integrity": "sha512-Jt30UQSzTbxf6L2bFTMabHtGtYUzQcvOY0a+s5brm8tzndV/XWifBIH9v5QKtH5gGCZ5RRDwRhdhGMDVHAEGNQ==" + }, + "quote-stream": { + "version": "0.0.0", + "resolved": "https://registry.npmjs.org/quote-stream/-/quote-stream-0.0.0.tgz", + "integrity": "sha1-zeKelMQJsW4Z3HCYuJtmWPlyHTs=", + "requires": { + "minimist": "0.0.8", + "through2": "0.4.2" + }, + "dependencies": { + "minimist": { + "version": "0.0.8", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz", + "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=" + }, + "object-keys": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-0.4.0.tgz", + "integrity": "sha1-KKaq50KN0sOpLz2V8hM13SBOAzY=" + }, + "through2": { + "version": "0.4.2", + "resolved": "https://registry.npmjs.org/through2/-/through2-0.4.2.tgz", + "integrity": "sha1-2/WGYDEVHsg1K7bE22SiKSqEC5s=", + "requires": { + "readable-stream": "1.0.34", + "xtend": "2.1.2" + } + }, + "xtend": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-2.1.2.tgz", + "integrity": "sha1-bv7MKk2tjmlixJAbM3znuoe10os=", + "requires": { + "object-keys": "0.4.0" + } + } + } + }, + "randomatic": { + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/randomatic/-/randomatic-1.1.7.tgz", + "integrity": "sha512-D5JUjPyJbaJDkuAazpVnSfVkLlpeO3wDlPROTMLGKG1zMFNFRgrciKo1ltz/AzNTkqE0HzDx655QOL51N06how==", + "dev": true, + "requires": { + "is-number": "3.0.0", + "kind-of": "4.0.0" + }, + "dependencies": { + "is-number": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", + "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", + "dev": true, + "requires": { + "kind-of": "3.2.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "1.1.6" + } + } + } + }, + "kind-of": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-4.0.0.tgz", + "integrity": "sha1-IIE989cSkosgc3hpGkUGb65y3Vc=", + "dev": true, + "requires": { + "is-buffer": "1.1.6" + } + } + } + }, + "randombytes": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.0.6.tgz", + "integrity": "sha512-CIQ5OFxf4Jou6uOKe9t1AOgqpeU5fd70A8NPdHSGeYXqXsPe6peOwI0cUl88RWZ6sP1vPMV3avd/R6cZ5/sP1A==", + "dev": true, + "requires": { + "safe-buffer": "5.1.1" + } + }, + "randomfill": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/randomfill/-/randomfill-1.0.4.tgz", + "integrity": "sha512-87lcbR8+MhcWcUiQ+9e+Rwx8MyR2P7qnt15ynUlbm3TU/fjbgz4GsvfSUDTemtCCtVCqb4ZcEFlyPNTh9bBTLw==", + "dev": true, + "requires": { + "randombytes": "2.0.6", + "safe-buffer": "5.1.1" + } + }, + "rat-vec": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/rat-vec/-/rat-vec-1.1.1.tgz", + "integrity": "sha1-Dd4rZrezS7G80qI4BerIBth/0X8=", + "requires": { + "big-rat": "1.0.4" + } + }, + "read-package-json": { + "version": "2.0.12", + "resolved": "https://registry.npmjs.org/read-package-json/-/read-package-json-2.0.12.tgz", + "integrity": "sha512-m7/I0+tP6D34EVvSlzCtuVA4D/dHL6OpLcn2e4XVP5X57pCKGUy1JjRSBVKHWpB+vUU91sL85h84qX0MdXzBSw==", + "dev": true, + "requires": { + "glob": "7.1.2", + "graceful-fs": "4.1.11", + "json-parse-better-errors": "1.0.1", + "normalize-package-data": "2.4.0", + "slash": "1.0.0" + } + }, + "read-pkg": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-2.0.0.tgz", + "integrity": "sha1-jvHAYjxqbbDcZxPEv6xGMysjaPg=", + "dev": true, + "requires": { + "load-json-file": "2.0.0", + "normalize-package-data": "2.4.0", + "path-type": "2.0.0" + } + }, + "read-pkg-up": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-2.0.0.tgz", + "integrity": "sha1-a3KoBImE4MQeeVEP1en6mbO1Sb4=", + "dev": true, + "requires": { + "find-up": "2.1.0", + "read-pkg": "2.0.0" + } + }, + "readable-stream": { + "version": "1.0.34", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz", + "integrity": "sha1-Elgg40vIQtLyqq+v5MKRbuMsFXw=", + "requires": { + "core-util-is": "1.0.2", + "inherits": "2.0.3", + "isarray": "0.0.1", + "string_decoder": "0.10.31" + } + }, + "readdirp": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-2.1.0.tgz", + "integrity": "sha1-TtCtBg3zBzMAxIRANz9y0cxkLXg=", + "dev": true, + "requires": { + "graceful-fs": "4.1.11", + "minimatch": "3.0.4", + "readable-stream": "2.3.4", + "set-immediate-shim": "1.0.1" + }, + "dependencies": { + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", + "dev": true + }, + "readable-stream": { + "version": "2.3.4", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.4.tgz", + "integrity": "sha512-vuYxeWYM+fde14+rajzqgeohAI7YoJcHE7kXDAc4Nk0EbuKnJfqtY9YtRkLo/tqkuF7MsBQRhPnPeyjYITp3ZQ==", + "dev": true, + "requires": { + "core-util-is": "1.0.2", + "inherits": "2.0.3", + "isarray": "1.0.0", + "process-nextick-args": "2.0.0", + "safe-buffer": "5.1.1", + "string_decoder": "1.0.3", + "util-deprecate": "1.0.2" + } + }, + "string_decoder": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.0.3.tgz", + "integrity": "sha512-4AH6Z5fzNNBcH+6XDMfA/BTt87skxqJlO0lAh3Dker5zThcAxG6mKz+iGu308UKoPPQ8Dcqx/4JhujzltRa+hQ==", + "dev": true, + "requires": { + "safe-buffer": "5.1.1" + } + } + } + }, + "reduce-simplicial-complex": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/reduce-simplicial-complex/-/reduce-simplicial-complex-1.0.0.tgz", + "integrity": "sha1-dNaWovg196bc2SBl/YxRgfLt+Lw=", + "requires": { + "cell-orientation": "1.0.1", + "compare-cell": "1.0.0", + "compare-oriented-cell": "1.0.1" + } + }, + "regex-cache": { + "version": "0.4.4", + "resolved": "https://registry.npmjs.org/regex-cache/-/regex-cache-0.4.4.tgz", + "integrity": "sha512-nVIZwtCjkC9YgvWkpM55B5rBhBYRZhAaJbgcFYXXsHnbZ9UZI9nnVWYZpBlCqv9ho2eZryPnWrZGsOdPwVWXWQ==", + "dev": true, + "requires": { + "is-equal-shallow": "0.1.3" + } + }, + "regl": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/regl/-/regl-1.3.1.tgz", + "integrity": "sha1-KZXmOnmExSDvLaD28QJ/cFEzgUA=" + }, + "regl-error2d": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/regl-error2d/-/regl-error2d-2.0.4.tgz", + "integrity": "sha512-EsK+KJ2OREwMyVQ5jRBcoHN3vWPM8RSKU6mHlAVZ4sh71XsbQh4ob+IQ200nHasvusWY6ensMZG+RwTbG5tvXQ==", + "requires": { + "array-bounds": "1.0.1", + "bubleify": "1.1.0", + "color-normalize": "1.0.3", + "flatten-vertex-data": "1.0.0", + "object-assign": "4.1.1", + "pick-by-alias": "1.2.0", + "to-float32": "1.0.0", + "update-diff": "1.1.0" + } + }, + "regl-line2d": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/regl-line2d/-/regl-line2d-2.1.4.tgz", + "integrity": "sha512-m7c7y1H5QhlWVN++DjHdDvn/2sLdpBMd97GiGsnnXeE1oWboh6LGV7xNIcmodokc5B3AFR7W+izeFkSGThXg8g==", + "requires": { + "array-bounds": "1.0.1", + "array-normalize": "1.1.3", + "bubleify": "1.1.0", + "color-normalize": "1.0.3", + "earcut": "2.1.3", + "flatten-vertex-data": "1.0.0", + "glslify": "6.1.0", + "object-assign": "4.1.1", + "pick-by-alias": "1.2.0", + "to-float32": "1.0.0", + "update-diff": "1.1.0" + } + }, + "regl-scatter2d": { + "version": "2.1.16", + "resolved": "https://registry.npmjs.org/regl-scatter2d/-/regl-scatter2d-2.1.16.tgz", + "integrity": "sha512-HyXzk/6Cox4zz/NA5YDKJhgkkHQ58w8C+M6hHzgZRWRiM/0UWMB8PbLFi8tYYHLRPAeMZJOyaipqjzZqlXrg1g==", + "requires": { + "array-range": "1.0.1", + "binary-search-bounds": "2.0.4", + "bubleify": "1.1.0", + "clamp": "1.0.1", + "color-id": "1.1.0", + "color-normalize": "1.0.3", + "flatten-vertex-data": "1.0.0", + "glslify": "6.1.0", + "is-iexplorer": "1.0.0", + "object-assign": "4.1.1", + "parse-rect": "1.1.1", + "pick-by-alias": "1.2.0", + "snap-points-2d": "3.2.0", + "to-float32": "1.0.0", + "update-diff": "1.1.0" + }, + "dependencies": { + "binary-search-bounds": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/binary-search-bounds/-/binary-search-bounds-2.0.4.tgz", + "integrity": "sha512-2hg5kgdKql5ClF2ErBcSx0U5bnl5hgS4v7wMnLFodyR47yMtj2w+UAZB+0CiqyHct2q543i7Bi4/aMIegorCCg==" + } + } + }, + "remove-trailing-separator": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/remove-trailing-separator/-/remove-trailing-separator-1.1.0.tgz", + "integrity": "sha1-wkvOKig62tW8P1jg1IJJuSN52O8=", + "dev": true + }, + "repeat-element": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/repeat-element/-/repeat-element-1.1.2.tgz", + "integrity": "sha1-7wiaF40Ug7quTZPrmLT55OEdmQo=", + "dev": true + }, + "repeat-string": { + "version": "1.6.1", + "resolved": "https://registry.npmjs.org/repeat-string/-/repeat-string-1.6.1.tgz", + "integrity": "sha1-jcrkcOHIirwtYA//Sndihtp15jc=" + }, + "request": { + "version": "2.83.0", + "resolved": "https://registry.npmjs.org/request/-/request-2.83.0.tgz", + "integrity": "sha512-lR3gD69osqm6EYLk9wB/G1W/laGWjzH90t1vEa2xuxHD5KUrSzp9pUSfTm+YC5Nxt2T8nMPEvKlhbQayU7bgFw==", + "requires": { + "aws-sign2": "0.7.0", + "aws4": "1.6.0", + "caseless": "0.12.0", + "combined-stream": "1.0.6", + "extend": "3.0.1", + "forever-agent": "0.6.1", + "form-data": "2.3.2", + "har-validator": "5.0.3", + "hawk": "6.0.2", + "http-signature": "1.2.0", + "is-typedarray": "1.0.0", + "isstream": "0.1.2", + "json-stringify-safe": "5.0.1", + "mime-types": "2.1.18", + "oauth-sign": "0.8.2", + "performance-now": "2.1.0", + "qs": "6.5.1", + "safe-buffer": "5.1.1", + "stringstream": "0.0.5", + "tough-cookie": "2.3.3", + "tunnel-agent": "0.6.0", + "uuid": "3.2.1" + } + }, + "require-directory": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", + "integrity": "sha1-jGStX9MNqxyXbiNE/+f3kqam30I=", + "dev": true + }, + "require-main-filename": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-1.0.1.tgz", + "integrity": "sha1-l/cXtp1IeE9fUmpsWqj/3aBVpNE=", + "dev": true + }, + "requires-port": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz", + "integrity": "sha1-kl0mAdOaxIXgkc8NpcbmlNw9yv8=" + }, + "resolve": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.4.0.tgz", + "integrity": "sha512-aW7sVKPufyHqOmyyLzg/J+8606v5nevBgaliIlV7nUpVMsDnoBGV/cbSLNjZAg9q0Cfd/+easKVKQ8vOu8fn1Q==", + "requires": { + "path-parse": "1.0.5" + } + }, + "resolve-protobuf-schema": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/resolve-protobuf-schema/-/resolve-protobuf-schema-2.0.0.tgz", + "integrity": "sha1-5nsGKmfwLRG9aIbnDv2niEB+D7Q=", + "requires": { + "protocol-buffers-schema": "2.2.0" + } + }, + "resolve-url": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/resolve-url/-/resolve-url-0.2.1.tgz", + "integrity": "sha1-LGN/53yJOv0qZj/iGqkIAGjiBSo=" + }, + "resumer": { + "version": "0.0.0", + "resolved": "https://registry.npmjs.org/resumer/-/resumer-0.0.0.tgz", + "integrity": "sha1-8ej0YeQGS6Oegq883CqMiT0HZ1k=", + "requires": { + "through": "2.3.8" + } + }, + "right-align": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/right-align/-/right-align-0.1.3.tgz", + "integrity": "sha1-YTObci/mo1FWiSENJOFMlhSGE+8=", + "requires": { + "align-text": "0.1.4" + } + }, + "right-now": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/right-now/-/right-now-1.0.0.tgz", + "integrity": "sha1-bolgne69fc2vja7Mmuo5z1haCRg=" + }, + "rimraf": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.2.tgz", + "integrity": "sha512-lreewLK/BlghmxtfH36YYVg1i8IAce4TI7oao75I1g245+6BctqTVQiBP3YUJ9C6DQOXJmkYR9X9fCLtCOJc5w==", + "dev": true, + "requires": { + "glob": "7.1.2" + } + }, + "ripemd160": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/ripemd160/-/ripemd160-2.0.1.tgz", + "integrity": "sha1-D0WEKVxTo2KK9+bXmsohzlfRxuc=", + "dev": true, + "requires": { + "hash-base": "2.0.2", + "inherits": "2.0.3" + } + }, + "robust-compress": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/robust-compress/-/robust-compress-1.0.0.tgz", + "integrity": "sha1-TPYsSzGNgwhRYBK7jBF1Lzkymxs=" + }, + "robust-determinant": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/robust-determinant/-/robust-determinant-1.1.0.tgz", + "integrity": "sha1-jsrnm3nKqz509t6+IjflORon6cc=", + "requires": { + "robust-compress": "1.0.0", + "robust-scale": "1.0.2", + "robust-sum": "1.0.0", + "two-product": "1.0.2" + } + }, + "robust-dot-product": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/robust-dot-product/-/robust-dot-product-1.0.0.tgz", + "integrity": "sha1-yboBeL0sMEv9cl9Y6Inx2UYARVM=", + "requires": { + "robust-sum": "1.0.0", + "two-product": "1.0.2" + } + }, + "robust-in-sphere": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/robust-in-sphere/-/robust-in-sphere-1.1.3.tgz", + "integrity": "sha1-HFiD0WpOkjkpR27zSBmFe/Kpz3U=", + "requires": { + "robust-scale": "1.0.2", + "robust-subtract": "1.0.0", + "robust-sum": "1.0.0", + "two-product": "1.0.2" + } + }, + "robust-linear-solve": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/robust-linear-solve/-/robust-linear-solve-1.0.0.tgz", + "integrity": "sha1-DNasUEBpGm8qo81jEdcokFyjofE=", + "requires": { + "robust-determinant": "1.1.0" + } + }, + "robust-orientation": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/robust-orientation/-/robust-orientation-1.1.3.tgz", + "integrity": "sha1-2v9bANO+TmByLw6cAVbvln8cIEk=", + "requires": { + "robust-scale": "1.0.2", + "robust-subtract": "1.0.0", + "robust-sum": "1.0.0", + "two-product": "1.0.2" + } + }, + "robust-product": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/robust-product/-/robust-product-1.0.0.tgz", + "integrity": "sha1-aFJQAHzbunzx3nW/9tKScBEJir4=", + "requires": { + "robust-scale": "1.0.2", + "robust-sum": "1.0.0" + } + }, + "robust-scale": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/robust-scale/-/robust-scale-1.0.2.tgz", + "integrity": "sha1-d1Ey7QlULQKOWLLMecBikLz3jDI=", + "requires": { + "two-product": "1.0.2", + "two-sum": "1.0.0" + } + }, + "robust-segment-intersect": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/robust-segment-intersect/-/robust-segment-intersect-1.0.1.tgz", + "integrity": "sha1-MlK2oPwboUreaRXMvgnLzpqrHBw=", + "requires": { + "robust-orientation": "1.1.3" + } + }, + "robust-subtract": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/robust-subtract/-/robust-subtract-1.0.0.tgz", + "integrity": "sha1-4LFk4e2LpOOl3aRaEgODSNvtPpo=" + }, + "robust-sum": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/robust-sum/-/robust-sum-1.0.0.tgz", + "integrity": "sha1-FmRuUlKStNJdgnV6KGlV4Lv6U9k=" + }, + "rw": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/rw/-/rw-0.1.4.tgz", + "integrity": "sha1-SQPL2AJIrg7eaFv1j9I2p6mymj4=" + }, + "safe-buffer": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.1.tgz", + "integrity": "sha512-kKvNJn6Mm93gAczWVJg7wH+wGYWNrDHdWvpUmHyEsgCtIwwo3bqPtV4tR5tuPaUhTOo/kvhVwd8XwwOllGYkbg==" + }, + "sane-topojson": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/sane-topojson/-/sane-topojson-2.0.0.tgz", + "integrity": "sha1-QOJXNqKMTM6qojP0W7hjc6J4W4Q=" + }, + "semver": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.5.0.tgz", + "integrity": "sha512-4SJ3dm0WAwWy/NVeioZh5AntkdJoWKxHxcmyP622fOkgHa4z3R0TdBJICINyaSDE6uNwVc8gZr+ZinwZAH4xIA==", + "dev": true + }, + "set-blocking": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", + "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=", + "dev": true + }, + "set-immediate-shim": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/set-immediate-shim/-/set-immediate-shim-1.0.1.tgz", + "integrity": "sha1-SysbJ+uAip+NzEgaWOXlb1mfP2E=", + "dev": true + }, + "setimmediate": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/setimmediate/-/setimmediate-1.0.5.tgz", + "integrity": "sha1-KQy7Iy4waULX1+qbg3Mqt4VvgoU=", + "dev": true + }, + "sha.js": { + "version": "2.4.10", + "resolved": "https://registry.npmjs.org/sha.js/-/sha.js-2.4.10.tgz", + "integrity": "sha512-vnwmrFDlOExK4Nm16J2KMWHLrp14lBrjxMxBJpu++EnsuBmpiYaM/MEs46Vxxm/4FvdP5yTwuCTO9it5FSjrqA==", + "dev": true, + "requires": { + "inherits": "2.0.3", + "safe-buffer": "5.1.1" + } + }, + "shallow-copy": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/shallow-copy/-/shallow-copy-0.0.1.tgz", + "integrity": "sha1-QV9CcC1z2BAzApLMXuhurhoRoXA=" + }, + "shebang-command": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-1.2.0.tgz", + "integrity": "sha1-RKrGW2lbAzmJaMOfNj/uXer98eo=", + "dev": true, + "requires": { + "shebang-regex": "1.0.0" + } + }, + "shebang-regex": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-1.0.0.tgz", + "integrity": "sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM=", + "dev": true + }, + "shelf-pack": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/shelf-pack/-/shelf-pack-1.1.0.tgz", + "integrity": "sha1-tGea/dAK1o39m70rWj6BkpOnTYI=" + }, + "signal-exit": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.2.tgz", + "integrity": "sha1-tf3AjxKH6hF4Yo5BXiUTK3NkbG0=", + "dev": true + }, + "signum": { + "version": "0.0.0", + "resolved": "https://registry.npmjs.org/signum/-/signum-0.0.0.tgz", + "integrity": "sha1-q1UbEAM1EHCnBHg/GgnF52kfnPY=" + }, + "simplicial-complex": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/simplicial-complex/-/simplicial-complex-1.0.0.tgz", + "integrity": "sha1-bDOk7Wn81Nkbe8rdOzC2NoPq4kE=", + "requires": { + "bit-twiddle": "1.0.2", + "union-find": "1.0.2" + } + }, + "simplicial-complex-boundary": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/simplicial-complex-boundary/-/simplicial-complex-boundary-1.0.1.tgz", + "integrity": "sha1-csn/HiTeqjdMm7L6DL8MCB6++BU=", + "requires": { + "boundary-cells": "2.0.1", + "reduce-simplicial-complex": "1.0.0" + } + }, + "simplicial-complex-contour": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/simplicial-complex-contour/-/simplicial-complex-contour-1.0.2.tgz", + "integrity": "sha1-iQqsrChDZTQBEFRc8mKaJuBL+dE=", + "requires": { + "marching-simplex-table": "1.0.0", + "ndarray": "1.0.18", + "ndarray-sort": "1.0.1", + "typedarray-pool": "1.1.0" + } + }, + "simplify-planar-graph": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/simplify-planar-graph/-/simplify-planar-graph-2.0.1.tgz", + "integrity": "sha1-vIWJNyXzLo+oriVoE5hEbSy892Y=", + "requires": { + "robust-orientation": "1.1.3", + "simplicial-complex": "0.3.3" + }, + "dependencies": { + "bit-twiddle": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/bit-twiddle/-/bit-twiddle-0.0.2.tgz", + "integrity": "sha1-wurruVKjuUrMFASX4c3NLxoz9Y4=" + }, + "simplicial-complex": { + "version": "0.3.3", + "resolved": "https://registry.npmjs.org/simplicial-complex/-/simplicial-complex-0.3.3.tgz", + "integrity": "sha1-TDDK1X+eRXKd2PMGyHU1efRr6Z4=", + "requires": { + "bit-twiddle": "0.0.2", + "union-find": "0.0.4" + } + }, + "union-find": { + "version": "0.0.4", + "resolved": "https://registry.npmjs.org/union-find/-/union-find-0.0.4.tgz", + "integrity": "sha1-uFSzMBYZva0USwAUx4+W6sDS8PY=" + } + } + }, + "slab-decomposition": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/slab-decomposition/-/slab-decomposition-1.0.2.tgz", + "integrity": "sha1-He1WdU1AixBznxRRA9/GGAf2UTQ=", + "requires": { + "binary-search-bounds": "1.0.0", + "functional-red-black-tree": "1.0.1", + "robust-orientation": "1.1.3" + } + }, + "slash": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-1.0.0.tgz", + "integrity": "sha1-xB8vbDn8FtHNF61LXYlhFK5HDVU=", + "dev": true + }, + "snap-points-2d": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/snap-points-2d/-/snap-points-2d-3.2.0.tgz", + "integrity": "sha1-DhniKjoOlrziHN9cfx1+1blnRfA=", + "requires": { + "array-bounds": "1.0.1" + } + }, + "sntp": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/sntp/-/sntp-2.1.0.tgz", + "integrity": "sha512-FL1b58BDrqS3A11lJ0zEdnJ3UOKqVxawAkF3k7F0CVN7VQ34aZrV+G8BZ1WC9ZL7NyrwsW0oviwsWDgRuVYtJg==", + "requires": { + "hoek": "4.2.1" + } + }, + "sort-asc": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/sort-asc/-/sort-asc-0.1.0.tgz", + "integrity": "sha1-q3md9h/HPqCVbHnEtTHtHp53J+k=" + }, + "sort-desc": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/sort-desc/-/sort-desc-0.1.1.tgz", + "integrity": "sha1-GYuMDN6wlcRjNBhh45JdTuNZqe4=" + }, + "sort-object": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/sort-object/-/sort-object-0.3.2.tgz", + "integrity": "sha1-mODRme3kDgfGGoRAPGHWw7KQ+eI=", + "requires": { + "sort-asc": "0.1.0", + "sort-desc": "0.1.1" + } + }, + "source-list-map": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/source-list-map/-/source-list-map-2.0.0.tgz", + "integrity": "sha512-I2UmuJSRr/T8jisiROLU3A3ltr+swpniSmNPI4Ml3ZCX6tVnDsuZzK7F2hl5jTqbZBWCEKlj5HRQiPExXLgE8A==", + "dev": true + }, + "source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=" + }, + "spdx-correct": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-1.0.2.tgz", + "integrity": "sha1-SzBz2TP/UfORLwOsVRlJikFQ20A=", + "dev": true, + "requires": { + "spdx-license-ids": "1.2.2" + } + }, + "spdx-expression-parse": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-1.0.4.tgz", + "integrity": "sha1-m98vIOH0DtRH++JzJmGR/O1RYmw=", + "dev": true + }, + "spdx-license-ids": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-1.2.2.tgz", + "integrity": "sha1-yd96NCRZSt5r0RkA1ZZpbcBrrFc=", + "dev": true + }, + "split-polygon": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/split-polygon/-/split-polygon-1.0.0.tgz", + "integrity": "sha1-DqzIoTanaxKj2VJW6n2kXbDC0kc=", + "requires": { + "robust-dot-product": "1.0.0", + "robust-sum": "1.0.0" + } + }, + "sprintf-js": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.1.1.tgz", + "integrity": "sha1-Nr54Mgr+WAH2zqPueLblqrlA6gw=" + }, + "sshpk": { + "version": "1.13.1", + "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.13.1.tgz", + "integrity": "sha1-US322mKHFEMW3EwY/hzx2UBzm+M=", + "requires": { + "asn1": "0.2.3", + "assert-plus": "1.0.0", + "bcrypt-pbkdf": "1.0.1", + "dashdash": "1.14.1", + "ecc-jsbn": "0.1.1", + "getpass": "0.1.7", + "jsbn": "0.1.1", + "tweetnacl": "0.14.5" + } + }, + "stack-trace": { + "version": "0.0.9", + "resolved": "https://registry.npmjs.org/stack-trace/-/stack-trace-0.0.9.tgz", + "integrity": "sha1-qPbq7KkGdMMz58Q5U/J1tFFRBpU=" + }, + "static-eval": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/static-eval/-/static-eval-1.1.1.tgz", + "integrity": "sha1-yoEwIQNUzxPZpyK8fpI3eEV7sZI=", + "requires": { + "escodegen": "1.9.0" + } + }, + "static-module": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/static-module/-/static-module-1.5.0.tgz", + "integrity": "sha1-J9qYg8QajNCSNvhC8MHrxu32PYY=", + "requires": { + "concat-stream": "1.6.0", + "duplexer2": "0.0.2", + "escodegen": "1.3.3", + "falafel": "2.1.0", + "has": "1.0.1", + "object-inspect": "0.4.0", + "quote-stream": "0.0.0", + "readable-stream": "1.0.34", + "shallow-copy": "0.0.1", + "static-eval": "0.2.4", + "through2": "0.4.2" + }, + "dependencies": { + "escodegen": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/escodegen/-/escodegen-1.3.3.tgz", + "integrity": "sha1-8CQBb1qI4Eb9EgBQVek5gC5sXyM=", + "requires": { + "esprima": "1.1.1", + "estraverse": "1.5.1", + "esutils": "1.0.0", + "source-map": "0.1.43" + } + }, + "esprima": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-1.1.1.tgz", + "integrity": "sha1-W28VR/TRAuZw4UDFCb5ncdautUk=" + }, + "estraverse": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-1.5.1.tgz", + "integrity": "sha1-hno+jlip+EYYr7bC3bzZFrfLr3E=" + }, + "esutils": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/esutils/-/esutils-1.0.0.tgz", + "integrity": "sha1-gVHTWOIMisx/t0XnRywAJf5JZXA=" + }, + "object-inspect": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-0.4.0.tgz", + "integrity": "sha1-9RV8EWwUVbJDsG7pdwM5LFrYn+w=" + }, + "object-keys": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-0.4.0.tgz", + "integrity": "sha1-KKaq50KN0sOpLz2V8hM13SBOAzY=" + }, + "source-map": { + "version": "0.1.43", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.1.43.tgz", + "integrity": "sha1-wkvBRspRfBRx9drL4lcbK3+eM0Y=", + "optional": true, + "requires": { + "amdefine": "1.0.1" + } + }, + "static-eval": { + "version": "0.2.4", + "resolved": "https://registry.npmjs.org/static-eval/-/static-eval-0.2.4.tgz", + "integrity": "sha1-t9NNg4k3uWn5ZBygfUj47eJj6ns=", + "requires": { + "escodegen": "0.0.28" + }, + "dependencies": { + "escodegen": { + "version": "0.0.28", + "resolved": "https://registry.npmjs.org/escodegen/-/escodegen-0.0.28.tgz", + "integrity": "sha1-Dk/xcV8yh3XWyrUaxEpAbNer/9M=", + "requires": { + "esprima": "1.0.4", + "estraverse": "1.3.2", + "source-map": "0.1.43" + } + }, + "esprima": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-1.0.4.tgz", + "integrity": "sha1-n1V+CPw7TSbs6d00+Pv0drYlha0=" + }, + "estraverse": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-1.3.2.tgz", + "integrity": "sha1-N8K4k+8T1yPydth41g2FNRUqbEI=" + } + } + }, + "through2": { + "version": "0.4.2", + "resolved": "https://registry.npmjs.org/through2/-/through2-0.4.2.tgz", + "integrity": "sha1-2/WGYDEVHsg1K7bE22SiKSqEC5s=", + "requires": { + "readable-stream": "1.0.34", + "xtend": "2.1.2" + } + }, + "xtend": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-2.1.2.tgz", + "integrity": "sha1-bv7MKk2tjmlixJAbM3znuoe10os=", + "requires": { + "object-keys": "0.4.0" + } + } + } + }, + "stream-browserify": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/stream-browserify/-/stream-browserify-2.0.1.tgz", + "integrity": "sha1-ZiZu5fm9uZQKTkUUyvtDu3Hlyds=", + "dev": true, + "requires": { + "inherits": "2.0.3", + "readable-stream": "2.3.4" + }, + "dependencies": { + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", + "dev": true + }, + "readable-stream": { + "version": "2.3.4", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.4.tgz", + "integrity": "sha512-vuYxeWYM+fde14+rajzqgeohAI7YoJcHE7kXDAc4Nk0EbuKnJfqtY9YtRkLo/tqkuF7MsBQRhPnPeyjYITp3ZQ==", + "dev": true, + "requires": { + "core-util-is": "1.0.2", + "inherits": "2.0.3", + "isarray": "1.0.0", + "process-nextick-args": "2.0.0", + "safe-buffer": "5.1.1", + "string_decoder": "1.0.3", + "util-deprecate": "1.0.2" + } + }, + "string_decoder": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.0.3.tgz", + "integrity": "sha512-4AH6Z5fzNNBcH+6XDMfA/BTt87skxqJlO0lAh3Dker5zThcAxG6mKz+iGu308UKoPPQ8Dcqx/4JhujzltRa+hQ==", + "dev": true, + "requires": { + "safe-buffer": "5.1.1" + } + } + } + }, + "stream-http": { + "version": "2.8.0", + "resolved": "https://registry.npmjs.org/stream-http/-/stream-http-2.8.0.tgz", + "integrity": "sha512-sZOFxI/5xw058XIRHl4dU3dZ+TTOIGJR78Dvo0oEAejIt4ou27k+3ne1zYmCV+v7UucbxIFQuOgnkTVHh8YPnw==", + "dev": true, + "requires": { + "builtin-status-codes": "3.0.0", + "inherits": "2.0.3", + "readable-stream": "2.3.4", + "to-arraybuffer": "1.0.1", + "xtend": "4.0.1" + }, + "dependencies": { + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", + "dev": true + }, + "readable-stream": { + "version": "2.3.4", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.4.tgz", + "integrity": "sha512-vuYxeWYM+fde14+rajzqgeohAI7YoJcHE7kXDAc4Nk0EbuKnJfqtY9YtRkLo/tqkuF7MsBQRhPnPeyjYITp3ZQ==", + "dev": true, + "requires": { + "core-util-is": "1.0.2", + "inherits": "2.0.3", + "isarray": "1.0.0", + "process-nextick-args": "2.0.0", + "safe-buffer": "5.1.1", + "string_decoder": "1.0.3", + "util-deprecate": "1.0.2" + } + }, + "string_decoder": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.0.3.tgz", + "integrity": "sha512-4AH6Z5fzNNBcH+6XDMfA/BTt87skxqJlO0lAh3Dker5zThcAxG6mKz+iGu308UKoPPQ8Dcqx/4JhujzltRa+hQ==", + "dev": true, + "requires": { + "safe-buffer": "5.1.1" + } + } + } + }, + "stream-shift": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/stream-shift/-/stream-shift-1.0.0.tgz", + "integrity": "sha1-1cdSgl5TZ+eG944Y5EXqIjoVWVI=" + }, + "string-width": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", + "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==", + "dev": true, + "requires": { + "is-fullwidth-code-point": "2.0.0", + "strip-ansi": "4.0.0" + }, + "dependencies": { + "ansi-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", + "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", + "dev": true + }, + "is-fullwidth-code-point": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", + "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", + "dev": true + }, + "strip-ansi": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", + "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", + "dev": true, + "requires": { + "ansi-regex": "3.0.0" + } + } + } + }, + "string.prototype.trim": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/string.prototype.trim/-/string.prototype.trim-1.1.2.tgz", + "integrity": "sha1-0E3iyJ4Tf019IG8Ia17S+ua+jOo=", + "requires": { + "define-properties": "1.1.2", + "es-abstract": "1.10.0", + "function-bind": "1.1.1" + } + }, + "string_decoder": { + "version": "0.10.31", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", + "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=" + }, + "stringstream": { + "version": "0.0.5", + "resolved": "https://registry.npmjs.org/stringstream/-/stringstream-0.0.5.tgz", + "integrity": "sha1-TkhM1N5aC7vuGORjB3EKioFiGHg=" + }, + "strip-ansi": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", + "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", + "dev": true, + "requires": { + "ansi-regex": "2.1.1" + } + }, + "strip-bom": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", + "integrity": "sha1-IzTBjpx1n3vdVv3vfprj1YjmjtM=", + "dev": true + }, + "strip-eof": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/strip-eof/-/strip-eof-1.0.0.tgz", + "integrity": "sha1-u0P/VZim6wXYm1n80SnJgzE2Br8=", + "dev": true + }, + "strongly-connected-components": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/strongly-connected-components/-/strongly-connected-components-1.0.1.tgz", + "integrity": "sha1-CSDitN9nyOrulsa2I0/inoc9upk=" + }, + "supercluster": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/supercluster/-/supercluster-2.3.0.tgz", + "integrity": "sha1-h6tWCBu+qaHXJN9TUe6ejDry9Is=", + "requires": { + "kdbush": "1.0.1" + } + }, + "superscript-text": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/superscript-text/-/superscript-text-1.0.0.tgz", + "integrity": "sha1-58snUlZzYN9QvrBhDOjfPXHY39g=" + }, + "supports-color": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.2.0.tgz", + "integrity": "sha512-F39vS48la4YvTZUPVeTqsjsFNrvcMwrV3RLZINsmHo+7djCvuUzSIeXOnZ5hmjef4bajL1dNccN+tg5XAliO5Q==", + "requires": { + "has-flag": "3.0.0" + } + }, + "surface-nets": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/surface-nets/-/surface-nets-1.0.2.tgz", + "integrity": "sha1-5DPIy7qUpydMb0yZVStGG/H8eks=", + "requires": { + "ndarray-extract-contour": "1.0.1", + "triangulate-hypercube": "1.0.1", + "zero-crossings": "1.0.1" + } + }, + "svg-arc-to-cubic-bezier": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/svg-arc-to-cubic-bezier/-/svg-arc-to-cubic-bezier-3.0.0.tgz", + "integrity": "sha1-iFaaoYqLrWOEA7+taB97Wp8vZoU=" + }, + "svg-path-bounds": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/svg-path-bounds/-/svg-path-bounds-1.0.1.tgz", + "integrity": "sha1-v0WLeDcmv1NDG0Yz8nkvYHSNn3Q=", + "requires": { + "abs-svg-path": "0.1.1", + "is-svg-path": "1.0.2", + "normalize-svg-path": "1.0.1", + "parse-svg-path": "0.1.2" + }, + "dependencies": { + "normalize-svg-path": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/normalize-svg-path/-/normalize-svg-path-1.0.1.tgz", + "integrity": "sha1-b3Ka1rcLtMpO/y/ksQdInv4dVv4=", + "requires": { + "svg-arc-to-cubic-bezier": "3.0.0" + } + } + } + }, + "svg-path-sdf": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/svg-path-sdf/-/svg-path-sdf-1.1.1.tgz", + "integrity": "sha1-oqlHJb/mw8Gsn6UmYCc/P18JMuU=", + "requires": { + "bitmap-sdf": "1.0.3", + "draw-svg-path": "1.0.0", + "is-svg-path": "1.0.2", + "parse-svg-path": "0.1.2", + "svg-path-bounds": "1.0.1" + } + }, + "tapable": { + "version": "0.2.8", + "resolved": "https://registry.npmjs.org/tapable/-/tapable-0.2.8.tgz", + "integrity": "sha1-mTcqXJmb8t8WCvwNdL7U9HlIzSI=", + "dev": true + }, + "tape": { + "version": "4.8.0", + "resolved": "https://registry.npmjs.org/tape/-/tape-4.8.0.tgz", + "integrity": "sha512-TWILfEnvO7I8mFe35d98F6T5fbLaEtbFTG/lxWvid8qDfFTxt19EBijWmB4j3+Hoh5TfHE2faWs73ua+EphuBA==", + "requires": { + "deep-equal": "1.0.1", + "defined": "1.0.0", + "for-each": "0.3.2", + "function-bind": "1.1.1", + "glob": "7.1.2", + "has": "1.0.1", + "inherits": "2.0.3", + "minimist": "1.2.0", + "object-inspect": "1.3.0", + "resolve": "1.4.0", + "resumer": "0.0.0", + "string.prototype.trim": "1.1.2", + "through": "2.3.8" + } + }, + "text-cache": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/text-cache/-/text-cache-4.1.0.tgz", + "integrity": "sha1-fFgJDoWsCRD5dt9M/Izoqg6lh2Y=", + "requires": { + "vectorize-text": "3.0.2" + } + }, + "through": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", + "integrity": "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=" + }, + "through2": { + "version": "0.6.5", + "resolved": "https://registry.npmjs.org/through2/-/through2-0.6.5.tgz", + "integrity": "sha1-QaucZ7KdVyCQcUEOHXp6lozTrUg=", + "requires": { + "readable-stream": "1.0.34", + "xtend": "4.0.1" + } + }, + "timers-browserify": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/timers-browserify/-/timers-browserify-2.0.6.tgz", + "integrity": "sha512-HQ3nbYRAowdVd0ckGFvmJPPCOH/CHleFN/Y0YQCX1DVaB7t+KFvisuyN09fuP8Jtp1CpfSh8O8bMkHbdbPe6Pw==", + "dev": true, + "requires": { + "setimmediate": "1.0.5" + } + }, + "tiny-sdf": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/tiny-sdf/-/tiny-sdf-1.0.2.tgz", + "integrity": "sha1-KOdphcRMTlhMS2fY7N2bM6HKwow=" + }, + "tinycolor2": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/tinycolor2/-/tinycolor2-1.4.1.tgz", + "integrity": "sha1-9PrTM0R7wLB9TcjpIJ2POaisd+g=" + }, + "to-arraybuffer": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/to-arraybuffer/-/to-arraybuffer-1.0.1.tgz", + "integrity": "sha1-fSKbH8xjfkZsoIEYCDanqr/4P0M=", + "dev": true + }, + "to-float32": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/to-float32/-/to-float32-1.0.0.tgz", + "integrity": "sha512-AtYAqiHS1q+IqVfZOExaRC72mUZuMZP7yU1xsR07y0SLLEvPf68R+xGfya3eY4CR7jxT/zQt3wM8w4mGq/mPXA==" + }, + "to-px": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/to-px/-/to-px-1.0.1.tgz", + "integrity": "sha1-W7rtXl1PdkRbzJA8KTojB90yRkY=", + "requires": { + "parse-unit": "1.0.1" + } + }, + "to-utf8": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/to-utf8/-/to-utf8-0.0.1.tgz", + "integrity": "sha1-0Xrqcv8vujm55DYBvns/9y4ImFI=" + }, + "topojson-client": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/topojson-client/-/topojson-client-2.1.0.tgz", + "integrity": "sha1-/59784mRGF4LQoTCsGroNPDqxsg=", + "requires": { + "commander": "2.1.0" + } + }, + "tough-cookie": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.3.3.tgz", + "integrity": "sha1-C2GKVWW23qkL80JdBNVe3EdadWE=", + "requires": { + "punycode": "1.4.1" + } + }, + "triangulate-hypercube": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/triangulate-hypercube/-/triangulate-hypercube-1.0.1.tgz", + "integrity": "sha1-2Acdsuv8/VHzCNC88qXEils20Tc=", + "requires": { + "gamma": "0.1.0", + "permutation-parity": "1.0.0", + "permutation-rank": "1.0.0" + } + }, + "triangulate-polyline": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/triangulate-polyline/-/triangulate-polyline-1.0.3.tgz", + "integrity": "sha1-v4uod6hQVBA/65+lphtOjXAXgU0=", + "requires": { + "cdt2d": "1.0.0" + } + }, + "tty-browserify": { + "version": "0.0.0", + "resolved": "https://registry.npmjs.org/tty-browserify/-/tty-browserify-0.0.0.tgz", + "integrity": "sha1-oVe6QC2iTpv5V/mqadUk7tQpAaY=", + "dev": true + }, + "tunnel-agent": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", + "integrity": "sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0=", + "requires": { + "safe-buffer": "5.1.1" + } + }, + "turntable-camera-controller": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/turntable-camera-controller/-/turntable-camera-controller-3.0.1.tgz", + "integrity": "sha1-jb0/4AVQGRxlFky4iJcQSVeK/Zk=", + "requires": { + "filtered-vector": "1.2.4", + "gl-mat4": "1.1.4", + "gl-vec3": "1.0.3" + } + }, + "tweetnacl": { + "version": "0.14.5", + "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz", + "integrity": "sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q=", + "optional": true + }, + "two-product": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/two-product/-/two-product-1.0.2.tgz", + "integrity": "sha1-Z9ldSyV6kh4stL16+VEfkIhSLqo=" + }, + "two-sum": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/two-sum/-/two-sum-1.0.0.tgz", + "integrity": "sha1-MdPzIjnk9zHsqd+RVeKyl/AIq2Q=" + }, + "type-check": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.3.2.tgz", + "integrity": "sha1-WITKtRLPHTVeP7eE8wgEsrUg23I=", + "requires": { + "prelude-ls": "1.1.2" + } + }, + "typedarray": { + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz", + "integrity": "sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=" + }, + "typedarray-pool": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/typedarray-pool/-/typedarray-pool-1.1.0.tgz", + "integrity": "sha1-0RT0hIAUifU+yrXoCIqiMET0mNk=", + "requires": { + "bit-twiddle": "1.0.2", + "dup": "1.0.0" + } + }, + "uglify-js": { + "version": "2.8.29", + "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-2.8.29.tgz", + "integrity": "sha1-KcVzMUgFe7Th913zW3qcty5qWd0=", + "requires": { + "source-map": "0.5.7", + "uglify-to-browserify": "1.0.2", + "yargs": "3.10.0" + } + }, + "uglify-to-browserify": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/uglify-to-browserify/-/uglify-to-browserify-1.0.2.tgz", + "integrity": "sha1-bgkk1r2mta/jSeOabWMoUKD4grc=", + "optional": true + }, + "uglifyjs-webpack-plugin": { + "version": "0.4.6", + "resolved": "https://registry.npmjs.org/uglifyjs-webpack-plugin/-/uglifyjs-webpack-plugin-0.4.6.tgz", + "integrity": "sha1-uVH0q7a9YX5m9j64kUmOORdj4wk=", + "dev": true, + "requires": { + "source-map": "0.5.7", + "uglify-js": "2.8.29", + "webpack-sources": "1.1.0" + } + }, + "ultron": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/ultron/-/ultron-1.0.2.tgz", + "integrity": "sha1-rOEWq1V80Zc4ak6I9GhTeMiy5Po=" + }, + "unassert": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/unassert/-/unassert-1.5.1.tgz", + "integrity": "sha1-y8iOw4dBfFpeTALTzQe+mL11/3Y=", + "requires": { + "acorn": "4.0.13", + "call-matcher": "1.0.1", + "deep-equal": "1.0.1", + "espurify": "1.7.0", + "estraverse": "4.2.0", + "esutils": "2.0.2", + "object-assign": "4.1.1" + }, + "dependencies": { + "acorn": { + "version": "4.0.13", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-4.0.13.tgz", + "integrity": "sha1-EFSVrlNh1pe9GVyCUZLhrX8lN4c=" + } + } + }, + "unassertify": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/unassertify/-/unassertify-2.1.0.tgz", + "integrity": "sha512-CB3C3vbOwrZydRuGdU8H421r4/qhM8RLuEOo3G+wEFf7kDP4TR+7oDuj1yOik5pUzXMaJmzxICM7akupP1AlJw==", + "requires": { + "acorn": "5.4.1", + "convert-source-map": "1.5.1", + "escodegen": "1.9.0", + "multi-stage-sourcemap": "0.2.1", + "through": "2.3.8", + "unassert": "1.5.1" + } + }, + "underscore": { + "version": "1.8.3", + "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.8.3.tgz", + "integrity": "sha1-Tz+1OxBuYJf8+ctBCfKl6b36UCI=" + }, + "union-find": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/union-find/-/union-find-1.0.2.tgz", + "integrity": "sha1-KSusQV5q06iVNdI3AQ20pTYoTlg=" + }, + "uniq": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/uniq/-/uniq-1.0.1.tgz", + "integrity": "sha1-sxxa6CVIRKOoKBVBzisEuGWnNP8=" + }, + "unitbezier": { + "version": "0.0.0", + "resolved": "https://registry.npmjs.org/unitbezier/-/unitbezier-0.0.0.tgz", + "integrity": "sha1-M79/XXKExTUL/Fx/dw+6dUnFSl4=" + }, + "update-diff": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/update-diff/-/update-diff-1.1.0.tgz", + "integrity": "sha1-9RAYLYHugZ+4LDprIrYrve2ngI8=" + }, + "url": { + "version": "0.11.0", + "resolved": "https://registry.npmjs.org/url/-/url-0.11.0.tgz", + "integrity": "sha1-ODjpfPxgUh63PFJajlW/3Z4uKPE=", + "dev": true, + "requires": { + "punycode": "1.3.2", + "querystring": "0.2.0" + }, + "dependencies": { + "punycode": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.3.2.tgz", + "integrity": "sha1-llOgNvt8HuQjQvIyXM7v6jkmxI0=", + "dev": true + } + } + }, + "url-parse": { + "version": "1.1.9", + "resolved": "https://registry.npmjs.org/url-parse/-/url-parse-1.1.9.tgz", + "integrity": "sha1-xn8dd11R8KGJEd17P/rSe7nlvRk=", + "requires": { + "querystringify": "1.0.0", + "requires-port": "1.0.0" + } + }, + "util": { + "version": "0.10.3", + "resolved": "https://registry.npmjs.org/util/-/util-0.10.3.tgz", + "integrity": "sha1-evsa/lCAUkZInj23/g7TeTNqwPk=", + "dev": true, + "requires": { + "inherits": "2.0.1" + }, + "dependencies": { + "inherits": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz", + "integrity": "sha1-sX0I0ya0Qj5Wjv9xn5GwscvfafE=", + "dev": true + } + } + }, + "util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=" + }, + "uuid": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.2.1.tgz", + "integrity": "sha512-jZnMwlb9Iku/O3smGWvZhauCf6cvvpKi4BKRiliS3cxnI+Gz9j5MEpTz2UFuXiKPJocb7gnsLHwiS05ige5BEA==" + }, + "validate-npm-package-license": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.1.tgz", + "integrity": "sha1-KAS6vnEq0zeUWaz74kdGqywwP7w=", + "dev": true, + "requires": { + "spdx-correct": "1.0.2", + "spdx-expression-parse": "1.0.4" + } + }, + "vector-tile": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/vector-tile/-/vector-tile-1.3.0.tgz", + "integrity": "sha1-BtUWqDsGPwTILvU5zxuxrr62lrQ=", + "requires": { + "point-geometry": "0.0.0" + } + }, + "vectorize-text": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/vectorize-text/-/vectorize-text-3.0.2.tgz", + "integrity": "sha1-BasWMOQJ83eWTiuSBbLVWakvYNg=", + "requires": { + "cdt2d": "1.0.0", + "clean-pslg": "1.1.2", + "ndarray": "1.0.18", + "planar-graph-to-polyline": "1.0.5", + "simplify-planar-graph": "2.0.1", + "surface-nets": "1.0.2", + "triangulate-polyline": "1.0.3" + } + }, + "verror": { + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/verror/-/verror-1.10.0.tgz", + "integrity": "sha1-OhBcoXBTr1XW4nDB+CiGguGNpAA=", + "requires": { + "assert-plus": "1.0.0", + "core-util-is": "1.0.2", + "extsprintf": "1.3.0" + } + }, + "vlq": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/vlq/-/vlq-0.2.3.tgz", + "integrity": "sha512-DRibZL6DsNhIgYQ+wNdWDL2SL3bKPlVrRiBqV5yuMm++op8W4kGFtaQfCs4KEJn0wBZcHVHJ3eoywX8983k1ow==" + }, + "vm-browserify": { + "version": "0.0.4", + "resolved": "https://registry.npmjs.org/vm-browserify/-/vm-browserify-0.0.4.tgz", + "integrity": "sha1-XX6kW7755Kb/ZflUOOCofDV9WnM=", + "dev": true, + "requires": { + "indexof": "0.0.1" + } + }, + "vt-pbf": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/vt-pbf/-/vt-pbf-2.1.4.tgz", + "integrity": "sha1-td98P5cGFW4LmIGpncsFY1dAtSI=", + "requires": { + "pbf": "1.3.7", + "point-geometry": "0.0.0", + "vector-tile": "1.3.0" + } + }, + "watchpack": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-1.4.0.tgz", + "integrity": "sha1-ShRyvLuVK9Cpu0A2gB+VTfs5+qw=", + "dev": true, + "requires": { + "async": "2.6.0", + "chokidar": "1.7.0", + "graceful-fs": "4.1.11" + } + }, + "weak-map": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/weak-map/-/weak-map-1.0.5.tgz", + "integrity": "sha1-eWkVhNmGB/UHC9O3CkDmuyLkAes=" + }, + "weakmap-shim": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/weakmap-shim/-/weakmap-shim-1.1.1.tgz", + "integrity": "sha1-1lr9eEEJshZuAP9XHDMVDsKkC0k=" + }, + "webgl-context": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/webgl-context/-/webgl-context-2.2.0.tgz", + "integrity": "sha1-jzfXJXz23xzQpJ5qextyG5TMhqA=", + "requires": { + "get-canvas-context": "1.0.2" + } + }, + "webpack": { + "version": "3.11.0", + "resolved": "https://registry.npmjs.org/webpack/-/webpack-3.11.0.tgz", + "integrity": "sha512-3kOFejWqj5ISpJk4Qj/V7w98h9Vl52wak3CLiw/cDOfbVTq7FeoZ0SdoHHY9PYlHr50ZS42OfvzE2vB4nncKQg==", + "dev": true, + "requires": { + "acorn": "5.4.1", + "acorn-dynamic-import": "2.0.2", + "ajv": "6.1.1", + "ajv-keywords": "3.1.0", + "async": "2.6.0", + "enhanced-resolve": "3.4.1", + "escope": "3.6.0", + "interpret": "1.1.0", + "json-loader": "0.5.7", + "json5": "0.5.1", + "loader-runner": "2.3.0", + "loader-utils": "1.1.0", + "memory-fs": "0.4.1", + "mkdirp": "0.5.1", + "node-libs-browser": "2.1.0", + "source-map": "0.5.7", + "supports-color": "4.5.0", + "tapable": "0.2.8", + "uglifyjs-webpack-plugin": "0.4.6", + "watchpack": "1.4.0", + "webpack-sources": "1.1.0", + "yargs": "8.0.2" + }, + "dependencies": { + "ajv": { + "version": "6.1.1", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.1.1.tgz", + "integrity": "sha1-l41Zf7wrfQ5aXD3esUmmgvKr+g4=", + "dev": true, + "requires": { + "fast-deep-equal": "1.0.0", + "fast-json-stable-stringify": "2.0.0", + "json-schema-traverse": "0.3.1" + } + }, + "camelcase": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-4.1.0.tgz", + "integrity": "sha1-1UVjW+HjPFQmScaRc+Xeas+uNN0=", + "dev": true + }, + "cliui": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-3.2.0.tgz", + "integrity": "sha1-EgYBU3qRbSmUD5NNo7SNWFo5IT0=", + "dev": true, + "requires": { + "string-width": "1.0.2", + "strip-ansi": "3.0.1", + "wrap-ansi": "2.1.0" + }, + "dependencies": { + "string-width": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", + "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", + "dev": true, + "requires": { + "code-point-at": "1.1.0", + "is-fullwidth-code-point": "1.0.0", + "strip-ansi": "3.0.1" + } + } + } + }, + "has-flag": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-2.0.0.tgz", + "integrity": "sha1-6CB68cx7MNRGzHC3NLXovhj4jVE=", + "dev": true + }, + "supports-color": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-4.5.0.tgz", + "integrity": "sha1-vnoN5ITexcXN34s9WRJQRJEvY1s=", + "dev": true, + "requires": { + "has-flag": "2.0.0" + } + }, + "yargs": { + "version": "8.0.2", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-8.0.2.tgz", + "integrity": "sha1-YpmpBVsc78lp/355wdkY3Osiw2A=", + "dev": true, + "requires": { + "camelcase": "4.1.0", + "cliui": "3.2.0", + "decamelize": "1.2.0", + "get-caller-file": "1.0.2", + "os-locale": "2.1.0", + "read-pkg-up": "2.0.0", + "require-directory": "2.1.1", + "require-main-filename": "1.0.1", + "set-blocking": "2.0.0", + "string-width": "2.1.1", + "which-module": "2.0.0", + "y18n": "3.2.1", + "yargs-parser": "7.0.0" + } + } + } + }, + "webpack-sources": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-1.1.0.tgz", + "integrity": "sha512-aqYp18kPphgoO5c/+NaUvEeACtZjMESmDChuD3NBciVpah3XpMEU9VAAtIaB1BsfJWWTSdv8Vv1m3T0aRk2dUw==", + "dev": true, + "requires": { + "source-list-map": "2.0.0", + "source-map": "0.6.1" + }, + "dependencies": { + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + } + } + }, + "webworkify": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/webworkify/-/webworkify-1.5.0.tgz", + "integrity": "sha512-AMcUeyXAhbACL8S2hqqdqOLqvJ8ylmIbNwUIqQujRSouf4+eUFaXbG6F1Rbu+srlJMmxQWsiU7mOJi0nMBfM1g==" + }, + "wgs84": { + "version": "0.0.0", + "resolved": "https://registry.npmjs.org/wgs84/-/wgs84-0.0.0.tgz", + "integrity": "sha1-NP3FVZF7blfPKigu0ENxDASc3HY=" + }, + "which": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/which/-/which-1.3.0.tgz", + "integrity": "sha512-xcJpopdamTuY5duC/KnTTNBraPK54YwpenP4lzxU8H91GudWpFv38u0CKjclE1Wi2EH2EDz5LRcHcKbCIzqGyg==", + "dev": true, + "requires": { + "isexe": "2.0.0" + } + }, + "which-module": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/which-module/-/which-module-2.0.0.tgz", + "integrity": "sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho=", + "dev": true + }, + "whoots-js": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/whoots-js/-/whoots-js-2.1.0.tgz", + "integrity": "sha1-vLIBw04OrzNfzOWuLPh0V5qZxIc=" + }, + "window-size": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/window-size/-/window-size-0.1.0.tgz", + "integrity": "sha1-VDjNLqk7IC76Ohn+iIeu58lPnJ0=" + }, + "wordwrap": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-1.0.0.tgz", + "integrity": "sha1-J1hIEIkUVqQXHI0CJkQa3pDLyus=" + }, + "world-calendars": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/world-calendars/-/world-calendars-1.0.3.tgz", + "integrity": "sha1-slxQMrokEo/8QdCfr0pewbnBQzU=", + "requires": { + "object-assign": "4.1.1" + } + }, + "wrap-ansi": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-2.1.0.tgz", + "integrity": "sha1-2Pw9KE3QV5T+hJc8rs3Rz4JP3YU=", + "dev": true, + "requires": { + "string-width": "1.0.2", + "strip-ansi": "3.0.1" + }, + "dependencies": { + "string-width": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", + "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", + "dev": true, + "requires": { + "code-point-at": "1.1.0", + "is-fullwidth-code-point": "1.0.0", + "strip-ansi": "3.0.1" + } + } + } + }, + "wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=" + }, + "ws": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/ws/-/ws-1.1.5.tgz", + "integrity": "sha512-o3KqipXNUdS7wpQzBHSe180lBGO60SoK0yVo3CYJgb2MkobuWuBX6dhkYP5ORCLd55y+SaflMOV5fqAB53ux4w==", + "requires": { + "options": "0.0.6", + "ultron": "1.0.2" + } + }, + "xtend": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.1.tgz", + "integrity": "sha1-pcbVMr5lbiPbgg77lDofBJmNY68=" + }, + "y18n": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-3.2.1.tgz", + "integrity": "sha1-bRX7qITAhnnA136I53WegR4H+kE=", + "dev": true + }, + "yallist": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-2.1.2.tgz", + "integrity": "sha1-HBH5IY8HYImkfdUS+TxmmaaoHVI=", + "dev": true + }, + "yargs": { + "version": "3.10.0", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-3.10.0.tgz", + "integrity": "sha1-9+572FfdfB0tOMDnTvvWgdFDH9E=", + "requires": { + "camelcase": "1.2.1", + "cliui": "2.1.0", + "decamelize": "1.2.0", + "window-size": "0.1.0" + } + }, + "yargs-parser": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-7.0.0.tgz", + "integrity": "sha1-jQrELxbqVd69MyyvTEA4s+P139k=", + "dev": true, + "requires": { + "camelcase": "4.1.0" + }, + "dependencies": { + "camelcase": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-4.1.0.tgz", + "integrity": "sha1-1UVjW+HjPFQmScaRc+Xeas+uNN0=", + "dev": true + } + } + }, + "zero-crossings": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/zero-crossings/-/zero-crossings-1.0.1.tgz", + "integrity": "sha1-xWK9MRNkPzRDokXRJAa4i2m5qf8=", + "requires": { + "cwise-compiler": "1.1.3" + } + } + } +} diff --git a/js/package.json b/js/package.json new file mode 100644 index 00000000000..32830ac44c7 --- /dev/null +++ b/js/package.json @@ -0,0 +1,41 @@ +{ + "name": "plotlywidget", + "version": "0.1.0", + "description": "The plotly ipywidget library", + "author": "Jon Mease", + "main": "src/index.js", + "repository": { + "type": "git", + "url": "" + }, + "keywords": [ + "jupyter", + "widgets", + "ipython", + "ipywidgets" + ], + "files": [ + "src/**/*.js", + "dist/*.js" + ], + "scripts": { + "clean": "rimraf dist/ && rimraf ../plotlywidget/static", + "build": "webpack", + "prepublish": "npm run clean && npm run build", + "test": "echo \"Error: no test specified\" && exit 1" + }, + "devDependencies": { + "json-loader": "^0.5.4", + "webpack": "^3.5.5", + "rimraf": "^2.6.1", + "ify-loader": "^1.1.0" + }, + "dependencies": { + "plotly.js": "^1.34.0", + "@jupyter-widgets/base": "^1.0.4", + "lodash": "^4.0" + }, + "jupyterlab": { + "extension": "src/jupyterlab-plugin" + } +} diff --git a/js/src/Figure.js b/js/src/Figure.js new file mode 100644 index 00000000000..ab852925cee --- /dev/null +++ b/js/src/Figure.js @@ -0,0 +1,1228 @@ +var widgets = require('@jupyter-widgets/base'); +var _ = require('lodash'); +var Plotly = require('plotly.js'); + + +// Models +// ====== +var FigureModel = widgets.DOMWidgetModel.extend({ + + defaults: _.extend(widgets.DOMWidgetModel.prototype.defaults(), { + _model_name: 'FigureModel', + _view_name: 'FigureView', + _model_module: 'plotlywidget', + _view_module: 'plotlywidget', + + _data: [], + _layout: {}, // Not synced to python side + + // Message properties + _py2js_addTraces: null, + _py2js_deleteTraces: null, + _py2js_moveTraces: null, + _py2js_restyle: null, + _py2js_relayout: null, + _py2js_update: null, + _py2js_animate: null, + + _py2js_removeLayoutProps: null, + _py2js_removeStyleProps: null, + + _py2js_requestSvg: null, + + // JS -> Python + _js2py_restyle: null, + _js2py_relayout: null, + _js2py_update: null, + + _js2py_layoutDelta: null, + _js2py_tracesDelta: null, + + // callbacks + _js2py_pointsCallback: null, + + // svg + _js2py_svg: null, + + // message tracking + _last_relayout_msg_id: 0, + _last_restyle_msg_id: 0 + }), + + initialize: function() { + FigureModel.__super__.initialize.apply(this, arguments); + console.log(['FigureModel: initialize', this._data, this._layout]); + + this.on('change:_py2js_addTraces', this.do_addTraces, this); + this.on('change:_py2js_deleteTraces', this.do_deleteTraces, this); + this.on('change:_py2js_moveTraces', this.do_moveTraces, this); + this.on("change:_py2js_restyle", this.do_restyle, this); + this.on("change:_py2js_relayout", this.do_relayout, this); + this.on("change:_py2js_update", this.do_update, this); + this.on("change:_py2js_animate", this.do_animate, this); + this.on("change:_py2js_removeLayoutProps", this.do_removeLayoutProps, this); + this.on("change:_py2js_removeStyleProps", this.do_removeStyleProps, this); + }, + + _str_to_dict_path: function (rawKey) { + + // Split string on periods. e.g. 'foo.bar[0]' -> ['foo', 'bar[0]'] + var keyPath = rawKey.split('.'); + var regex = /(.*)\[(\d+)\]/; + + // Split out bracket indexes. e.g. ['foo', 'bar[0]'] -> ['foo', 'bar', '0'] + var keyPath2 = []; + for (var k = 0; k < keyPath.length; k++) { + var key = keyPath[k]; + var match = regex.exec(key); + if (match === null) { + keyPath2.push(key); + } else { + keyPath2.push(match[1]); + keyPath2.push(match[2]); + } + } + + // Convert elements to ints if possible. e.g. e.g. ['foo', 'bar', '0'] -> ['foo', 'bar', 0] + for (k = 0; k < keyPath2.length; k++) { + key = keyPath2[k]; + var potentialInt = parseInt(key); + if (!isNaN(potentialInt)) { + keyPath2[k] = potentialInt; + } + } + return keyPath2 + }, + + normalize_trace_indexes: function (trace_indexes) { + if (trace_indexes === null || trace_indexes === undefined) { + var numTraces = this.get('_data').length; + trace_indexes = Array.apply(null, new Array(numTraces)).map(function (_, i) {return i;}); + } + if (!Array.isArray(trace_indexes)) { + // Make sure idx is an array + trace_indexes = [trace_indexes]; + } + return trace_indexes + }, + + + do_addTraces: function () { + // add trace to plot + console.log('Figure Model: do_addTraces'); + var data = this.get('_py2js_addTraces'); + + if (data !== null) { + console.log(data); + var tracesData = this.get('_data'); + _.forEach(data, function (traceData) { + tracesData.push(traceData); + }) + } + }, + + do_deleteTraces: function () { + // add trace to plot + var data = this.get('_py2js_deleteTraces'); + console.log('Figure Model: do_deleteTraces'); + if (data !== null) { + var delete_inds = data['delete_inds']; + var tracesData = this.get('_data'); + + // Remove del inds in reverse order so indexes remain valid throughout loop + delete_inds.slice().reverse().forEach(function (del_ind) { + tracesData.splice(del_ind, 1); + }); + } + }, + + do_moveTraces: function () { + console.log('Figure Model: do_moveTraces'); + + var move_data = this.get('_py2js_moveTraces'); + console.log('do_moveTraces'); + + if (move_data !== null) { + var currentInds = move_data[0]; + var newInds = move_data[1]; + var tracesData = this.get('_data'); + + // ### Remove by curr_inds in reverse order ### + var movingTracesData = []; + for (var ci = currentInds.length - 1; ci >= 0; ci--) { + // Insert moving tracesData at beginning of the list + movingTracesData.splice(0, 0, tracesData[currentInds[ci]]); + tracesData.splice(currentInds[ci], 1); + } + + // ### Sort newInds and movingTracesData by newInds ### + var newIndexSortedArrays = _(newInds).zip(movingTracesData) + .sortBy(0) + .unzip() + .value(); + + newInds = newIndexSortedArrays[0]; + movingTracesData = newIndexSortedArrays[1]; + + // ### Insert by newInds in forward order ### + for (var ni = 0; ni < newInds.length; ni++) { + tracesData.splice(newInds[ni], 0, movingTracesData[ni]); + } + } + }, + + do_restyle: function () { + console.log('FigureModel: do_restyle'); + var data = this.get('_py2js_restyle'); + if (data !== null) { + var style = data[0]; + var trace_indexes = this.normalize_trace_indexes(data[1]); + this._performRestyle(style, trace_indexes) + } + }, + + _performRestyle: function (style, trace_indexes){ + + for (var rawKey in style) { + if (!style.hasOwnProperty(rawKey)) { continue } + var v = style[rawKey]; + + if (!Array.isArray(v)) { + v = [v] + } + + var keyPath = this._str_to_dict_path(rawKey); + + for (var i = 0; i < trace_indexes.length; i++) { + var trace_ind = trace_indexes[i]; + var valParent = this.get('_data')[trace_ind]; + + for (var kp = 0; kp < keyPath.length-1; kp++) { + var keyPathEl = keyPath[kp]; + + // Extend val_parent list if needed + if (Array.isArray(valParent)) { + if (typeof keyPathEl === 'number') { + while (valParent.length <= keyPathEl) { + valParent.push(null) + } + } + } else { // object + // Initialize child if needed + if (valParent[keyPathEl] === undefined) { + if (typeof keyPath[kp + 1] === 'number') { + valParent[keyPathEl] = [] + } else { + valParent[keyPathEl] = {} + } + } + } + valParent = valParent[keyPathEl]; + } + + var lastKey = keyPath[keyPath.length-1]; + var trace_v = v[i % v.length]; + + if (trace_v === undefined) { + // Nothing to do + } else if (trace_v === null){ + if(valParent.hasOwnProperty(lastKey)) { + delete valParent[lastKey]; + } + } else { + if (Array.isArray(valParent) && typeof lastKey === 'number') { + while (valParent.length <= lastKey) { + // Make sure array is long enough to assign into + valParent.push(null) + } + } + valParent[lastKey] = trace_v; + } + } + } + }, + + do_relayout: function () { + console.log('FigureModel: do_relayout'); + var data = this.get('_py2js_relayout'); + if (data !== null) { + console.log(data); + this._performRelayout(data); + console.log(this.get('_layout')) + } + }, + + _performRelayout: function (relayout_data) { + this._performRelayoutLike(relayout_data, this.get('_layout')) + }, + + _performRelayoutLike: function (relayout_data, parent_data) { + // Perform a relayout style operation on a given parent object + for (var rawKey in relayout_data) { + if (!relayout_data.hasOwnProperty(rawKey)) { + continue + } + + var v = relayout_data[rawKey]; + var keyPath = this._str_to_dict_path(rawKey); + + var valParent = parent_data; + + for (var kp = 0; kp < keyPath.length-1; kp++) { + var keyPathEl = keyPath[kp]; + + // Extend val_parent list if needed + if (Array.isArray(valParent)) { + if(typeof keyPathEl === 'number') { + while (valParent.length <= keyPathEl) { + valParent.push(null) + } + } + } else { + // Initialize child if needed + if (valParent[keyPathEl] === undefined) { + if (typeof keyPath[kp + 1] === 'number') { + valParent[keyPathEl] = [] + } else { + valParent[keyPathEl] = {} + } + } + } + valParent = valParent[keyPathEl]; + } + + var lastKey = keyPath[keyPath.length-1]; + + if (v === undefined) { + // Nothing to do + } else if (v === null){ + if(valParent.hasOwnProperty(lastKey)) { + delete valParent[lastKey]; + } + } else { + if (Array.isArray(valParent) && typeof lastKey === 'number') { + while (valParent.length <= lastKey) { + // Make sure array is long enough to assign into + valParent.push(null) + } + } + valParent[lastKey] = v; + } + } + }, + + do_update: function() { + console.log('FigureModel: do_update'); + var data = this.get('_py2js_update'); + if (data !== null) { + console.log(data); + + var style = data[0]; + var layout = data[1]; + var trace_indexes = this.normalize_trace_indexes(data[2]); + this._performRestyle(style, trace_indexes); + this._performRelayout(layout); + } + }, + + do_animate: function () { + console.log('FigureModel: do_animate'); + var data = this.get('_py2js_animate'); + if (data !== null) { + console.log(data); + var animationData = data[0]; + + var styles = animationData['data']; + var layout = animationData['layout']; + var trace_indexes = this.normalize_trace_indexes(animationData['traces']); + + for (var i = 0; i < styles.length; i++) { + var style = styles[i]; + var trace_index = trace_indexes[i]; + var trace = this.get('_data')[trace_index]; + this._performRelayoutLike(style, trace); + } + + this._performRelayout(layout); + } + }, + + // ### Remove props ### + do_removeLayoutProps: function () { + console.log('FigureModel:do_removeLayoutProps'); + var data = this.get('_py2js_removeLayoutProps'); + if (data !== null) { + console.log(this.get('_layout')); + for(var i=0; i < data.length; i++) { + + var keyPath = data[i]; + var valParent = this.get('_layout'); + + for (var kp = 0; kp < keyPath.length - 1; kp++) { + var keyPathEl = keyPath[kp]; + if (valParent[keyPathEl] === undefined) { + valParent = null; + break + } + valParent = valParent[keyPathEl]; + } + if (valParent !== null) { + var lastKey = keyPath[keyPath.length - 1]; + if (valParent.hasOwnProperty(lastKey)) { + delete valParent[lastKey]; + console.log('Removed ' + keyPath) + } + } + } + console.log(this.get('_layout')); + } + }, + + do_removeStyleProps: function () { + console.log('FigureModel:do_removeStyleProps'); + var data = this.get('_py2js_removeStyleProps'); + if (data !== null) { + console.log(data); + var keyPaths = data[0]; + var trace_indexes = this.normalize_trace_indexes(data[1]); + + for(var k=0; k < keyPaths.length; k++) { + + var keyPath = keyPaths[k]; + + for (var i = 0; i < trace_indexes.length; i++) { + var trace_ind = trace_indexes[i]; + var valParent = this.get('_data')[trace_ind]; + + for (var kp = 0; kp < keyPath.length - 1; kp++) { + var keyPathEl = keyPath[kp]; + if (valParent[keyPathEl] === undefined) { + valParent = null; + break + } + valParent = valParent[keyPathEl]; + } + if (valParent !== null) { + var lastKey = keyPath[keyPath.length - 1]; + if (valParent.hasOwnProperty(lastKey)) { + delete valParent[lastKey]; + console.log('Removed ' + keyPath) + } + } + } + } + } + } +}, { + serializers: _.extend({ + _data: { deserialize: py2js_serializer, serialize: js2py_serializer}, + _layout: { deserialize: py2js_serializer, serialize: js2py_serializer}, + _py2js_addTraces: { deserialize: py2js_serializer, serialize: js2py_serializer}, + _py2js_deleteTraces: { deserialize: py2js_serializer, serialize: js2py_serializer}, + _py2js_moveTraces: { deserialize: py2js_serializer, serialize: js2py_serializer}, + _py2js_restyle: { deserialize: py2js_serializer, serialize: js2py_serializer}, + _py2js_relayout: { deserialize: py2js_serializer, serialize: js2py_serializer}, + _py2js_update: { deserialize: py2js_serializer, serialize: js2py_serializer}, + _py2js_animate: { deserialize: py2js_serializer, serialize: js2py_serializer}, + _py2js_removeLayoutProps: { deserialize: py2js_serializer, serialize: js2py_serializer}, + _py2js_removeStyleProps: { deserialize: py2js_serializer, serialize: js2py_serializer}, + _js2py_restyle: { deserialize: py2js_serializer, serialize: js2py_serializer}, + _js2py_relayout: { deserialize: py2js_serializer, serialize: js2py_serializer}, + _js2py_update: { deserialize: py2js_serializer, serialize: js2py_serializer}, + _js2py_layoutDelta: { deserialize: py2js_serializer, serialize: js2py_serializer}, + _js2py_tracesDelta: { deserialize: py2js_serializer, serialize: js2py_serializer}, + _js2py_pointsCallback: { deserialize: py2js_serializer, serialize: js2py_serializer}, + }, widgets.DOMWidgetModel.serializers) +}); + +var numpy_dtype_to_typedarray_type = { + int8: Int8Array, + int16: Int16Array, + int32: Int32Array, + uint8: Uint8Array, + uint16: Uint16Array, + uint32: Uint32Array, + float32: Float32Array, + float64: Float64Array +}; + +function js2py_serializer(v, widgetManager) { + var res; + if (Array.isArray(v)) { + res = new Array(v.length); + for (var i = 0; i < v.length; i++) { + res[i] = js2py_serializer(v[i]); + } + } else if (_.isPlainObject(v)) { + res = {}; + for (var p in v) { + if (v.hasOwnProperty(p)) { + res[p] = js2py_serializer(v[p]); + } + } + } else if (v === undefined) { + res = '_undefined_'; + } else { + res = v; + } + return res +} + +function py2js_serializer(v, widgetManager) { + var res; + if (Array.isArray(v)) { + res = new Array(v.length); + for (var i = 0; i < v.length; i++) { + res[i] = py2js_serializer(v[i]); + } + } else if (_.isPlainObject(v)) { + if (_.has(v, 'buffer') && _.has(v, 'dtype') && _.has(v, 'shape')) { + var typedarray_type = numpy_dtype_to_typedarray_type[v.dtype]; + var typedarray = new typedarray_type(v.buffer.buffer); + res = Array.from(typedarray); + } else { + res = {}; + for (var p in v) { + if (v.hasOwnProperty(p)) { + res[p] = py2js_serializer(v[p]); + } + } + } + } else if (v === '_undefined_') { + res = undefined; + } else { + res = v; + } + return res +} + +// Figure View +// =========== +var FigureView = widgets.DOMWidgetView.extend({ + + render: function() { + + var that = this; + + // Wire up property callbacks + // -------------------------- + // Python -> JS event properties + this.model.on('change:_py2js_addTraces', this.do_addTraces, this); + this.model.on('change:_py2js_deleteTraces', this.do_deleteTraces, this); + this.model.on('change:_py2js_moveTraces', this.do_moveTraces, this); + this.model.on('change:_py2js_restyle', this.do_restyle, this); + this.model.on("change:_py2js_relayout", this.do_relayout, this); + this.model.on("change:_py2js_update", this.do_update, this); + this.model.on("change:_py2js_animate", this.do_animate, this); + this.model.on("change:_py2js_requestSvg", this.do_requestSvg, this); + + // Increment message ids + // --------------------- + var relayout_msg_id = this.model.get('_last_relayout_msg_id') + 1; + this.model.set('_last_relayout_msg_id', relayout_msg_id); + var restyle_msg_id = this.model.get('_last_restyle_msg_id') + 1; + this.model.set('_last_restyle_msg_id', restyle_msg_id); + this.touch(); + + // Set view UID + // ------------ + this.viewID = randstr(); + console.log('Created view with id: ' + this.viewID); + + // Initialize figure + // ----------------- + console.log('render'); + console.log(this.model.get('_data')); + console.log(this.model.get('_layout')); + + // Clone traces and layout so plotly instances in the views don't mutate the model + var initial_traces = JSON.parse(JSON.stringify(this.model.get('_data'))); + var initial_layout = JSON.parse(JSON.stringify(this.model.get('_layout'))); + + Plotly.newPlot(this.el, initial_traces, initial_layout).then(function () { + + // Update layout + var relayoutDelta = that.create_delta_object(that.model.get('_layout'), that.getFullLayout()); + relayoutDelta['_relayout_msg_id'] = relayout_msg_id; + that.model.set('_js2py_layoutDelta', relayoutDelta); + + // Update traces + // Loop over new traces + var traceDeltas = new Array(initial_traces.length); + var fullData = that.getFullData(); + for(var i=0; i < initial_traces.length; i++) { + var fullTraceData = fullData[i]; + var traceData = initial_traces[i]; + traceDeltas[i] = that.create_delta_object(traceData, fullTraceData); + traceDeltas[i]['_restyle_msg_id'] = restyle_msg_id; + } + + console.log(traceDeltas); + that.model.set('_js2py_styleDelta', traceDeltas); + + // sync any/all changes back to model + that.touch(); + + // Wire up plotly event callbacks + that.el.on('plotly_restyle', function(update) {that.handle_plotly_restyle(update)}); + that.el.on('plotly_relayout', function(update) {that.handle_plotly_relayout(update)}); + that.el.on('plotly_update', function(update) {that.handle_plotly_update(update)}); + + that.el.on('plotly_click', function(update) {that.handle_plotly_click(update)}); + that.el.on('plotly_hover', function(update) {that.handle_plotly_hover(update)}); + that.el.on('plotly_unhover', function(update) {that.handle_plotly_unhover(update)}); + that.el.on('plotly_selected', function(update) {that.handle_plotly_selected(update)}); + that.el.on('plotly_doubleclick', function(update) {that.handle_plotly_doubleclick(update)}); + that.el.on('plotly_afterplot', function(update) {that.handle_plotly_afterplot(update)}); + }); + }, + destroy: function() { + Plotly.purge(this.el); + }, + getFullData: function () { + // Merge so that we use .data properties if available. + // e.g. colorscales can be stored by name in this.el.data (Viridis) but by array in el._fullData. We want + // the string in this case + return _.merge(this.el._fullData, this.el.data); + }, + + getFullLayout: function () { + return _.merge(this.el._fullLayout, this.el.layout); + }, + + buildPointsObject: function (data) { + + var pointsObject; + if (data.hasOwnProperty('points')) { + // Most cartesian plots + var pointObjects = data['points']; + var numPoints = pointObjects.length; + pointsObject = { + 'curveNumbers': new Array(numPoints), + 'pointNumbers': new Array(numPoints), + 'xs': new Array(numPoints), + 'ys': new Array(numPoints)}; + + + for (var p = 0; p < numPoints; p++) { + pointsObject['curveNumbers'][p] = pointObjects[p]['curveNumber']; + pointsObject['pointNumbers'][p] = pointObjects[p]['pointNumber']; + pointsObject['xs'][p] = pointObjects[p]['x']; + pointsObject['ys'][p] = pointObjects[p]['y']; + } + + // Add z if present + var hasZ = pointObjects[0] !== undefined && pointObjects[0].hasOwnProperty('z'); + if (hasZ) { + pointsObject['zs'] = new Array(numPoints); + for (p = 0; p < numPoints; p++) { + pointsObject['zs'][p] = pointObjects[p]['z']; + } + } + + return pointsObject + } else { + return null + } + }, + + buildMouseEventObject: function (data) { + var event = data['event']; + if (event === undefined) { + return {} + } else { + var mouseEventObject = { + // Keyboard modifiers + 'alt': event['altKey'], + 'ctrl': event['ctrlKey'], + 'meta': event['metaKey'], + 'shift': event['shiftKey'], + + // Mouse buttons + 'button': event['button'], + // Indicates which button was pressed on the mouse to trigger the event. + // 0: Main button pressed, usually the left button or the un-initialized state + // 1: Auxiliary button pressed, usually the wheel button or the middle button (if present) + // 2: Secondary button pressed, usually the right button + // 3: Fourth button, typically the Browser Back button + // 4: Fifth button, typically the Browser Forward button + 'buttons': event['buttons'] + // Indicates which buttons are pressed on the mouse when the event is triggered. + // 0 : No button or un-initialized + // 1 : Primary button (usually left) + // 2 : Secondary button (usually right) + // 4 : Auxilary button (usually middle or mouse wheel button) + // 8 : 4th button (typically the "Browser Back" button) + // 16 : 5th button (typically the "Browser Forward" button) + }; + return mouseEventObject + } + }, + + buildSelectorObject: function(data) { + var selectorObject = {}; + + // Test for box select + if (data.hasOwnProperty('range')) { + selectorObject['type'] = 'box'; + selectorObject['xrange'] = data['range']['x']; + selectorObject['yrange'] = data['range']['y']; + } else if (data.hasOwnProperty('lassoPoints')) { + selectorObject['type'] = 'lasso'; + selectorObject['xs'] = data['lassoPoints']['x']; + selectorObject['ys'] = data['lassoPoints']['y']; + } + return selectorObject + }, + + handle_plotly_restyle: function (data) { + if (data !== null && data !== undefined && data[0].hasOwnProperty('_doNotReportToPy')) { + // Restyle originated on the Python side + return + } + + // Work around some plotly bugs/limitations + if (data === null || data === undefined) { + + data = new Array(this.el.data.length); + + for (var t = 0; t < this.el.data.length; t++) { + var traceData = this.el.data[t]; + data[t] = {'uid': traceData['uid']}; + if (traceData['type'] === 'parcoords') { + + // Parallel coordinate diagram 'constraintrange' property not provided + for (var d = 0; d < traceData.dimensions.length; d++) { + var constraintrange = traceData.dimensions[d]['constraintrange']; + if (constraintrange !== undefined) { + data[t]['dimensions[' + d + '].constraintrange'] = [constraintrange]; + } + } + } + } + } + + // Add viewID to style + data[0]['_view_id'] = this.viewID; + + // Log message + console.log("plotly_restyle"); + console.log(data); + + this.model.set('_js2py_restyle', data); + this.touch(); + }, + + handle_plotly_relayout: function (data) { + if (data !== null && data !== undefined && data.hasOwnProperty('_doNotReportToPy')) { + // Relayout originated on the Python side + return + } + + // Work around some plotly bugs/limitations + + // Sometimes (in scatterGL at least) axis range isn't wrapped in range + if ('xaxis' in data && Array.isArray(data['xaxis'])) { + data['xaxis'] = {'range': data['xaxis']} + } + + if ('yaxis' in data && Array.isArray(data['yaxis'])) { + data['yaxis'] = {'range': data['yaxis']} + } + + // Add viewID + data['_view_id'] = this.viewID; + + // Log message + console.log("plotly_relayout"); + console.log(data); + + this.model.set('_js2py_relayout', data); + this.touch(); + }, + + handle_plotly_update: function (data) { + if (data !== null && data !== undefined && + data['data'][0].hasOwnProperty('_doNotReportToPy')) { + // Update originated on the Python side + return + } + + // Add viewID to style element + data['data'][0]['_view_id'] = this.viewID; + + // Log message + console.log("plotly_update"); + console.log(data); + + this.model.set('_js2py_update', data); + this.touch(); + }, + + handle_plotly_click: function (data) { + console.log("plotly_click"); + + if (data === null || data === undefined) return; + + var pyData = { + 'event_type': 'plotly_click', + 'points': this.buildPointsObject(data), + 'state': this.buildMouseEventObject(data) + }; + + if (pyData['points'] !== null) { + console.log(data); + console.log(pyData); + this.model.set('_js2py_pointsCallback', pyData); + this.touch(); + } + }, + + handle_plotly_hover: function (data) { + console.log("plotly_hover"); + + if (data === null || data === undefined) return; + + var pyData = { + 'event_type': 'plotly_hover', + 'points': this.buildPointsObject(data), + 'state': this.buildMouseEventObject(data) + }; + + if (pyData['points'] !== null && pyData['points'] !== undefined) { + console.log(data); + console.log(pyData); + this.model.set('_js2py_pointsCallback', pyData); + this.touch(); + } + }, + + handle_plotly_unhover: function (data) { + console.log("plotly_unhover"); + + if (data === null || data === undefined) return; + + var pyData = { + 'event_type': 'plotly_unhover', + 'points': this.buildPointsObject(data), + 'state': this.buildMouseEventObject(data) + }; + + if (pyData['points'] !== null) { + console.log(data); + console.log(pyData); + this.model.set('_js2py_pointsCallback', pyData); + this.touch(); + } + }, + + handle_plotly_selected: function (data) { + console.log("plotly_selected"); + + if (data === null || + data === undefined) return; + + var pyData = { + 'event_type': 'plotly_selected', + 'points': this.buildPointsObject(data), + 'selector': this.buildSelectorObject(data), + }; + + if (pyData['points'] !== null) { + console.log(data); + console.log(pyData); + this.model.set('_js2py_pointsCallback', pyData); + this.touch(); + } + }, + + handle_plotly_doubleclick: function (data) { + // console.log("plotly_doubleclick"); + // console.log(data); + }, + + handle_plotly_afterplot: function (data) { + // console.log("plotly_afterplot"); + // console.log(data); + }, + + do_addTraces: function () { + // add trace to plot + + var data = this.model.get('_py2js_addTraces'); + console.log('Figure View: do_addTraces'); + + if (data !== null) { + console.log(data); + var prev_num_traces = this.el.data.length; + + // console.log(data); + var that = this; + Plotly.addTraces(this.el, data).then(function () { + // Loop over new traces + var traceDeltas = new Array(data.length); + var tracesData = that.model.get('_data'); + var fullData = that.getFullData(); + var restyle_msg_id = data[0]['_restyle_msg_id']; + var relayout_msg_id = data[0]['_relayout_msg_id']; + console.log('relayout_msg_id: ' + relayout_msg_id); + for(var i=0; i < data.length; i++) { + var fullTraceData = fullData[i + prev_num_traces]; + var traceData = tracesData[i + prev_num_traces]; + traceDeltas[i] = that.create_delta_object(traceData, fullTraceData); + traceDeltas[i]['_restyle_msg_id'] = restyle_msg_id; + } + + that.model.set('_js2py_styleDelta', traceDeltas); + + + // Update layout + var layoutDelta = that.create_delta_object(that.model.get('_layout'), that.getFullLayout()); + layoutDelta['_relayout_msg_id'] = relayout_msg_id; + that.model.set('_js2py_layoutDelta', layoutDelta); + console.log(layoutDelta); + + that.touch(); + }); + } + }, + + do_deleteTraces: function () { + var data = this.model.get('_py2js_deleteTraces'); + console.log('do_deleteTraces'); + if (data !== null){ + var delete_inds = data['delete_inds']; + var relayout_msg_id = data['_relayout_msg_id']; + + console.log(delete_inds); + var that = this; + Plotly.deleteTraces(this.el, delete_inds).then(function () { + // Send back layout delta + var relayoutDelta = that.create_delta_object(that.model.get('_layout'), that.getFullLayout()); + relayoutDelta['_relayout_msg_id'] = relayout_msg_id; + that.model.set('_js2py_layoutDelta', relayoutDelta); + that.touch(); + }); + } + }, + + do_moveTraces: function () { + var move_data = this.model.get('_py2js_moveTraces'); + console.log('do_moveTraces'); + + if (move_data !== null){ + var current_inds = move_data[0]; + var new_inds = move_data[1]; + + var inds_equal = current_inds.length===new_inds.length && + current_inds.every(function(v,i) { return v === new_inds[i]}); + + if (!inds_equal) { + console.log(current_inds + "->" + new_inds); + Plotly.moveTraces(this.el, current_inds, new_inds) + } + } + }, + + do_restyle: function () { + console.log('do_restyle'); + var data = this.model.get('_py2js_restyle'); + console.log(data); + if (data !== null) { + var style = data[0]; + var trace_indexes = this.model.normalize_trace_indexes(data[1]); + + if (style['_view_id'] === this.viewID) { + // Operation originated from this view, don't re-apply it + console.log('Skipping restyle for view ' + this.viewID); + return + } else { + console.log('Applying restyle for view ' + this.viewID) + } + + style['_doNotReportToPy'] = true; + Plotly.restyle(this.el, style, trace_indexes); + + // uid + var restyle_msg_id = style['_restyle_msg_id']; + + // Send back style delta + var traceDeltas = new Array(trace_indexes.length); + var trace_data = this.model.get('_data'); + var fullData = this.getFullData(); + for (var i = 0; i < trace_indexes.length; i++) { + traceDeltas[i] = this.create_delta_object(trace_data[trace_indexes[i]], fullData[trace_indexes[i]]); + traceDeltas[i]['_restyle_msg_id'] = restyle_msg_id; + } + + this.model.set('_js2py_styleDelta', traceDeltas); + + // Send back layout delta + var relayout_msg_id = style['_relayout_msg_id']; + var relayoutDelta = this.create_delta_object(this.model.get('_layout'), this.getFullLayout()); + relayoutDelta['_relayout_msg_id'] = relayout_msg_id; + this.model.set('_js2py_layoutDelta', relayoutDelta); + + this.touch(); + } + }, + + do_relayout: function () { + console.log('FigureView: do_relayout'); + var data = this.model.get('_py2js_relayout'); + if (data !== null) { + + if (data['_view_id'] === this.viewID) { + // Operation originated from this view, don't re-apply it + console.log('Skipping relayout for view ' + this.viewID) + return + } else { + console.log('Applying relayout for view ' + this.viewID) + } + + data['_doNotReportToPy'] = true; + Plotly.relayout(this.el, data); + + var layoutDelta = this.create_delta_object(this.model.get('_layout'), this.getFullLayout()); + + // Add message id + layoutDelta['_relayout_msg_id'] = data['_relayout_msg_id']; + + console.log(layoutDelta); + console.log(this.model.get('_layout')); + this.model.set('_js2py_layoutDelta', layoutDelta); + + this.touch(); + } + }, + + do_update: function () { + console.log('FigureView: do_update'); + var data = this.model.get('_py2js_update'); + if (data !== null) { + var style = data[0]; + var layout = data[1]; + var trace_indexes = this.model.normalize_trace_indexes(data[2]); + + if (style['_view_id'] === this.viewID) { + // Operation originated from this view, don't re-apply it + console.log('Skipping update for view ' + this.viewID); + return + } else { + console.log('Applying update for view ' + this.viewID) + } + + style['_doNotReportToPy'] = true; + Plotly.update(this.el, style, layout, trace_indexes); + + // Message ids + var restyle_msg_id = style['_restyle_msg_id']; + var relayout_msg_id = layout['_relayout_msg_id']; + + // Send back style delta + var traceDeltas = new Array(trace_indexes.length); + var trace_data = this.model.get('_data'); + var fullData = this.getFullData(); + for (var i = 0; i < trace_indexes.length; i++) { + traceDeltas[i] = this.create_delta_object(trace_data[trace_indexes[i]], fullData[trace_indexes[i]]); + traceDeltas[i]['_restyle_msg_id'] = restyle_msg_id; + } + + this.model.set('_js2py_styleDelta', traceDeltas); + + // Send back layout delta + var relayoutDelta = this.create_delta_object(this.model.get('_layout'), this.getFullLayout()); + relayoutDelta['_relayout_msg_id'] = relayout_msg_id; + this.model.set('_js2py_layoutDelta', relayoutDelta); + + this.touch(); + } + }, + + do_animate: function() { + console.log('FigureView: do_animate'); + var data = this.model.get('_py2js_animate'); + if (data !== null) { + + // Unpack params + var animationData = data[0]; + var animationOpts = data[1]; + + var styles = animationData['data']; + var layout = animationData['layout']; + var trace_indexes = this.model.normalize_trace_indexes(animationData['traces']); + + animationData['_doNotReportToPy'] = true; + var that = this; + Plotly.animate(this.el, animationData, animationOpts).then(function () { + // Send back style delta + var traceDeltas = new Array(trace_indexes.length); + var trace_data = that.model.get('_data'); + var fullData = that.getFullData(); + for (var i = 0; i < trace_indexes.length; i++) { + var restyle_msg_id = styles[i]['_restyle_msg_id']; + traceDeltas[i] = that.create_delta_object(trace_data[trace_indexes[i]], fullData[trace_indexes[i]]); + traceDeltas[i]['_restyle_msg_id'] = restyle_msg_id; + } + + that.model.set('_js2py_styleDelta', traceDeltas); + + // Send back layout delta + var relayout_msg_id = layout['_relayout_msg_id']; + var relayoutDelta = that.create_delta_object(that.model.get('_layout'), that.getFullLayout()); + relayoutDelta['_relayout_msg_id'] = relayout_msg_id; + that.model.set('_js2py_layoutDelta', relayoutDelta); + + that.touch(); + }); + } + }, + + do_requestSvg: function() { + console.log('FigureView: do_requestSvg'); + var req_id = this.model.get('_py2js_requestSvg'); + var that = this; + if (req_id !== null) { + Plotly.toImage(this.el, {format:'svg'}).then(function (svg_uri) { + console.log([req_id, svg_uri]); + + that.send({event: 'svg', req_id: req_id, svg_uri: svg_uri}); + + // that.model.set('_js2py_svg', [req_id, svg_uri]); + // that.touch(); + }); + } + }, + + clone_fullLayout_data: function (fullLayout) { + var fullStr = JSON.stringify(fullLayout, function(k, v) { + if (k.length > 0 && k[0] === '_') { + return undefined + } + return v + }); + return JSON.parse(fullStr) + }, + + clone_fullData_metadata: function (fullData) { + var fullStr = JSON.stringify(fullData, function(k, v) { + if (k.length > 0 && k[0] === '_') { + return undefined + } else if (Array.isArray(v)) { + // For performance, we don't clone arrays + return undefined + } + return v + }); + return JSON.parse(fullStr) + }, + + create_delta_object: function(data, fullData) { + var res; + if(Array.isArray(fullData)) { + res = new Array(fullData.length); + } else { + res = {}; + } + + if (data === null || data === undefined) { + data = {}; + } + for (var p in fullData) { + if (p[0] !== '_' && fullData.hasOwnProperty(p) && fullData[p] !== null) { + + var props_equal; + if (data.hasOwnProperty(p) && Array.isArray(data[p]) && Array.isArray(fullData[p])) { + props_equal = JSON.stringify(data[p]) === JSON.stringify(fullData[p]); + } else if (data.hasOwnProperty(p)) { + props_equal = data[p] === fullData[p]; + } else { + props_equal = false; + } + + if (!props_equal || p === 'uid') { // Let uids through + // property has non-null value in fullData that doesn't match the value in + var full_val = fullData[p]; + if (data.hasOwnProperty(p) && typeof full_val === 'object') { + if(Array.isArray(full_val)) { + + if (full_val.length > 0 && typeof(full_val[0]) === 'object') { + // We have an object array + res[p] = new Array(full_val.length); + for (var i = 0; i < full_val.length; i++) { + if (!Array.isArray(data[p]) || data[p].length <= i) { + res[p][i] = full_val[i] + } else { + res[p][i] = this.create_delta_object(data[p][i], full_val[i]); + } + } + } else { + // We have a primitive array + res[p] = full_val; + } + } else { // object + var full_obj = this.create_delta_object(data[p], full_val); + if (Object.keys(full_obj).length > 0) { + // new object is not empty + res[p] = full_obj; + } + } + } else if (typeof full_val === 'object' && !Array.isArray(full_val)) { + res[p] = this.create_delta_object({}, full_val); + + } else if (full_val !== undefined) { + res[p] = full_val; + } + } + } + } + return res + } +}); + +// Copied from Plotly src/lib/index.js (How can we call it?) +// random string generator +function randstr(existing, bits, base) { + /* + * Include number of bits, the base of the string you want + * and an optional array of existing strings to avoid. + */ + if(!base) base = 16; + if(bits === undefined) bits = 24; + if(bits <= 0) return '0'; + + var digits = Math.log(Math.pow(2, bits)) / Math.log(base), + res = '', + i, + b, + x; + + for(i = 2; digits === Infinity; i *= 2) { + digits = Math.log(Math.pow(2, bits / i)) / Math.log(base) * i; + } + + var rem = digits - Math.floor(digits); + + for(i = 0; i < Math.floor(digits); i++) { + x = Math.floor(Math.random() * base).toString(base); + res = x + res; + } + + if(rem) { + b = Math.pow(base, rem); + x = Math.floor(Math.random() * b).toString(base); + res = x + res; + } + + var parsed = parseInt(res, base); + if((existing && (existing.indexOf(res) > -1)) || + (parsed !== Infinity && parsed >= Math.pow(2, bits))) { + return randstr(existing, bits, base); + } + else return res; +}; + +module.exports = { + FigureView : FigureView, + FigureModel: FigureModel, +}; diff --git a/js/src/embed.js b/js/src/embed.js new file mode 100644 index 00000000000..85bc6308ad7 --- /dev/null +++ b/js/src/embed.js @@ -0,0 +1,9 @@ +// Entry point for the unpkg bundle containing custom model definitions. +// +// It differs from the notebook bundle in that it does not need to define a +// dynamic baseURL for the static assets and may load some css that would +// already be loaded by the notebook otherwise. + +// Export widget models and views, and the npm package version number. +module.exports = require('./Figure.js'); +module.exports['version'] = require('../package.json').version; diff --git a/js/src/extension.js b/js/src/extension.js new file mode 100644 index 00000000000..93114e153c1 --- /dev/null +++ b/js/src/extension.js @@ -0,0 +1,19 @@ +// This file contains the javascript that is run when the notebook is loaded. +// It contains some requirejs configuration and the `load_ipython_extension` +// which is required for any notebook extension. + +// Configure requirejs +if (window.require) { + window.require.config({ + map: { + "*" : { + "plotlywidget": "nbextensions/plotlywidget/index" + } + } + }); +} + +// Export the required load_ipython_extention +module.exports = { + load_ipython_extension: function() {} +}; diff --git a/js/src/index.js b/js/src/index.js new file mode 100644 index 00000000000..106ab52033b --- /dev/null +++ b/js/src/index.js @@ -0,0 +1,12 @@ +// Entry point for the notebook bundle containing custom model definitions. +// +// Setup notebook base URL +// +// Some static assets may be required by the custom widget javascript. The base +// url for the notebook is not known at build time and is therefore computed +// dynamically. +__webpack_public_path__ = document.querySelector('body').getAttribute('data-base-url') + 'nbextensions/plotlywidget/'; + +// Export widget models and views, and the npm package version number. +module.exports = require('./Figure.js'); +module.exports['version'] = require('../package.json').version; diff --git a/js/src/jupyterlab-plugin.js b/js/src/jupyterlab-plugin.js new file mode 100644 index 00000000000..aff2ce752d7 --- /dev/null +++ b/js/src/jupyterlab-plugin.js @@ -0,0 +1,18 @@ +var plotly = require('./index'); +var base = require('@jupyter-widgets/base'); + +/** + * The widget manager provider. + */ +module.exports = { + id: 'plotlywidget', + requires: [base.IJupyterWidgetRegistry], + activate: function(app, widgets) { + widgets.registerWidget({ + name: 'plotlywidget', + version: plotly.version, + exports: plotly + }); + }, + autoStart: true +}; diff --git a/js/webpack.config.js b/js/webpack.config.js new file mode 100644 index 00000000000..75031109013 --- /dev/null +++ b/js/webpack.config.js @@ -0,0 +1,80 @@ +var path = require('path'); +var version = require('./package.json').version; + +// Custom webpack loaders are generally the same for all webpack bundles, hence +// stored in a separate local variable. +var rules = [ + { test: /\.css$/, use: ['style-loader', 'css-loader']}, + { test: /\.json$/, use: 'json-loader' }, + { test: /\.js$/, use: 'ify-loader' } +]; + + +module.exports = [ + {// Notebook extension + // + // This bundle only contains the part of the JavaScript that is run on + // load of the notebook. This section generally only performs + // some configuration for requirejs, and provides the legacy + // "load_ipython_extension" function which is required for any notebook + // extension. + // + entry: './src/extension.js', + output: { + filename: 'extension.js', + path: path.resolve(__dirname, '..', 'plotlywidget', 'static'), + libraryTarget: 'amd' + } + }, + {// Bundle for the notebook containing the custom widget views and models + // + // This bundle contains the implementation for the custom widget views and + // custom widget. + // It must be an amd module + // + entry: './src/index.js', + output: { + filename: 'index.js', + path: path.resolve(__dirname, '..', 'plotlywidget', 'static'), + libraryTarget: 'amd' + }, + devtool: 'source-map', + node: { + fs: 'empty' + }, + module: { + rules: rules + }, + externals: ['@jupyter-widgets/base'] + }, + {// Embeddable plotlywidget bundle + // + // This bundle is generally almost identical to the notebook bundle + // containing the custom widget views and models. + // + // The only difference is in the configuration of the webpack public path + // for the static assets. + // + // It will be automatically distributed by unpkg to work with the static + // widget embedder. + // + // The target bundle is always `dist/index.js`, which is the path required + // by the custom widget embedder. + // + entry: './src/embed.js', + output: { + filename: 'index.js', + path: path.resolve(__dirname, 'dist'), + libraryTarget: 'amd', + publicPath: 'https://unpkg.com/plotlywidget@' + version + '/dist/' + }, + devtool: 'source-map', + node: { + fs: 'empty' + }, + module: { + rules: rules + }, + externals: ['@jupyter-widgets/base'] + } +]; diff --git a/makefile b/makefile index ca75f11480c..1e920877803 100644 --- a/makefile +++ b/makefile @@ -27,6 +27,7 @@ update_default_schema : f.close()" @echo "Auto-generating graph objects based on updated default-schema." python update_graph_objs.py + python codegen/__init__.py install : sync_subs @echo "" diff --git a/optional-requirements.txt b/optional-requirements.txt index 3d4083f6bf9..858722f996b 100644 --- a/optional-requirements.txt +++ b/optional-requirements.txt @@ -16,6 +16,9 @@ coverage==4.3.1 mock==2.0.0 nose==1.3.3 +## codegen dependencies ## +yapf + ## ipython ## ipython @@ -32,4 +35,4 @@ ipykernel ## deps for _county_choropleth.py figure factory pyshp geopandas -shapely \ No newline at end of file +shapely diff --git a/plotly/animation.py b/plotly/animation.py new file mode 100644 index 00000000000..5a1300d1c4b --- /dev/null +++ b/plotly/animation.py @@ -0,0 +1,52 @@ +from plotly.basevalidators import EnumeratedValidator, NumberValidator + + +class EasingValidator(EnumeratedValidator): + + def __init__(self, plotly_name='easing'): + super().__init__(plotly_name=plotly_name, + parent_name='batch_animate', + values=[ + "linear", + "quad", + "cubic", + "sin", + "exp", + "circle", + "elastic", + "back", + "bounce", + "linear-in", + "quad-in", + "cubic-in", + "sin-in", + "exp-in", + "circle-in", + "elastic-in", + "back-in", + "bounce-in", + "linear-out", + "quad-out", + "cubic-out", + "sin-out", + "exp-out", + "circle-out", + "elastic-out", + "back-out", + "bounce-out", + "linear-in-out", + "quad-in-out", + "cubic-in-out", + "sin-in-out", + "exp-in-out", + "circle-in-out", + "elastic-in-out", + "back-in-out", + "bounce-in-out" + ]) + + +class DurationValidator(NumberValidator): + + def __init__(self, plotly_name='duration'): + super().__init__(plotly_name=plotly_name, parent_name='batch_animate', min=0) diff --git a/plotly/basedatatypes.py b/plotly/basedatatypes.py new file mode 100644 index 00000000000..0f5251aa93c --- /dev/null +++ b/plotly/basedatatypes.py @@ -0,0 +1,1793 @@ +import collections +import numbers +import os +import re +import typing as typ +import uuid +from contextlib import contextmanager +from copy import deepcopy +from importlib import import_module +from pprint import pprint +from urllib import parse + +import numpy as np +from plotly.offline import plot as plotlypy_plot +from traitlets import Undefined + +from plotly import animation +from plotly.basevalidators import CompoundValidator, CompoundArrayValidator, BaseDataValidator +from plotly.callbacks import Points, BoxSelector, LassoSelector, InputState +from plotly.validators.layout import (XAxisValidator, YAxisValidator, GeoValidator, + TernaryValidator, SceneValidator) + + +class BaseFigure: + + # Constructor + # ----------- + def __init__(self, data=None, layout_plotly=None, frames=None): + super().__init__() + + layout = layout_plotly + + # Traces + # ------ + from plotly.validators import DataValidator + self._data_validator = DataValidator() + + if data is None: + self._data_objs = () # type: typ.Tuple[BaseTraceType] + self._data_defaults = [] + self._data = [] + else: + data = self._data_validator.validate_coerce(data) + + self._data_objs = data + self._data_defaults = [{} for trace in data] + self._data = [deepcopy(trace._props) for trace in data] + for trace in data: + trace._orphan_props.clear() + trace._parent = self + + # Layout + # ------ + from plotly.validators import LayoutValidator + self._layout_validator = LayoutValidator() + + from plotly.datatypes import Layout + + if layout is None: + layout = Layout() # type: Layout + else: + layout = self._layout_validator.validate_coerce(layout) + + self._layout_obj = layout + self._layout = deepcopy(self._layout_obj._props) + self._layout_obj._parent = self + self._layout_defaults = {} + + # Frames + # ------ + from plotly.validators import FramesValidator + self._frames_validator = FramesValidator() + + if frames: + self._frame_objs = self._frames_validator.validate_coerce(frames) + else: + self._frame_objs = () + + # Message States + # -------------- + self._relayout_in_process = False + self._waiting_relayout_callbacks = [] + self._last_relayout_msg_id = 0 + + self._restyle_in_process = False + self._waiting_restyle_callbacks = [] + self._last_restyle_msg_id = 0 + + # View count + # ---------- + self._view_count = 0 + + # Context manager + # --------------- + self._in_batch_mode = False + self._batch_style_commands = {} # type: typ.Dict[int, typ.Dict[str, typ.Any]] + self._batch_layout_commands = {} # type: typ.Dict[str, typ.Any] + self._animation_duration_validator = animation.DurationValidator() + self._animation_easing_validator = animation.EasingValidator() + + # SVG + # --- + self._svg_requests = {} + + # Logging + # ------- + self._log_plotly_commands = False + + # Magic Methods + # ------------- + def __setitem__(self, prop, value): + if prop == 'data': + self.data = value + elif prop == 'layout': + self.layout = value + elif prop == 'frames': + self.frames = value + else: + raise KeyError(prop) + + def __getitem__(self, prop): + if prop == 'data': + return self.data + elif prop == 'layout': + return self.layout + elif prop == 'frames': + return self.frames + else: + raise KeyError(prop) + + def __contains__(self, prop): + return prop in ('data', 'layout', 'frames') + + # Data + # ---- + @property + def data(self) -> typ.Tuple['BaseTraceType']: + return self._data_objs + + @data.setter + def data(self, new_data): + + # Validate new_data + new_data = self._data_validator.validate_coerce(new_data) + + + orig_uids = [_trace['uid'] for _trace in self._data] + new_uids = [trace.uid for trace in new_data] + + invalid_uids = set(new_uids).difference(set(orig_uids)) + if invalid_uids: + raise ValueError(('The trace property of a figure may only be assigned to ' + 'a permutation of a subset of itself\n' + ' Invalid trace(s) with uid(s): {invalid_uids}').format(invalid_uids=invalid_uids)) + + # Check for duplicates + uid_counter = collections.Counter(new_uids) + duplicate_uids = [uid for uid, count in uid_counter.items() if count > 1] + if duplicate_uids: + raise ValueError(('The trace property of a figure may not be assigned ' + 'multiple copies of a trace\n' + ' Duplicate trace uid(s): {duplicate_uids}' + ).format(duplicate_uids=duplicate_uids)) + + # Compute traces to remove + remove_uids = set(orig_uids).difference(set(new_uids)) + delete_inds = [] + for i, _trace in enumerate(self._data): + if _trace['uid'] in remove_uids: + delete_inds.append(i) + + # Unparent trace object to be removed + old_trace = self.data[i] + old_trace._orphan_props.update(deepcopy(self.data[i]._props)) + old_trace._parent = None + + # Compute trace data list after removal + traces_props_post_removal = [t for t in self._data] + traces_prop_defaults_post_removal = [t for t in self._data_defaults] + orig_uids_post_removal = [trace_data['uid'] for trace_data in self._data] + + for i in reversed(delete_inds): + del traces_props_post_removal[i] + del traces_prop_defaults_post_removal[i] + del orig_uids_post_removal[i] + + if delete_inds: + relayout_msg_id = self._last_relayout_msg_id + 1 + self._last_relayout_msg_id = relayout_msg_id + self._relayout_in_process = True + + for di in reversed(delete_inds): + del self._data[di] # Modify in-place so we don't trigger serialization + + if self._log_plotly_commands: + print('Plotly.deleteTraces') + pprint(delete_inds, indent=4) + + self._py2js_deleteTraces = {'delete_inds': delete_inds, + '_relayout_msg_id ': relayout_msg_id} + self._py2js_deleteTraces = None + + # Compute move traces + new_inds = [] + + for uid in orig_uids_post_removal: + new_inds.append(new_uids.index(uid)) + + current_inds = list(range(len(traces_props_post_removal))) + + if not all([i1 == i2 for i1, i2 in zip(new_inds, current_inds)]): + + move_msg = [current_inds, new_inds] + + if self._log_plotly_commands: + print('Plotly.moveTraces') + pprint(move_msg, indent=4) + + self._py2js_moveTraces = move_msg + self._py2js_moveTraces = None + + # ### Reorder trace elements ### + # We do so in-place so we don't trigger serialization + # pprint(self._traces_data) + + # #### Remove by curr_inds in reverse order #### + moving_traces_data = [] + for ci in reversed(current_inds): + # Push moving traces data to front of list + moving_traces_data.insert(0, self._data[ci]) + del self._data[ci] + + # #### Sort new_inds and moving_traces_data by new_inds #### + new_inds, moving_traces_data = zip(*sorted(zip(new_inds, moving_traces_data))) + + # #### Insert by new_inds in forward order #### + for ni, trace_data in zip(new_inds, moving_traces_data): + self._data.insert(ni, trace_data) + + # pprint(self._traces_data) + + # Update _traces order + self._data_defaults = [_trace for i, _trace in sorted(zip(new_inds, traces_prop_defaults_post_removal))] + self._data_objs = tuple(new_data) + + def restyle(self, style, trace_indexes=None): + if trace_indexes is None: + trace_indexes = list(range(len(self.data))) + + if not isinstance(trace_indexes, (list, tuple)): + trace_indexes = [trace_indexes] + + restyle_msg = self._perform_restyle_dict(style, trace_indexes) + if restyle_msg: + self._dispatch_change_callbacks_restyle(restyle_msg, trace_indexes) + self._send_restyle_msg(restyle_msg, trace_indexes=trace_indexes) + + def _perform_restyle_dict(self, style, trace_indexes): + # Make sure trace_indexes is an array + if not isinstance(trace_indexes, list): + trace_indexes = [trace_indexes] + + restyle_data = {} # Resytyle data to send to JS side as Plotly.restylePlot() + + for raw_key, v in style.items(): + # kstr may have periods. e.g. foo.bar + key_path = self._str_to_dict_path(raw_key) + + # Properties with leading underscores passed through as-is + if raw_key.startswith('_'): + restyle_data[raw_key] = v + continue + + if not isinstance(v, list): + v = [v] + + if isinstance(v, dict): + raise ValueError('Restyling objects not supported, only individual properties\n' + ' Received: {{k}: {v}}'.format(k=raw_key, v=v)) + else: + restyle_msg_vs = [] + any_vals_changed = False + for i, trace_ind in enumerate(trace_indexes): + if trace_ind >= len(self._data): + raise ValueError('Trace index {trace_ind} out of range'.format(trace_ind=trace_ind)) + val_parent = self._data[trace_ind] + for kp, key_path_el in enumerate(key_path[:-1]): + + # Extend val_parent list if needed + if isinstance(val_parent, list) and isinstance(key_path_el, int): + while len(val_parent) <= key_path_el: + val_parent.append(None) + + elif isinstance(val_parent, dict) and key_path_el not in val_parent: + if isinstance(key_path[kp + 1], int): + val_parent[key_path_el] = [] + else: + val_parent[key_path_el] = {} + + val_parent = val_parent[key_path_el] + + last_key = key_path[-1] + + trace_v = v[i % len(v)] + + restyle_msg_vs.append(trace_v) + + if BasePlotlyType._vals_equal(trace_v, Undefined): + # Do nothing + pass + elif trace_v is None: + if isinstance(val_parent, dict) and last_key in val_parent: + val_parent.pop(last_key) + any_vals_changed = True + elif isinstance(val_parent, dict): + if last_key not in val_parent or not BasePlotlyType._vals_equal(val_parent[last_key], trace_v): + val_parent[last_key] = trace_v + any_vals_changed = True + + if any_vals_changed: + # At lease one of the values for one of the traces has changed. Update them all + restyle_data[raw_key] = restyle_msg_vs + + return restyle_data + + def _dispatch_change_callbacks_restyle(self, style, trace_indexes): + if not isinstance(trace_indexes, list): + trace_indexes = [trace_indexes] + + dispatch_plan = {t: {} for t in trace_indexes} + # e.g. {0: {(): {'obj': layout, + # 'changed_paths': [('xaxis', 'range')]}}} + + for raw_key, v in style.items(): + key_path = self._str_to_dict_path(raw_key) + + # Test whether we should remove trailing integer in path + # e.g. ('xaxis', 'range', '1') -> ('xaxis', 'range') + # We only do this if the trailing index is an integer that references a primitive value + if isinstance(key_path[-1], int) and not isinstance(v, dict): + key_path = key_path[:-1] + + for trace_ind in trace_indexes: + + parent_obj = self.data[trace_ind] + key_path_so_far = () + keys_left = key_path + + # Iterate down the key path + for next_key in key_path: + if next_key not in parent_obj: + # Not a property + break + + if isinstance(parent_obj, BasePlotlyType): + if key_path_so_far not in dispatch_plan[trace_ind]: + dispatch_plan[trace_ind][key_path_so_far] = {'obj': parent_obj, 'changed_paths': set()} + + dispatch_plan[trace_ind][key_path_so_far]['changed_paths'].add(keys_left) + + next_val = parent_obj[next_key] + elif isinstance(parent_obj, (list, tuple)): + next_val = parent_obj[next_key] + else: + # Primitive value + break + + key_path_so_far = key_path_so_far + (next_key,) + keys_left = keys_left[1:] + parent_obj = next_val + + # pprint(dispatch_plan) + for trace_ind in trace_indexes: + for p in dispatch_plan[trace_ind].values(): + obj = p['obj'] + changed_paths = p['changed_paths'] + obj._dispatch_change_callbacks(changed_paths) + + def _send_restyle_msg(self, style, trace_indexes=None): + if not isinstance(trace_indexes, (list, tuple)): + trace_indexes = [trace_indexes] + + # Add and update message ids + relayout_msg_id = self._last_relayout_msg_id + 1 + style['_relayout_msg_id'] = relayout_msg_id + self._last_relayout_msg_id = relayout_msg_id + self._relayout_in_process = True + + restyle_msg_id = self._last_restyle_msg_id + 1 + style['_restyle_msg_id'] = restyle_msg_id + self._last_restyle_msg_id = restyle_msg_id + self._restyle_in_process = True + + restyle_msg = (style, trace_indexes) + if self._log_plotly_commands: + print('Plotly.restyle') + pprint(restyle_msg, indent=4) + + self._py2js_restyle = restyle_msg + self._py2js_restyle = None + + def _restyle_child(self, child, prop, val): + + trace_index = self.data.index(child) + + if not self._in_batch_mode: + send_val = [val] + restyle = {prop: send_val} + self._dispatch_change_callbacks_restyle(restyle, trace_index) + self._send_restyle_msg(restyle, trace_indexes=trace_index) + else: + if trace_index not in self._batch_style_commands: + self._batch_style_commands[trace_index] = {} + self._batch_style_commands[trace_index][prop] = val + + def add_traces(self, data: typ.List['BaseTraceType']): + + if self._in_batch_mode: + self._batch_layout_commands.clear() + self._batch_style_commands.clear() + raise ValueError('Traces may not be added in a batch context') + + if not isinstance(data, (list, tuple)): + data = [data] + + # Validate + data = self._data_validator.validate_coerce(data) + + # Make deep copy of trace data (Optimize later if needed) + new_traces_data = [deepcopy(trace._props) for trace in data] + + # Update trace parent + for trace in data: + trace._parent = self + trace._orphan_props.clear() + + # Update python side + self._data.extend(new_traces_data) # append instead of assignment so we don't trigger serialization + self._data_defaults = self._data_defaults + [{} for trace in data] + self._data_objs = self._data_objs + data + + # Update messages + relayout_msg_id = self._last_relayout_msg_id + 1 + self._last_relayout_msg_id = relayout_msg_id + self._relayout_in_process = True + + restyle_msg_id = self._last_restyle_msg_id + 1 + self._last_restyle_msg_id = restyle_msg_id + self._restyle_in_process = True + + # Add message ids + for traces_data in new_traces_data: + traces_data['_relayout_msg_id'] = relayout_msg_id + traces_data['_restyle_msg_id'] = restyle_msg_id + + # Send to front end + if self._log_plotly_commands: + print('Plotly.addTraces') + pprint(new_traces_data, indent=4) + + add_traces_msg = new_traces_data + self._py2js_addTraces = add_traces_msg + self._py2js_addTraces = None + + return data + + def _get_child_props(self, child): + try: + trace_index = self.data.index(child) + except ValueError as _: + trace_index = None + + if trace_index is not None: + return self._data[trace_index] + elif child is self.layout: + return self._layout + else: + raise ValueError('Unrecognized child: %s' % child) + + def _get_child_prop_defaults(self, child): + try: + trace_index = self.data.index(child) + except ValueError as _: + trace_index = None + + if trace_index is not None: + return self._data_defaults[trace_index] + elif child is self.layout: + return self._layout_defaults + else: + raise ValueError('Unrecognized child: %s' % child) + + def _init_child_props(self, child): + # layout and traces dict are never None + return + + # Layout + # ------ + @property + def layout(self): + return self._layout_obj + + @layout.setter + def layout(self, new_layout): + # Validate layout + new_layout = self._layout_validator.validate_coerce(new_layout) + new_layout_data = deepcopy(new_layout._props) + + # Unparent current layout + if self._layout_obj: + old_layout_data = deepcopy(self._layout_obj._props) + self._layout_obj._orphan_props.update(old_layout_data) + self._layout_obj._parent = None + + # Parent new layout + self._layout = new_layout_data + new_layout._parent = self + self._layout_obj = new_layout + + # Notify JS side + self._send_relayout_msg(new_layout_data) + + def _relayout_child(self, child, prop, val): + send_val = val # Don't wrap in a list for relayout + + if not self._in_batch_mode: + relayout_msg = {prop: send_val} + self._dispatch_change_callbacks_relayout(relayout_msg) + self._send_relayout_msg(relayout_msg) + else: + self._batch_layout_commands[prop] = send_val + + def _send_relayout_msg(self, layout): + + if self._log_plotly_commands: + print('Plotly.relayout') + pprint(layout, indent=4) + + # Add message id + msg_id = self._last_relayout_msg_id + 1 + layout['_relayout_msg_id'] = msg_id + self._last_relayout_msg_id = msg_id + + self._py2js_relayout = layout + self._py2js_relayout = None + + + def relayout(self, layout): + relayout_msg = self._perform_relayout_dict(layout) + if relayout_msg: + self._dispatch_change_callbacks_relayout(relayout_msg) + self._send_relayout_msg(relayout_msg) + + def _perform_relayout_dict(self, relayout_data): + relayout_msg = {} # relayout data to send to JS side as Plotly.relayout() + + # Update layout_data + # print('_perform_relayout') + for raw_key, v in relayout_data.items(): + # kstr may have periods. e.g. foo.bar + key_path = self._str_to_dict_path(raw_key) + + val_parent = self._layout + for kp, key_path_el in enumerate(key_path[:-1]): + if key_path_el not in val_parent: + + # Extend val_parent list if needed + if isinstance(val_parent, list) and isinstance(key_path_el, int): + while len(val_parent) <= key_path_el: + val_parent.append(None) + + elif isinstance(val_parent, dict) and key_path_el not in val_parent: + if isinstance(key_path[kp+1], int): + val_parent[key_path_el] = [] + else: + val_parent[key_path_el] = {} + + val_parent = val_parent[key_path_el] + + last_key = key_path[-1] + # print(f'{val_parent}, {key_path}, {last_key}, {v}') + + if v is Undefined: + # Do nothing + pass + elif v is None: + if isinstance(val_parent, dict) and last_key in val_parent: + val_parent.pop(last_key) + relayout_msg[raw_key] = None + else: + if isinstance(val_parent, list): + if isinstance(last_key, int): + while(len(val_parent) <= last_key): + val_parent.append(None) + val_parent[last_key] = v + relayout_msg[raw_key] = v + elif isinstance(val_parent, dict): + if last_key not in val_parent or not BasePlotlyType._vals_equal(val_parent[last_key], v): + val_parent[last_key] = v + relayout_msg[raw_key] = v + + return relayout_msg + + def _dispatch_change_callbacks_relayout(self, relayout_msg): + dispatch_plan = {} # e.g. {(): {'obj': layout, + # 'changed_paths': [('xaxis', 'range')]}} + for raw_key, v in relayout_msg.items(): + # kstr may have periods. e.g. foo.bar + key_path = self._str_to_dict_path(raw_key) + + # Test whether we should remove trailing integer in path + # e.g. ('xaxis', 'range', '1') -> ('xaxis', 'range') + # We only do this if the trailing index is an integer that references a primitive value + if isinstance(key_path[-1], int) and not isinstance(v, dict): + key_path = key_path[:-1] + + parent_obj = self.layout + key_path_so_far = () + keys_left = key_path + + # Iterate down the key path + for next_key in key_path: + if next_key not in parent_obj: + break + + if isinstance(parent_obj, BasePlotlyType): + if key_path_so_far not in dispatch_plan: + dispatch_plan[key_path_so_far] = {'obj': parent_obj, 'changed_paths': set()} + dispatch_plan[key_path_so_far]['changed_paths'].add(keys_left) + + next_val = parent_obj[next_key] + # parent_obj._dispatch_change_callbacks(next_key, next_val) + elif isinstance(parent_obj, (list, tuple)): + next_val = parent_obj[next_key] + else: + # Primitive value + break + + key_path_so_far = key_path_so_far + (next_key,) + keys_left = keys_left[1:] + parent_obj = next_val + + # pprint(dispatch_plan) + for p in dispatch_plan.values(): + obj = p['obj'] + changed_paths = p['changed_paths'] + obj._dispatch_change_callbacks(changed_paths) + + + # Frames + # ------ + @property + def frames(self): + return self._frame_objs + + @frames.setter + def frames(self, new_frames): + # Note: Frames are not supported by the FigureWidget subclass so we only validate coerce the frames + # We don't emit any events of frame change and we don't reparent the frames + + # Validate frames + self._frame_objs = self._frames_validator.validate_coerce(new_frames) + + # Update + # ------ + def update(self, style=None, layout=None, trace_indexes=None): + + restyle_msg, relayout_msg, trace_indexes = self._perform_update_dict(style=style, + layout=layout, + trace_indexes=trace_indexes) + # Perform restyle portion of update + if restyle_msg: + self._dispatch_change_callbacks_restyle(restyle_msg, trace_indexes) + + # Perform relayout portion of update + if relayout_msg: + self._dispatch_change_callbacks_relayout(relayout_msg) + + if restyle_msg or relayout_msg: + self._send_update_msg(restyle_msg, relayout_msg, trace_indexes) + + def _perform_update_dict(self, style=None, layout=None, trace_indexes=None): + if not style and not layout: + # Nothing to do + return None, None, None + + if style is None: + style = {} + if layout is None: + layout = {} + + # Process trace indexes + if trace_indexes is None: + trace_indexes = list(range(len(self.data))) + + if not isinstance(trace_indexes, (list, tuple)): + trace_indexes = [trace_indexes] + + relayout_msg = self._perform_relayout_dict(layout) + restyle_msg = self._perform_restyle_dict(style, trace_indexes) + # print(style, trace_indexes, restyle_msg) + # pprint(self._traces_data) + return restyle_msg, relayout_msg, trace_indexes + + def _send_update_msg(self, style, layout, trace_indexes=None): + if not isinstance(trace_indexes, (list, tuple)): + trace_indexes = [trace_indexes] + + # Add restyle message id + restyle_msg_id = self._last_restyle_msg_id + 1 + style['_restyle_msg_id'] = restyle_msg_id + self._last_restyle_msg_id = restyle_msg_id + self._restyle_in_process = True + + # Add relayout message id + relayout_msg_id = self._last_relayout_msg_id + 1 + layout['_relayout_msg_id'] = relayout_msg_id + self._last_relayout_msg_id = relayout_msg_id + self._relayout_in_process = True + + update_msg = (style, layout, trace_indexes) + + if self._log_plotly_commands: + print('Plotly.update') + pprint(update_msg, indent=4) + + self._py2js_update = update_msg + self._py2js_update = None + + # Callbacks + # --------- + def on_relayout_completed(self, fn): + if self._relayout_in_process: + self._waiting_relayout_callbacks.append(fn) + else: + fn() + + def on_restyle_completed(self, fn): + if self._restyle_in_process: + self._waiting_restyle_callbacks.append(fn) + else: + fn() + + # Context managers + # ---------------- + @contextmanager + def batch_update(self): + """Hold syncing any state until the outermost context manager exits""" + if self._in_batch_mode is True: + yield + else: + try: + self._in_batch_mode = True + yield + finally: + self._in_batch_mode = False + self._send_batch_update() + + def _build_update_params_from_batch(self): + # Handle Style / Trace Indexes + # ---------------------------- + batch_style_commands = self._batch_style_commands + trace_indexes = sorted(set([trace_ind for trace_ind in batch_style_commands])) + + all_props = sorted(set([prop + for trace_style in self._batch_style_commands.values() + for prop in trace_style])) + + # Initialize style dict with all values undefined + style = {prop: [Undefined for _ in range(len(trace_indexes))] + for prop in all_props} + + # Fill in values + for trace_ind, trace_style in batch_style_commands.items(): + for trace_prop, trace_val in trace_style.items(): + style[trace_prop][trace_indexes.index(trace_ind)] = trace_val + + # Handle Layout + # ------------- + layout = self._batch_layout_commands + + return style, layout, trace_indexes + + def _send_batch_update(self): + style, layout, trace_indexes = self._build_update_params_from_batch() + self.update(style=style, layout=layout, trace_indexes=trace_indexes) + self._batch_layout_commands.clear() + self._batch_style_commands.clear() + + @contextmanager + def batch_animate(self, duration=500, easing="cubic-in-out"): + """ + Context manager to animate trace / layout updates + + Parameters + ---------- + duration : number + The duration of the transition, in milliseconds. If equal to zero, updates are synchronous. + easing : string + The easing function used for the transition. + One of: + - linear + - quad + - cubic + - sin + - exp + - circle + - elastic + - back + - bounce + - linear-in + - quad-in + - cubic-in + - sin-in + - exp-in + - circle-in + - elastic-in + - back-in + - bounce-in + - linear-out + - quad-out + - cubic-out + - sin-out + - exp-out + - circle-out + - elastic-out + - back-out + - bounce-out + - linear-in-out + - quad-in-out + - cubic-in-out + - sin-in-out + - exp-in-out + - circle-in-out + - elastic-in-out + - back-in-out + - bounce-in-ou + + Returns + ------- + None + """ + duration = self._animation_duration_validator.validate_coerce(duration) + easing = self._animation_easing_validator.validate_coerce(easing) + + if self._in_batch_mode is True: + yield + else: + try: + self._in_batch_mode = True + yield + finally: + self._in_batch_mode = False + self._send_batch_animate( + {'transition': {'duration': duration,'easing': easing}, + 'frame': {'duration': duration}}) + + def _send_batch_animate(self, animation_opts): + + # Apply commands to internal dictionaries as an update + # ---------------------------------------------------- + style, layout, trace_indexes = self._build_update_params_from_batch() + restyle_msg, relayout_msg, trace_indexes = self._perform_update_dict(style, layout, trace_indexes) + + # ### Perform restyle portion of animate ### + if restyle_msg: + self._dispatch_change_callbacks_restyle(restyle_msg, trace_indexes) + + # ### Perform relayout portion of update ### + if relayout_msg: + self._dispatch_change_callbacks_relayout(relayout_msg) + + # Convert style / trace_indexes into animate form + # ----------------------------------------------- + if self._batch_style_commands: + animate_styles, animate_trace_indexes = zip(*[ + (trace_style, trace_index) for trace_index, trace_style in self._batch_style_commands.items()]) + else: + animate_styles, animate_trace_indexes = {}, [] + + animate_layout = self._batch_layout_commands + + # Send animate message to JS + # -------------------------- + self._send_animate_msg(list(animate_styles), animate_layout, list(animate_trace_indexes), animation_opts) + + # Clear batched commands + # ---------------------- + self._batch_layout_commands.clear() + self._batch_style_commands.clear() + + def _send_animate_msg(self, styles, layout, trace_indexes, animation_opts): + # print(styles, layout, trace_indexes, animation_opts) + if not isinstance(trace_indexes, (list, tuple)): + trace_indexes = [trace_indexes] + + # Add restyle message id + restyle_msg_id = self._last_restyle_msg_id + 1 + for style in styles: + style['_restyle_msg_id'] = restyle_msg_id + + self._last_restyle_msg_id = restyle_msg_id + self._restyle_in_process = True + + # Add relayout message id + relayout_msg_id = self._last_relayout_msg_id + 1 + layout['_relayout_msg_id'] = relayout_msg_id + self._last_relayout_msg_id = relayout_msg_id + self._relayout_in_process = True + + animate_msg = [{'data': styles, + 'layout': layout, + 'traces': trace_indexes}, + animation_opts] + + if self._log_plotly_commands: + print('Plotly.animate') + pprint(animate_msg, indent=4) + + self._py2js_animate = animate_msg + self._py2js_animate = None + + # Remove message ids + for style in styles: + style.pop('_restyle_msg_id') + + layout.pop('_relayout_msg_id') + + # Exports + # ------- + def to_dict(self): + + # Handle data + data = deepcopy([BaseFigure._remove_underscore_keys(trace) for trace in self._data]) + + # Handle layout + layout = deepcopy(BaseFigure._remove_underscore_keys(self._layout)) + + # Handle frames + res = {'data': data, 'layout': layout} + frames = deepcopy([BaseFigure._remove_underscore_keys(frame._props) for frame in self._frame_objs]) + if frames: + res['frames'] = frames + + return res + + def to_plotly_json(self): + return self.to_dict() + + def save_html(self, filename, auto_open=False, responsive=False): + data = self.to_dict() + if responsive: + if 'height' in data['layout']: + data['layout'].pop('height') + if 'width' in data['layout']: + data['layout'].pop('width') + else: + # Assign width/height explicitly in case these were defaults + data['layout']['height'] = self.layout.height + data['layout']['width'] = self.layout.width + + plotlypy_plot(data, filename=filename, show_link=False, auto_open=auto_open, validate=False) + + def save_image(self, filename, image_type=None, scale_factor=2): + """ + Save figure to a static image file + + Parameters + ---------- + filename : str + Image output file name + image_type : str + Image file type. One of: 'svg', 'png', 'pdf', or 'ps'. If not set, file type + is inferred from the filename extension + scale_factor : number + (For png image type) Factor by which to increase the number of pixels in each + dimension. A scale factor of 1 will result in a image with pixel dimensions + (layout.width, layout.height). A scale factor of 2 will result in an image + with dimensions (2*layout.width, 2*layout.height), doubling image's DPI. + (Default 2) + """ + + # Validate / infer image_type + supported_image_types = ['svg', 'png', 'pdf', 'ps'] + cairo_image_types = ['png', 'pdf', 'ps'] + supported_types_csv = ', '.join(supported_image_types) + + if not image_type: + # Infer image type from extension + _, extension = os.path.splitext(filename) + + if not extension: + raise ValueError('No image_type specified and file extension has no extension ' + 'from which to infer an image type ' + 'Supported image types are: {image_types}' + .format(image_types=supported_types_csv)) + + image_type = extension[1:] + + image_type = image_type.lower() + if image_type not in supported_image_types: + raise ValueError("Unsupported image type '{image_type}'\n" + "Supported image types are: {image_types}" + .format(image_type=image_type, + image_types=supported_types_csv)) + + # Validate cairo dependency + if image_type in cairo_image_types: + # Check whether we have cairosvg available + try: + import_module('cairosvg') + except ModuleNotFoundError: + raise ImportError('Exporting to {image_type} requires cairosvg' + .format(image_type=image_type)) + + # Validate scale_factor + if not isinstance(scale_factor, numbers.Number) or scale_factor <= 0: + raise ValueError('scale_factor must be a positive number.\n' + ' Received: {scale_factor}'.format(scale_factor=scale_factor)) + + req_id = str(uuid.uuid1()) + + # Register request + self._svg_requests[req_id] = {'filename': filename, + 'image_type': image_type, + 'scale_factor': scale_factor} + + self._py2js_requestSvg = req_id + self._py2js_requestSvg = None + + def _do_save_image(self, req_id, svg_uri): + req_info = self._svg_requests.pop(req_id, None) + if not req_info: + return + + # Remove svg header + if not svg_uri.startswith('data:image/svg+xml,'): + raise ValueError('Invalid svg data URI') + + svg = svg_uri.replace('data:image/svg+xml,', '') + + # Unquote characters (e.g. '%3Csvg%20' -> ' ['foo', 'bar[0]'] + key_path = raw_key.split('.') + + # Split out bracket indexes. e.g. ['foo', 'bar[0]'] -> ['foo', 'bar', '0'] + bracket_re = re.compile('(.*)\[(\d+)\]') + key_path2 = [] + for key in key_path: + match = bracket_re.fullmatch(key) + if match: + key_path2.extend(match.groups()) + else: + key_path2.append(key) + + # Convert elements to ints if possible. e.g. e.g. ['foo', 'bar', '0'] -> ['foo', 'bar', 0] + for i in range(len(key_path2)): + try: + key_path2[i] = int(key_path2[i]) + except ValueError as _: + pass + + return tuple(key_path2) + + @staticmethod + def _is_object_list(v): + return isinstance(v, list) and len(v) > 0 and isinstance(v[0], dict) + + @staticmethod + def _remove_overlapping_props(input_data, delta_data, prop_path=()): + """ + Remove properties in data that are also into delta. Do so recursively. + + Except, never remove uid from input_data + + Parameters + ---------- + data : + delta : + + Returns + ------- + List of removed property path tuples + """ + removed = [] + if isinstance(input_data, dict): + assert isinstance(delta_data, dict) + + for p, delta_val in delta_data.items(): + if isinstance(delta_val, dict) or BaseFigure._is_object_list(delta_val): + if p in input_data: + input_val = input_data[p] + removed.extend( + BaseFigure._remove_overlapping_props( + input_val, + delta_val, + prop_path + (p,))) + elif p in input_data and p != 'uid': + input_data.pop(p) + removed.append(prop_path + (p,)) + + elif isinstance(input_data, list): + assert isinstance(delta_data, list) + + for i, delta_val in enumerate(delta_data): + if i >= len(input_data): + break + + input_val = input_data[i] + if input_val is not None and isinstance(delta_val, dict) or BaseFigure._is_object_list(delta_val): + removed.extend( + BaseFigure._remove_overlapping_props( + input_val, + delta_val, + prop_path + (i,))) + + return removed + + @staticmethod + def transform_data(to_data, from_data, should_remove=True, relayout_path=()): + """ + Transform to_data into from_data and return relayout style description of transformation + + Parameters + ---------- + to_data : + from_data : + + Returns + ------- + + """ + relayout_terms = {} + if isinstance(to_data, dict): + if not isinstance(from_data, dict): + raise ValueError('Mismatched data types: to_data: {to_dict} {from_data}'.format( + to_dict=to_data, from_data=from_data)) + + # Handle addition / modification of terms + for from_prop, from_val in from_data.items(): + if isinstance(from_val, dict) or BaseFigure._is_object_list(from_val): + if from_prop not in to_data: + to_data[from_prop] = {} if isinstance(from_val, dict) else [] + + input_val = to_data[from_prop] + relayout_terms.update( + BaseFigure.transform_data( + input_val, + from_val, + should_remove=should_remove, + relayout_path=relayout_path + (from_prop,))) + else: + if from_prop not in to_data or not BasePlotlyType._vals_equal(to_data[from_prop], from_val): + # if from_prop in to_data: + # print(f'to_data[from_prop] != from_val -- {to_data}[{from_prop}] != {from_val}:') + to_data[from_prop] = from_val + relayout_terms[relayout_path + (from_prop,)] = from_val + + # Handle removal of terms + if should_remove: + for remove_prop in set(to_data.keys()).difference(set(from_data.keys())): + to_data.pop(remove_prop) + + elif isinstance(to_data, list): + if not isinstance(from_data, list): + raise ValueError('Mismatched data types: to_data: {to_data} {from_data}'.format( + to_data=to_data, from_data=from_data)) + + for i, from_val in enumerate(from_data): + if i >= len(to_data): + to_data.append(None) + + input_val = to_data[i] + if input_val is not None and isinstance(from_val, dict) or BaseFigure._is_object_list(from_val): + relayout_terms.update( + BaseFigure.transform_data( + input_val, + from_val, + should_remove=should_remove, + relayout_path=relayout_path + (i,))) + else: + if not BasePlotlyType._vals_equal(to_data[i], from_val): + to_data[i] = from_val + relayout_terms[relayout_path + (i,)] = from_val + + return relayout_terms + + +class BasePlotlyType: + _validators = None + + # Defaults to help mocking + def __init__(self, plotly_name, **kwargs): + + self._plotly_name = plotly_name + self._raise_on_invalid_property_error(**kwargs) + self._validators = {} + self._compound_props = {} + self._orphan_props = {} # properties dict for use while object has no parent + self._parent = None + self._change_callbacks = {} # type: typ.Dict[typ.Tuple, typ.Callable] + + @property + def plotly_name(self): + return self._plotly_name + + @property + def _parent_path(self) -> str: + raise NotImplementedError + + @property + def _prop_descriptions(self) -> str: + raise NotImplementedError + + def __setattr__(self, prop, value): + if prop.startswith('_') or hasattr(self, prop): + # Let known properties and private properties through + super().__setattr__(prop, value) + else: + # Raise error on unknown public properties + self._raise_on_invalid_property_error(**{prop: value}) + + def _raise_on_invalid_property_error(self, **kwargs): + invalid_props = list(kwargs.keys()) + if invalid_props: + if len(invalid_props) == 1: + prop_str = 'property' + invalid_str = repr(invalid_props[0]) + else: + prop_str = 'properties' + invalid_str = repr(invalid_props) + + if self._parent_path: + full_prop_name = self._parent_path + '.' + self.plotly_name + else: + full_prop_name = self.plotly_name + + raise ValueError("Invalid {prop_str} specified for {full_prop_name}: {invalid_str}\n\n" + " Valid properties:\n" + "{prop_descriptions}" + .format(prop_str=prop_str, + full_prop_name=full_prop_name, + invalid_str=invalid_str, + prop_descriptions=self._prop_descriptions)) + + @property + def _props(self): + if self.parent is None: + # Use orphan data + return self._orphan_props + else: + # Get data from parent's dict + return self.parent._get_child_props(self) + + def to_plotly_json(self): + return deepcopy(self._props) + + def _init_props(self): + # Ensure that _data is initialized. + if self._props is not None: + pass + else: + self._parent._init_child_props(self) + + def _init_child_props(self, child): + if self.parent: + self.parent._init_child_props(self) + self_props = self.parent._get_child_props(self) + else: + self_props = self._orphan_props + + child_or_children = self._compound_props[child.plotly_name] + if child is child_or_children: + if child.plotly_name not in self_props: + self_props[child.plotly_name] = {} + elif isinstance(child_or_children, (list, tuple)): + child_ind = child_or_children.index(child) + if child.plotly_name not in self_props: + # Initialize list + self_props[child.plotly_name] = [] + + # Make sure list is long enough for child + child_list = self_props[child.plotly_name] + while(len(child_list) <= child_ind): + child_list.append({}) + + def _get_child_props(self, child): + + if self.parent: + self_props = self.parent._get_child_props(self) + else: + self_props = self._orphan_props + + if self_props is None: + return None + else: + child_or_children = self._compound_props[child.plotly_name] + if child is child_or_children: + return self_props.get(child.plotly_name, None) + elif isinstance(child_or_children, (list, tuple)): + child_ind = child_or_children.index(child) + children_props = self_props.get(child.plotly_name, None) + return children_props[child_ind] \ + if children_props is not None and len(children_props) > child_ind \ + else None + else: + ValueError('Unexpected child: %s' % child_or_children) + + @property + def _prop_defaults(self): + if self.parent is None: + return None + else: + return self.parent._get_child_prop_defaults(self) + + def _get_child_prop_defaults(self, child): + if self.parent is None: + return None + + self_prop_defaults = self.parent._get_child_prop_defaults(self) + if self_prop_defaults is None: + return None + else: + child_or_children = self._compound_props[child.plotly_name] + if child is child_or_children: + return self_prop_defaults.get(child.plotly_name, None) + elif isinstance(child_or_children, (list, tuple)): + child_ind = child_or_children.index(child) + children_props = self_prop_defaults.get(child.plotly_name, None) + return children_props[child_ind] if children_props is not None else None + else: + ValueError('Unexpected child: %s' % child_or_children) + + @property + def parent(self): + return self._parent + + def __getitem__(self, prop): + if isinstance(prop, tuple): + res = self + for p in prop: + res = res[p] + + return res + else: + if prop not in self._validators: + raise KeyError(prop) + + if prop in self._compound_props: + return self._compound_props[prop] + elif self._props is not None and prop in self._props: + return self._props[prop] + elif self._prop_defaults is not None: + return self._prop_defaults.get(prop, None) + else: + return None + + def __contains__(self, prop): + return prop in self._validators + + def __setitem__(self, key, value): + if key not in self._validators: + raise KeyError(key) + + validator = self._validators[key] + + if isinstance(validator, CompoundValidator): + self._set_compound_prop(key, value) + elif isinstance(validator, (CompoundArrayValidator, BaseDataValidator)): + self._set_array_prop(key, value) + else: + # Simple property + self._set_prop(key, value) + + @property + def _in_batch_mode(self): + return self.parent and self.parent._in_batch_mode + + @staticmethod + def _vals_equal(v1, v2): + if isinstance(v1, np.ndarray) or isinstance(v2, np.ndarray): + return np.array_equal(v1, v2) + elif isinstance(v1, (list, tuple)): + # Handle recursive equality on lists and tuples + return (isinstance(v2, (list, tuple)) and + len(v1) == len(v2) and + all(BasePlotlyType._vals_equal(e1, e2) for e1, e2 in zip(v1, v2))) + elif isinstance(v1, dict): + # Handle recursive equality on dicts + return (isinstance(v2, dict) and + set(v1.keys()) == set(v2.keys()) and + all(BasePlotlyType._vals_equal(v1[k], v2[k])) for k in v1) + else: + return v1 == v2 + + def _set_prop(self, prop, val): + if val is Undefined: + # Do nothing + return + + validator = self._validators.get(prop) + val = validator.validate_coerce(val) + + if val is None: + # Check if we should send null update + if self._props and prop in self._props: + if not self._in_batch_mode: + self._props.pop(prop) + self._send_update(prop, val) + else: + self._init_props() + if prop not in self._props or not BasePlotlyType._vals_equal(self._props[prop], val): + if not self._in_batch_mode: + self._props[prop] = val + self._send_update(prop, val) + + def _set_compound_prop(self, prop, val): + if val is Undefined: + # Do nothing + return + + # Validate coerce new value + validator = self._validators.get(prop) + val = validator.validate_coerce(val) # type: BasePlotlyType + + # Grab deep copies of current and new states + curr_val = self._compound_props.get(prop, None) + if curr_val is not None: + curr_dict_val = deepcopy(curr_val._props) + else: + curr_dict_val = None + + if val is not None: + new_dict_val = deepcopy(val._props) + else: + new_dict_val = None + + # Update data dict + if not self._in_batch_mode: + if not new_dict_val: + if prop in self._props: + self._props.pop(prop) + else: + self._init_props() + self._props[prop] = new_dict_val + + # Send update if there was a change in value + if not BasePlotlyType._vals_equal(curr_dict_val, new_dict_val): + self._send_update(prop, new_dict_val) + + # Reparent new value and clear orphan data + val._parent = self + val._orphan_props.clear() + + # Reparent old value and update orphan data + if curr_val is not None and curr_val is not val: + if curr_dict_val is not None: + curr_val._orphan_props.update(curr_dict_val) + curr_val._parent = None + + self._compound_props[prop] = val + return val + + def _set_array_prop(self, prop, val): + if val is Undefined: + # Do nothing + return + + # Validate coerce new value + validator = self._validators.get(prop) + val = validator.validate_coerce(val) # type: tuple + + # Update data dict + curr_val = self._compound_props.get(prop, None) + if curr_val is not None: + curr_dict_vals = [deepcopy(cv._props) for cv in curr_val] + else: + curr_dict_vals = None + + if val is not None: + new_dict_vals = [deepcopy(nv._props) for nv in val] + else: + new_dict_vals = None + + # Update data dict + if not self._in_batch_mode: + if not new_dict_vals: + if prop in self._props: + self._props.pop(prop) + else: + self._init_props() + self._props[prop] = new_dict_vals + + # Send update if there was a change in value + if not BasePlotlyType._vals_equal(curr_dict_vals, new_dict_vals): + self._send_update(prop, new_dict_vals) + + # Reparent new values and clear orphan data + if val is not None: + for v in val: + v._orphan_props.clear() + v._parent = self + + # Reparent + if curr_val is not None: + for cv, cv_dict in zip(curr_val, curr_dict_vals): + if cv_dict is not None: + cv._orphan_props.update(cv_dict) + cv._parent = None + self._compound_props[prop] = val + return val + + def _send_update(self, prop, val): + raise NotImplementedError() + + def _update_child(self, child, prop, val): + child_prop_val = getattr(self, child.plotly_name) + if isinstance(child_prop_val, (list, tuple)): + child_ind = child_prop_val.index(child) + obj_path = '{child_name}.{child_ind}.{prop}'.format( + child_name=child.plotly_name, + child_ind=child_ind, + prop=prop) + else: + obj_path = '{child_name}.{prop}'.format(child_name=child.plotly_name, prop=prop) + + self._send_update(obj_path, val) + + def _restyle_child(self, child, prop, val): + self._update_child(child, prop, val) + + def _relayout_child(self, child, prop, val): + self._update_child(child, prop, val) + + # Callbacks + # --------- + def _dispatch_change_callbacks(self, changed_paths): + # print(f'Change callback: {self.prop_name} - {changed_paths}') + changed_paths = set(changed_paths) + # pprint(changed_paths) + for callback_paths, callback in self._change_callbacks.items(): + # pprint(set(callback_paths)) + common_paths = changed_paths.intersection(set(callback_paths)) + if common_paths: + # Invoke callback + callback_args = [self[cb_path] for cb_path in callback_paths] + callback(self, *callback_args) + + def on_change(self, callback, *args): + """ + Register callback function to be called with a properties or subproperties of this object are modified + + Parameters + ---------- + callback : function + Function that accepts 1 + len(args) parameters. First parameter is this object. Second throug last + parameters are the values referenced by args + args : str or tuple(str) + Property name (for direct properties) or tuple of property names / indices (for sub properties). Callback + will be invoked whenever ANY of these properties is modified. Furthermore. The callback will only be + invoked once even if multiple properties are modified during the same restyle operation. + + Returns + ------- + + """ + + if len(args) == 0: + raise ValueError('At least one property/subproperty must be specified') + + # TODO: Validate that args valid properties / subproperties + validated_args = tuple([a if isinstance(a, tuple) else (a,) for a in args]) + + # TODO: add append arg and store list of callbacks + self._change_callbacks[validated_args] = callback + + +class BaseLayoutHierarchyType(BasePlotlyType): + + # _send_relayout analogous to _send_restyle above + def __init__(self, plotly_name, **kwargs): + super().__init__(plotly_name, **kwargs) + + def _send_update(self, prop, val): + if self.parent: + self.parent._relayout_child(self, prop, val) + + +class BaseLayoutType(BaseLayoutHierarchyType): + _subplotid_prop_names = ['xaxis', 'yaxis', 'geo', 'ternary', 'scene'] + _subplotid_validators = {'xaxis': XAxisValidator, + 'yaxis': YAxisValidator, + 'geo': GeoValidator, + 'ternary': TernaryValidator, + 'scene': SceneValidator} + + _subplotid_prop_re = re.compile('(' + '|'.join(_subplotid_prop_names) + ')(\d+)') + + def __init__(self, plotly_name, **kwargs): + # Compute invalid kwargs. Pass to parent for error message + invalid_kwargs = {k: v for k, v in kwargs.items() + if not self._subplotid_prop_re.fullmatch(k)} + super().__init__(plotly_name, **invalid_kwargs) + self._subplotid_props = {} + for prop, value in kwargs.items(): + self._set_subplotid_prop(prop, value) + + def _set_subplotid_prop(self, prop, value): + # We already tested for match in constructor + match = self._subplotid_prop_re.fullmatch(prop) + subplot_prop = match.group(1) + suffix_digit = int(match.group(2)) + if suffix_digit in [0, 1]: + raise TypeError('Subplot properties may only be suffixed by an integer > 1\n' + 'Received {k}'.format(k=prop)) + + # Add validator + if prop not in self._validators: + validator = self._subplotid_validators[subplot_prop](prop_name=prop) + self._validators[prop] = validator + + # Import value + self._subplotid_props[prop] = self._set_compound_prop(prop, value) + + def __getattr__(self, item): + # Check for subplot access (e.g. xaxis2) + # Validate then call self._get_prop(item) + if item in self._subplotid_props: + return self._subplotid_props[item] + + raise AttributeError("'Layout' object has no attribute '{item}'".format(item=item)) + + def __setattr__(self, prop, value): + # Check for subplot assignment (e.g. xaxis2) + # Call _set_compound_prop with the xaxis validator + match = self._subplotid_prop_re.fullmatch(prop) + if match is None: + # Try setting as ordinary property + super().__setattr__(prop, value) + else: + self._set_subplotid_prop(prop, value) + + def __dir__(self): + # Include any active subplot values (xaxis2 etc.) + return super().__dir__() + list(self._subplotid_props.keys()) + + +class BaseTraceHierarchyType(BasePlotlyType): + + def __init__(self, plotly_name, **kwargs): + super().__init__(plotly_name, **kwargs) + + def _send_update(self, prop, val): + if self.parent: + self.parent._restyle_child(self, prop, val) + + +class BaseTraceType(BaseTraceHierarchyType): + def __init__(self, plotly_name, **kwargs): + super().__init__(plotly_name, **kwargs) + + self._hover_callbacks = [] + self._unhover_callbacks = [] + self._click_callbacks = [] + self._select_callbacks = [] + + # uid + # --- + @property + def uid(self) -> str: + raise NotImplementedError + + @uid.setter + def uid(self, val): + raise NotImplementedError + + # Hover + # ----- + def on_hover(self, + callback: typ.Callable[['BaseTraceType', Points, InputState], None], + append=False): + """ + Register callback to be called when the user hovers over a point from this trace + + Parameters + ---------- + callback + Callable that accepts 3 arguments + + - This trace + - Points object + - InputState object + + append : + + Returns + ------- + None + """ + if not append: + self._hover_callbacks.clear() + + if callback: + self._hover_callbacks.append(callback) + + def _dispatch_on_hover(self, points: Points, state: InputState): + for callback in self._hover_callbacks: + callback(self, points, state) + + # Unhover + # ------- + def on_unhover(self, callback: typ.Callable[['BaseTraceType', Points, InputState], None], append=False): + if not append: + self._unhover_callbacks.clear() + + if callback: + self._unhover_callbacks.append(callback) + + def _dispatch_on_unhover(self, points: Points, state: InputState): + for callback in self._unhover_callbacks: + callback(self, points, state) + + # Click + # ----- + def on_click(self, callback: typ.Callable[['BaseTraceType', Points, InputState], None], append=False): + if not append: + self._click_callbacks.clear() + if callback: + self._click_callbacks.append(callback) + + def _dispatch_on_click(self, points: Points, state: InputState): + for callback in self._click_callbacks: + callback(self, points, state) + + # Select + # ------ + def on_selected(self, + callback: typ.Callable[['BaseTraceType', Points, typ.Union[BoxSelector, LassoSelector]], None], + append=False): + if not append: + self._select_callbacks.clear() + + if callback: + self._select_callbacks.append(callback) + + def _dispatch_on_selected(self, points: Points, selector: typ.Union[BoxSelector, LassoSelector]): + for callback in self._select_callbacks: + callback(self, points, selector) + + +class BaseFrameHierarchyType(BasePlotlyType): + + def __init__(self, plotly_name, **kwargs): + super().__init__(plotly_name, **kwargs) + + def _send_update(self, prop, val): + # Frames are not supported by FrameWidget and updates are not propagated to parents + pass + diff --git a/plotly/basevalidators.py b/plotly/basevalidators.py new file mode 100644 index 00000000000..6b41ee59246 --- /dev/null +++ b/plotly/basevalidators.py @@ -0,0 +1,1270 @@ +import base64 +import numbers +import textwrap +import uuid +from importlib import import_module + +import io +from copy import deepcopy + +import numpy as np +import pandas as pd +import re + +# Utility functions +# ----------------- +def copy_to_contiguous_readonly_numpy_array(v, dtype=None, force_numeric=False): + + # Copy to numpy array and handle dtype param + # ------------------------------------------ + # If dtype was not specified then it will be passed to the numpy array constructor as None and the data type + # will be inferred automatically + + # TODO: support datetime dtype here and in widget serialization + numeric_kinds = ['u', 'i', 'f'] + + if not isinstance(v, np.ndarray): + new_v = np.array(v, order='C', dtype=dtype) + elif v.dtype.kind in numeric_kinds: + new_v = np.ascontiguousarray(v.astype(dtype)) + else: + new_v = v.copy() + + # Handle force numeric param + # -------------------------- + if force_numeric and new_v.dtype.kind not in numeric_kinds: # (un)signed int, or float + raise ValueError('Input value is not numeric and force_numeric parameter set to True') + + if dtype != 'unicode': + # Force non-numeric arrays to have object type + # -------------------------------------------- + # Here we make sure that non-numeric arrays have the object datatype. This works around cases like + # np.array([1, 2, '3']) where numpy converts the integers to strings and returns array of dtype '= self.min_val) + + if self.max_val is not None: + v_valid = np.logical_and(v_valid, v_array <= self.max_val) + + if not np.all(v_valid): + # Grab up to the first 10 invalid values + some_invalid_els = np.array(v, dtype='object')[np.logical_not(v_valid)][:10].tolist() + self.raise_invalid_elements(some_invalid_els) + + v = v_array # Always numpy array of float64 + else: + if not isinstance(v, numbers.Number): + self.raise_invalid_val(v) + + if (self.min_val is not None and not v >= self.min_val) or \ + (self.max_val is not None and not v <= self.max_val): + + self.raise_invalid_val(v) + + return v + + +class IntegerValidator(BaseValidator): + """ + "integer": { + "description": "An integer or an integer inside a string. When applicable, values greater (less) than `max` (`min`) are coerced to the `dflt`.", + "requiredOpts": [], + "otherOpts": [ + "dflt", + "min", + "max", + "arrayOk" + ] + }, + """ + def __init__(self, plotly_name, parent_name, min=None, max=None, array_ok=False, **_): + super().__init__(plotly_name=plotly_name, parent_name=parent_name) + + # Handle min + if min is None and max is not None: + # Max was specified, so make min -inf + self.min_val = np.iinfo(np.int32).min + else: + self.min_val = min + + # Handle max + if max is None and min is not None: + # Min was specified, so make min inf + self.max_val = np.iinfo(np.int32).max + else: + self.max_val = max + + self.array_ok = array_ok + + def description(self): + desc = """\ + The '{plotly_name}' property is a integer and may be specified as:""".format(plotly_name=self.plotly_name) + + if self.min_val is None and self.max_val is None: + desc = desc + """ + - An int (or float that will be cast to an int)""" + else: + desc = desc + """ + - An int (or float that will be cast to an int) in the interval [{min_val}, {max_val}]""".format( + min_val=self.min_val, + max_val=self.max_val) + + if self.array_ok: + desc = desc + """ + - A tuple, list, or one-dimensional numpy array of the above""" + + return desc + + def validate_coerce(self, v): + if v is None: + # Pass None through + pass + elif self.array_ok and is_array(v): + + try: + v_array = copy_to_contiguous_readonly_numpy_array(v, dtype='int32') + + except (ValueError, TypeError, OverflowError) as ve: + self.raise_invalid_val(v) + + v_valid = np.ones(v_array.shape, dtype='bool') + if self.min_val is not None: + v_valid = np.logical_and(v_valid, v_array >= self.min_val) + + if self.max_val is not None: + v_valid = np.logical_and(v_valid, v_array <= self.max_val) + + if not np.all(v_valid): + invalid_els = np.array(v, dtype='object')[np.logical_not(v_valid)][:10].tolist() + self.raise_invalid_elements(invalid_els) + + v = v_array + else: + try: + if not isinstance(v, numbers.Number): + # don't let int() cast strings to ints + self.raise_invalid_val(v) + + v_int = int(v) + except (ValueError, TypeError, OverflowError) as ve: + self.raise_invalid_val(v) + + if (self.min_val is not None and not v >= self.min_val) or \ + (self.max_val is not None and not v <= self.max_val): + self.raise_invalid_val(v) + + v = v_int + + return v + + +class StringValidator(BaseValidator): + """ + "string": { + "description": "A string value. Numbers are converted to strings except for attributes with `strict` set to true.", + "requiredOpts": [], + "otherOpts": [ + "dflt", + "noBlank", + "strict", + "arrayOk", + "values" + ] + }, + """ + def __init__(self, plotly_name, parent_name, no_blank=False, strict=False, array_ok=False, values=None, **_): + super().__init__(plotly_name=plotly_name, parent_name=parent_name) + self.no_blank = no_blank + self.strict = strict # Not implemented. We're always strict + self.array_ok = array_ok + self.values = values + + def description(self): + desc = """\ + The '{plotly_name}' property is a string and must be specified as:""".format(plotly_name=self.plotly_name) + + if self.no_blank: + desc = desc + """ + - A non-empty string""" + elif self.values: + valid_str = '\n'.join(textwrap.wrap(repr(self.values), + subsequent_indent=' ' * 12, + break_on_hyphens=False)) + + desc = desc + """ + - One of the following strings: + {valid_str}""".format(valid_str=valid_str) + else: + desc = desc + """ + - A string""" + + if self.array_ok: + desc = desc + """ + - A tuple, list, or one-dimensional numpy array of the above""" + + return desc + + def validate_coerce(self, v): + if v is None: + # Pass None through + pass + elif self.array_ok and is_array(v): + + # Make sure all elements are strings. Is there a more efficient way to do this in numpy? + invalid_els = [e for e in v if not isinstance(e, str)] + if invalid_els: + self.raise_invalid_elements(invalid_els) + + v = copy_to_contiguous_readonly_numpy_array(v, dtype='unicode') + + if self.no_blank: + invalid_els = v[v == ''][:10].tolist() + if invalid_els: + self.raise_invalid_elements(invalid_els) + + if self.values: + invalid_els = v[np.logical_not(np.isin(v, self.values))][:10].tolist() + if invalid_els: + self.raise_invalid_elements(invalid_els) + else: + if not isinstance(v, str): + self.raise_invalid_val(v) + + if self.no_blank and len(v) == 0: + self.raise_invalid_val(v) + + if self.values and v not in self.values: + self.raise_invalid_val(v) + + return v + + +class ColorValidator(BaseValidator): + """ + "color": { + "description": "A string describing color. Supported formats: - hex (e.g. '#d3d3d3') - rgb (e.g. 'rgb(255, 0, 0)') - rgba (e.g. 'rgb(255, 0, 0, 0.5)') - hsl (e.g. 'hsl(0, 100%, 50%)') - hsv (e.g. 'hsv(0, 100%, 100%)') - named colors (full list: http://www.w3.org/TR/css3-color/#svg-color)", + "requiredOpts": [], + "otherOpts": [ + "dflt", + "arrayOk" + ] + }, + """ + re_hex = re.compile('#([A-Fa-f0-9]{6}|[A-Fa-f0-9]{3})') + re_rgb_etc = re.compile('(rgb|hsl|hsv)a?\([\d.]+%?(,[\d.]+%?){2,3}\)') + + named_colors = [ + "aliceblue", "antiquewhite", "aqua", "aquamarine", "azure", "beige", "bisque", "black", "blanchedalmond", + "blue", "blueviolet", "brown", "burlywood", "cadetblue", "chartreuse", "chocolate", "coral", "cornflowerblue", + "cornsilk", "crimson", "cyan", "darkblue", "darkcyan", "darkgoldenrod", "darkgray", "darkgrey", "darkgreen", + "darkkhaki", "darkmagenta", "darkolivegreen", "darkorange", "darkorchid", "darkred", "darksalmon", + "darkseagreen", "darkslateblue", "darkslategray", "darkslategrey", "darkturquoise", "darkviolet", "deeppink", + "deepskyblue", "dimgray", "dimgrey", "dodgerblue", "firebrick", "floralwhite", "forestgreen", "fuchsia", + "gainsboro", "ghostwhite", "gold", "goldenrod", "gray", "grey", "green", "greenyellow", "honeydew", "hotpink", + "indianred", "indigo", "ivory", "khaki", "lavender", "lavenderblush", "lawngreen", "lemonchiffon", "lightblue", + "lightcoral", "lightcyan", "lightgoldenrodyellow", "lightgray", "lightgrey", "lightgreen", "lightpink", + "lightsalmon", "lightseagreen", "lightskyblue", "lightslategray", "lightslategrey", "lightsteelblue", + "lightyellow", "lime", "limegreen", "linen", "magenta", "maroon", "mediumaquamarine", "mediumblue", + "mediumorchid", "mediumpurple", "mediumseagreen", "mediumslateblue", "mediumspringgreen", "mediumturquoise", + "mediumvioletred", "midnightblue", "mintcream", "mistyrose", "moccasin", "navajowhite", "navy", "oldlace", + "olive", "olivedrab", "orange", "orangered", "orchid", "palegoldenrod", "palegreen", "paleturquoise", + "palevioletred", "papayawhip", "peachpuff", "peru", "pink", "plum", "powderblue", "purple", "red", "rosybrown", + "royalblue", "saddlebrown", "salmon", "sandybrown", "seagreen", "seashell", "sienna", "silver", "skyblue", + "slateblue", "slategray", "slategrey", "snow", "springgreen", "steelblue", "tan", "teal", "thistle", "tomato", + "turquoise", "violet", "wheat", "white", "whitesmoke", "yellow", "yellowgreen"] + + def __init__(self, plotly_name, parent_name, array_ok=False, colorscale_path=None, **_): + super().__init__(plotly_name=plotly_name, parent_name=parent_name) + self.colorscale_path = colorscale_path + self.array_ok = array_ok + + def numbers_allowed(self): + return self.colorscale_path is not None + + def description(self): + + named_clrs_str = '\n'.join(textwrap.wrap(', '.join(self.named_colors), width=80, subsequent_indent=' ' * 12)) + + valid_color_description = """\ + The '{plotly_name}' property is a color and may be specified as: + - A hex string (e.g. '#ff0000') + - An rgb/rgba string (e.g. 'rgb(255,0,0)') + - An hsl/hsla string (e.g. 'hsl(0,100%,50%)') + - An hsv/hsva string (e.g. 'hsv(0,100%,100%)') + - A named CSS color: + {clrs}""".format( + plotly_name=self.plotly_name, + clrs=named_clrs_str) + + if self.colorscale_path: + valid_color_description = valid_color_description + """ + - A number that will be interpreted as a color according to {colorscale_path}""".format( + colorscale_path=self.colorscale_path) + + if self.array_ok: + valid_color_description = valid_color_description + """ + - A list or array of any of the above""" + + return valid_color_description + + def validate_coerce(self, v): + if v is None: + # Pass None through + pass + elif self.array_ok and is_array(v): + v_array = copy_to_contiguous_readonly_numpy_array(v) + if self.numbers_allowed() and v_array.dtype.kind in ['u', 'i', 'f']: # (un)signed int or float + # All good + v = v_array + else: + validated_v = [ColorValidator.perform_validate_coerce(e, allow_number=self.numbers_allowed()) + for e in v] + + invalid_els = [el for el, validated_el in zip(v, validated_v) if validated_el is None] + if invalid_els: + self.raise_invalid_elements(invalid_els) + + # ### Check that elements have valid colors types ### + if self.numbers_allowed(): + v = copy_to_contiguous_readonly_numpy_array(validated_v, dtype='object') + else: + v = copy_to_contiguous_readonly_numpy_array(validated_v, dtype='unicode') + + else: + # Validate scalar color + validated_v = ColorValidator.perform_validate_coerce(v, allow_number=self.numbers_allowed()) + if validated_v is None: + self.raise_invalid_val(v) + + v = validated_v + + return v + + @staticmethod + def perform_validate_coerce(v, allow_number=None): + + if isinstance(v, numbers.Number) and allow_number: + # If allow_numbers then any number is ok + return v + elif not isinstance(v, str): + return None + else: + # Remove spaces so regexes don't need to bother with them. + v = v.replace(' ', '') + v = v.lower() + + if ColorValidator.re_hex.fullmatch(v): + # valid hex color (e.g. #f34ab3) + return v + elif ColorValidator.re_rgb_etc.fullmatch(v): + # Valid rgb(a), hsl(a), hsv(a) color (e.g. rgba(10, 234, 200, 50%) + return v + elif v in ColorValidator.named_colors: + # Valid named color (e.g. 'coral') + return v + else: + # Not a valid color + return None + + +class ColorlistValidator(BaseValidator): + """ + "colorlist": { + "description": "A list of colors. Must be an {array} containing valid colors.", + "requiredOpts": [], + "otherOpts": [ + "dflt" + ] + } + """ + def __init__(self, plotly_name, parent_name, **_): + super().__init__(plotly_name=plotly_name, parent_name=parent_name) + + def description(self): + return ("""\ + The '{plotly_name}' property is a colorlist that may be specified as a tuple, list, + or one-dimensional numpy array of valid color strings""".format(plotly_name=self.plotly_name)) + + def validate_coerce(self, v): + + if v is None: + # Pass None through + pass + elif is_array(v): + validated_v = [ColorValidator.perform_validate_coerce(e, allow_number=False) for e in v] + + invalid_els = [el for el, validated_el in zip(v, validated_v) if validated_el is None] + if invalid_els: + self.raise_invalid_elements(invalid_els) + + v = copy_to_contiguous_readonly_numpy_array(validated_v, dtype='unicode') + else: + self.raise_invalid_val(v) + return v + + +class ColorscaleValidator(BaseValidator): + """ + "colorscale": { + "description": "A Plotly colorscale either picked by a name: (any of Greys, YlGnBu, Greens, YlOrRd, Bluered, RdBu, Reds, Blues, Picnic, Rainbow, Portland, Jet, Hot, Blackbody, Earth, Electric, Viridis ) customized as an {array} of 2-element {arrays} where the first element is the normalized color level value (starting at *0* and ending at *1*), and the second item is a valid color string.", + "requiredOpts": [], + "otherOpts": [ + "dflt" + ] + }, + """ + + named_colorscales = ['Greys', 'YlGnBu', 'Greens', 'YlOrRd', 'Bluered', 'RdBu', 'Reds', 'Blues', 'Picnic', + 'Rainbow', 'Portland', 'Jet', 'Hot', 'Blackbody', 'Earth', 'Electric', 'Viridis'] + + def __init__(self, plotly_name, parent_name, **_): + super().__init__(plotly_name=plotly_name, parent_name=parent_name) + + def description(self): + desc = """\ + The '{plotly_name}' property is a colorscale and may be specified as: + - A list of 2-element lists where the first element is the normalized color level value + (starting at 0 and ending at 1), and the second item is a valid color string. + (e.g. [[0.5, 'red'], [1.0, 'rgb(0, 0, 255)']]) + - One of the following named colorscales: + ['Greys', 'YlGnBu', 'Greens', 'YlOrRd', 'Bluered', 'RdBu', 'Reds', 'Blues', 'Picnic', + 'Rainbow', 'Portland', 'Jet', 'Hot', 'Blackbody', 'Earth', 'Electric', 'Viridis'] + """.format(plotly_name=self.plotly_name) + + return desc + + def validate_coerce(self, v): + v_valid = False + + if v is None: + # Pass None through + pass + if v is None: + v_valid = True + elif isinstance(v, str): + v_match = [el for el in ColorscaleValidator.named_colorscales if el.lower() == v.lower()] + if v_match: + v_valid = True + v = v_match[0] + + elif is_array(v) and len(v) > 0: + invalid_els = [e for e in v + if not is_array(e) or + len(e) != 2 or + not isinstance(e[0], numbers.Number) or + not (0 <= e[0] <= 1) or + not isinstance(e[1], str) or + ColorValidator.perform_validate_coerce(e[1]) is None] + if len(invalid_els) == 0: + v_valid = True + + # Convert to tuple of tuples so colorscale is immutable + v = tuple([tuple([e[0], ColorValidator.perform_validate_coerce(e[1])]) for e in v]) + + if not v_valid: + self.raise_invalid_val(v) + return v + + +class AngleValidator(BaseValidator): + """ + "angle": { + "description": "A number (in degree) between -180 and 180.", + "requiredOpts": [], + "otherOpts": [ + "dflt" + ] + }, + """ + def __init__(self, plotly_name, parent_name, **_): + super().__init__(plotly_name=plotly_name, parent_name=parent_name) + + def description(self): + desc = """\ + The '{plotly_name}' property is a angle (in degrees) that may be specified as a number between -180 and 180. + Numeric values outside this range are converted to the equivalent value (e.g. 270 is converted to -90). + """.format(plotly_name=self.plotly_name) + + return desc + + def validate_coerce(self, v): + if v is None: + # Pass None through + pass + elif not isinstance(v, numbers.Number): + self.raise_invalid_val(v) + else: + # Normalize v onto the interval [-180, 180) + v = (v + 180) % 360 - 180 + + return v + + +class SubplotidValidator(BaseValidator): + """ + "subplotid": { + "description": "An id string of a subplot type (given by dflt), optionally followed by an integer >1. e.g. if dflt='geo', we can have 'geo', 'geo2', 'geo3', ...", + "requiredOpts": [ + "dflt" + ], + "otherOpts": [] + }, + """ + def __init__(self, plotly_name, parent_name, dflt, **_): + super().__init__(plotly_name=plotly_name, parent_name=parent_name) + self.base = dflt + self.regex = dflt + "(\d*)" + + def description(self): + + desc = """\ + The '{plotly_name}' property is an identifier of a particular subplot, of type '{base}', that + may be specified as the string '{base}' optionally followed by an integer > 1 + (e.g. '{base}', '{base}2', '{base}3', etc.) + """.format(plotly_name=self.plotly_name, base=self.base) + return desc + + def validate_coerce(self, v): + if v is None: + v = self.base + elif not isinstance(v, str): + self.raise_invalid_val(v) + else: + if not re.fullmatch(self.regex, v): + is_valid = False + else: + digit_str = re.fullmatch(self.regex, v).group(1) + if len(digit_str) > 0 and int(digit_str) in [0, 1]: + is_valid = False + else: + is_valid = True + + if not is_valid: + self.raise_invalid_val(v) + return v + + +class FlaglistValidator(BaseValidator): + """ + "flaglist": { + "description": "A string representing a combination of flags (order does not matter here). Combine any of the available `flags` with *+*. (e.g. ('lines+markers')). Values in `extras` cannot be combined.", + "requiredOpts": [ + "flags" + ], + "otherOpts": [ + "dflt", + "extras", + "arrayOk" + ] + }, + """ + def __init__(self, plotly_name, parent_name, flags, extras=None, array_ok=False, **_): + super().__init__(plotly_name=plotly_name, parent_name=parent_name) + self.flags = flags + self.extras = extras if extras is not None else [] + self.array_ok = array_ok + + self.all_flags = self.flags + self.extras + + def description(self): + + desc = ("""\ + The '{plotly_name}' property is a flaglist and may be specified as a string containing:""" + ).format(plotly_name=self.plotly_name) + + # Flags + desc = desc + (""" + - Any combination of {flags} joined with '+' characters (e.g. '{eg_flag}')""" + ).format(flags=self.flags, + eg_flag='+'.join(self.flags[:2])) + + # Extras + if self.extras: + desc = desc + (""" + OR exactly one of {extras} (e.g. '{eg_extra}')""" + ).format(extras=self.extras, + eg_extra=self.extras[-1]) + + if self.array_ok: + desc = desc + """ + - A list or array of the above""" + + return desc + + def perform_validate_coerce(self, v): + if not isinstance(v, str): + return None + + split_vals = [e.strip() for e in re.split('[,+]', v)] + + all_flags_valid = [f for f in split_vals if f not in self.all_flags] == [] + has_extras = [f for f in split_vals if f in self.extras] != [] + + is_valid = all_flags_valid and (not has_extras or len(split_vals) == 1) + if is_valid: + return '+'.join(split_vals) + else: + return None + + def validate_coerce(self, v): + if v is None: + # Pass None through + pass + elif self.array_ok and is_array(v): + + validated_v = [self.perform_validate_coerce(e) for e in v] # Coerce individual strings + + invalid_els = [el for el, validated_el in zip(v, validated_v) if validated_el is None] + if invalid_els: + self.raise_invalid_elements(invalid_els) + + v = copy_to_contiguous_readonly_numpy_array(validated_v, dtype='unicode') + else: + + validated_v = self.perform_validate_coerce(v) + if validated_v is None: + self.raise_invalid_val(v) + + v = validated_v + + return v + + +class AnyValidator(BaseValidator): + """ + "any": { + "description": "Any type.", + "requiredOpts": [], + "otherOpts": [ + "dflt", + "values", + "arrayOk" + ] + }, + """ + def __init__(self, plotly_name, parent_name, values=None, array_ok=False, **_): + super().__init__(plotly_name=plotly_name, parent_name=parent_name) + self.values = values + self.array_ok = array_ok + + def description(self): + + desc = """\ + The '{plotly_name}' property accepts values of any type + """.format(plotly_name=self.plotly_name) + return desc + + def validate_coerce(self, v): + if v is None: + # Pass None through + pass + elif self.array_ok and is_array(v): + v = copy_to_contiguous_readonly_numpy_array(v, dtype='object') + + return v + + +class InfoArrayValidator(BaseValidator): + """ + "info_array": { + "description": "An {array} of plot information.", + "requiredOpts": [ + "items" + ], + "otherOpts": [ + "dflt", + "freeLength" + ] + } + """ + def __init__(self, plotly_name, parent_name, items, free_length=None, **_): + super().__init__(plotly_name=plotly_name, parent_name=parent_name) + self.items = items + + self.item_validators = [] + for i, item in enumerate(self.items): + item_validator = InfoArrayValidator.build_validator(item, '{plotly_name}[{i}]'.format(plotly_name=plotly_name, i=i), parent_name) + self.item_validators.append(item_validator) + + self.free_length = free_length + + def description(self): + upto = ' up to' if self.free_length else '' + desc = """\ + The '{plotly_name}' property is an info array that may be specified as a list or tuple of{upto} + {N} elements such that: + """.format(plotly_name=self.plotly_name, upto=upto, N=len(self.item_validators)) + + for i, item_validator in enumerate(self.item_validators): + el_desc = ('\n' + ' ' * 12).join([line.strip() for line in item_validator.description().split('\n')]) + desc = desc + """ + ({i}) {el_desc} + """.format(i=i, el_desc=el_desc) + + return desc + + @staticmethod + def build_validator(validator_info, plotly_name, parent_name): + datatype = validator_info['valType'] # type: str + validator_classname = datatype.title().replace('_', '') + 'Validator' + validator_class = eval(validator_classname) + + kwargs = {k: validator_info[k] for k in validator_info + if k not in ['valType', 'description', 'role']} + + return validator_class(plotly_name=plotly_name, parent_name=parent_name, **kwargs) + + def validate_coerce(self, v): + if v is None: + # Pass None through + pass + elif not isinstance(v, (list, tuple)): + self.raise_invalid_val(v) + elif not self.free_length and len(v) != len(self.item_validators): + self.raise_invalid_val(v) + elif self.free_length and len(v) > len(self.item_validators): + self.raise_invalid_val(v) + else: + # We have a list or tuple of the correct length + v = list(v) + for i, (el, validator) in enumerate(zip(v, self.item_validators)): + # Validate coerce elements + v[i] = validator.validate_coerce(el) + + return v + + +class ImageUriValidator(BaseValidator): + _PIL = None + + try: + _PIL = import_module('PIL') + except ModuleNotFoundError: + pass + + def __init__(self, plotly_name, parent_name, **_): + super().__init__(plotly_name=plotly_name, parent_name=parent_name) + + def description(self): + + desc = """\ + The '{plotly_name}' property is an image URI that may be specified as: + - A remote image URI string (e.g. 'http://www.somewhere.com/image.png') + - A local image URI string (e.g. 'file:////somewhere/image.png') + - A data URI image string (e.g. 'data:image/png;base64,iVBORw0KGgoAAAANSU') + - A PIL.Image.Image object which will be immediately converted to a data URI image string + See http://pillow.readthedocs.io/en/latest/reference/Image.html + """.format(plotly_name=self.plotly_name) + return desc + + def validate_coerce(self, v): + if v is None: + pass + elif isinstance(v, str): + # Future possibilities: + # - Detect filesystem system paths and convert to URI + # - Validate either url or data uri + pass + elif self._PIL and isinstance(v, self._PIL.Image.Image): + # Convert PIL image to png data uri string + in_mem_file = io.BytesIO() + v.save(in_mem_file, format="PNG") + in_mem_file.seek(0) + img_bytes = in_mem_file.read() + base64_encoded_result_bytes = base64.b64encode(img_bytes) + base64_encoded_result_str = base64_encoded_result_bytes.decode('ascii') + v = 'data:image/png;base64,{base64_encoded_result_str}'.format( + base64_encoded_result_str=base64_encoded_result_str) + else: + self.raise_invalid_val(v) + + return v + + +class CompoundValidator(BaseValidator): + def __init__(self, plotly_name, parent_name, data_class, data_docs): + super().__init__(plotly_name=plotly_name, parent_name=parent_name) + self.data_class = data_class + self.data_docs = data_docs + + @staticmethod + def get_constructor_params_str(data_class): + params_match = re.search("Parameters\n\W*-+\n\W*(.*?)(Returns|$)", + str(data_class.__init__.__doc__), + flags=re.DOTALL) + + if params_match is not None: + param_descs = params_match.groups()[0] + + # Increase indent by 4 spaces + param_descs_indented = ('\n' + ' ' * 4).join(param_descs.split('\n')) + + return param_descs_indented + else: + return '' + + def description(self): + + desc = ("""\ + The '{plotly_name}' property is an instance of {data_class} + that may be specified as: + - An instance of {data_class} + - A dict of string/value properties that will be passed to the + {data_class} constructor + + Supported dict properties: + {constructor_params_str}""" + ).format(plotly_name=self.plotly_name, + data_class=type_str(self.data_class), + constructor_params_str=self.data_docs) + + return desc + + def validate_coerce(self, v): + if isinstance(self.data_class, str): + raise ValueError("Invalid data_class of type 'string': {data_class}" + .format(data_class = self.data_class)) + + if v is None: + v = self.data_class() + + elif isinstance(v, dict): + v = self.data_class(**v) + + elif isinstance(v, self.data_class): + # Copy object + v = self.data_class(**v._props) + else: + self.raise_invalid_val(v) + + v._prop_name = self.plotly_name + return v + + +class CompoundArrayValidator(BaseValidator): + def __init__(self, plotly_name, parent_name, element_class, element_docs): + super().__init__(plotly_name=plotly_name, parent_name=parent_name) + self.data_class = element_class + self.data_docs = element_docs + + def description(self): + + desc = ("""\ + The '{plotly_name}' property is a tuple of instances of {data_class} that may be specified as: + - A list or tuple of instances of {data_class} + - A list or tuple of dicts of string/value properties that will be passed to the {data_class} constructor + + Supported dict properties: + {constructor_params_str}""" + ).format(plotly_name=self.plotly_name, + data_class=type_str(self.data_class), + constructor_params_str=self.data_docs) + + return desc + + def validate_coerce(self, v): + + if isinstance(self.data_class, str): + raise ValueError("Invalid data_class of type 'string': {data_class}" + .format(data_class = self.data_class)) + + if v is None: + v = () + + elif isinstance(v, (list, tuple)): + res = [] + invalid_els = [] + for v_el in v: + if isinstance(v_el, self.data_class): + res.append(v_el) + elif isinstance(v_el, dict): + res.append(self.data_class(**v_el)) + else: + res.append(None) + invalid_els.append(v_el) + + if invalid_els: + self.raise_invalid_elements(invalid_els) + + v = tuple(res) + + elif not isinstance(v, str): + self.raise_invalid_val(v) + + return v + + +class BaseDataValidator(BaseValidator): + def __init__(self, class_map, plotly_name, parent_name): + super().__init__(plotly_name=plotly_name, parent_name=parent_name) + self.class_map = class_map + + def description(self): + + trace_types = str(list(self.class_map.keys())) + + trace_types_wrapped = '\n'.join(textwrap.wrap(trace_types, + subsequent_indent=' ' * 21, + width=80 - 8)) + + desc = ("""\ + The '{plotly_name}' property is a tuple of trace instances that may be specified as: + - A list or tuple of trace instances + (e.g. [Scatter(...), Bar(...)]) + - A list or tuple of dicts of string/value properties where: + - The 'type' property specifies the trace type + One of: {trace_types} + + - All remaining properties are passed to the constructor of the specified trace type + + (e.g. [{{'type': 'scatter', ...}}, {{'type': 'bar, ...}}])""" + ).format(plotly_name=self.plotly_name, trace_types=trace_types_wrapped) + + return desc + + def validate_coerce(self, v): + + if v is None: + v = () + elif isinstance(v, (list, tuple)): + trace_classes = tuple(self.class_map.values()) + + res = [] + invalid_els = [] + for v_el in v: + if isinstance(v_el, trace_classes): + res.append(v_el) + elif isinstance(v_el, dict): + v_copy = deepcopy(v_el) + + if 'type' in v_copy: + trace_type = v_copy.pop('type') + else: + trace_type = 'scatter' + + if trace_type not in self.class_map: + res.append(None) + invalid_els.append(v_el) + else: + trace = self.class_map[trace_type](**v_copy) + res.append(trace) + else: + res.append(None) + invalid_els.append(v_el) + + if invalid_els: + self.raise_invalid_elements(invalid_els) + + v = tuple(res) + + # Add UIDs if not set. + # If UID is set then it's the users responsibility to make sure UIDs are unique + for trace in v: + if trace.uid is None: + trace.uid = str(uuid.uuid1()) + + else: + self.raise_invalid_val(v) + + return v diff --git a/plotly/basewidget.py b/plotly/basewidget.py new file mode 100644 index 00000000000..65794d65cd7 --- /dev/null +++ b/plotly/basewidget.py @@ -0,0 +1,282 @@ +import ipywidgets as widgets +from traitlets import List, Unicode, Dict, observe, Integer, Undefined +from plotly.basedatatypes import BaseFigure +from plotly.callbacks import BoxSelector, LassoSelector, InputState, Points +from plotly.serializers import custom_serializers + + +@widgets.register +class BaseFigureWidget(BaseFigure, widgets.DOMWidget): + + # Widget Traits + # ------------- + _view_name = Unicode('FigureView').tag(sync=True) + _view_module = Unicode('plotlywidget').tag(sync=True) + _model_name = Unicode('FigureModel').tag(sync=True) + _model_module = Unicode('plotlywidget').tag(sync=True) + + # Data properties for front end + # Note: These are only automatically synced on full assignment, not on mutation + _layout = Dict().tag(sync=True, **custom_serializers) + _data = List().tag(sync=True, **custom_serializers) + + # Python -> JS message properties + _py2js_addTraces = List(trait=Dict(), + allow_none=True).tag(sync=True, **custom_serializers) + + _py2js_restyle = List(allow_none=True).tag(sync=True, **custom_serializers) + _py2js_relayout = Dict(allow_none=True).tag(sync=True, **custom_serializers) + _py2js_update = List(allow_none=True).tag(sync=True, **custom_serializers) + _py2js_animate = List(allow_none=True).tag(sync=True, **custom_serializers) + + _py2js_deleteTraces = Dict(allow_none=True).tag(sync=True, **custom_serializers) + _py2js_moveTraces = List(allow_none=True).tag(sync=True, **custom_serializers) + + _py2js_removeLayoutProps = List(allow_none=True).tag(sync=True, **custom_serializers) + _py2js_removeStyleProps = List(allow_none=True).tag(sync=True, **custom_serializers) + _py2js_requestSvg = Unicode(allow_none=True).tag(sync=True) + + # JS -> Python message properties + _js2py_styleDelta = List(allow_none=True).tag(sync=True, **custom_serializers) + _js2py_layoutDelta = Dict(allow_none=True).tag(sync=True, **custom_serializers) + _js2py_restyle = List(allow_none=True).tag(sync=True, **custom_serializers) + _js2py_relayout = Dict(allow_none=True).tag(sync=True, **custom_serializers) + _js2py_update = Dict(allow_none=True).tag(sync=True, **custom_serializers) + + # For plotly_select/hover/unhover/click + _js2py_pointsCallback = Dict(allow_none=True).tag(sync=True, **custom_serializers) + + # Message tracking + _last_relayout_msg_id = Integer(0).tag(sync=True) + _last_restyle_msg_id = Integer(0).tag(sync=True) + + # Constructor + # ----------- + def __init__(self, data=None, layout=None, frames=None): + # TODO: error if frames is not None + # Validate Frames + # --------------- + if frames: + BaseFigureWidget._display_frames_error() + + self._frame_objs = None + + # Call superclass constructors + # ---------------------------- + # Note: We rename layout to layout_plotly because ipywidget also accepts a layout parameter + # We map a layout_ipywidget property to the layout property of the ipywidget + super().__init__(data=data, layout_plotly=layout) + + # Messages + # -------- + self.on_msg(self._handler_messages) + + # ### Trait methods ### + @observe('_js2py_styleDelta') + def handler_plotly_styleDelta(self, change): + deltas = change['new'] + self._js2py_styleDelta = None + + if not deltas: + return + + msg_id = deltas[0].get('_restyle_msg_id', None) + # print(f'styleDelta: {msg_id} == {self._last_restyle_msg_id}') + if msg_id == self._last_restyle_msg_id: + for delta in deltas: + trace_uid = delta['uid'] + + # Remove message id + # pprint(delta) + # print('Processing styleDelta') + + trace_uids = [trace.uid for trace in self.data] + trace_index = trace_uids.index(trace_uid) + uid_trace = self.data[trace_index] + delta_transform = BaseFigure.transform_data(uid_trace._prop_defaults, delta) + + removed_props = self._remove_overlapping_props(uid_trace._props, uid_trace._prop_defaults) + + if removed_props: + # print(f'Removed_props: {removed_props}') + self._py2js_removeStyleProps = [removed_props, trace_index] + self._py2js_removeStyleProps = None + + # print(delta_transform) + self._dispatch_change_callbacks_restyle(delta_transform, [trace_index]) + + self._restyle_in_process = False + while self._waiting_restyle_callbacks: + # Call callbacks + self._waiting_restyle_callbacks.pop()() + + @observe('_js2py_restyle') + def handler_js2py_restyle(self, change): + restyle_msg = change['new'] + self._js2py_restyle = None + + if not restyle_msg: + return + + self.restyle(*restyle_msg) + + @observe('_js2py_update') + def handler_js2py_update(self, change): + update_msg = change['new'] + self._js2py_update = None + + if not update_msg: + return + + # print('Update (JS->Py):') + # pprint(update_msg) + + style = update_msg['data'][0] + trace_indexes = update_msg['data'][1] + layout = update_msg['layout'] + + self.update(style=style, layout=layout, trace_indexes=trace_indexes) + + @observe('_js2py_layoutDelta') + def handler_plotly_layoutDelta(self, change): + delta = change['new'] + self._js2py_layoutDelta = None + + if not delta: + return + + msg_id = delta.get('_relayout_msg_id') + # print(f'layoutDelta: {msg_id} == {self._last_relayout_msg_id}') + if msg_id == self._last_relayout_msg_id: + + # print('Processing layoutDelta') + # print('layoutDelta: {deltas}'.format(deltas=delta)) + delta_transform = self.transform_data(self._layout_defaults, delta) + # print(f'delta_transform: {delta_transform}') + + # No relayout messages in process. Handle removing overlapping properties + removed_props = self._remove_overlapping_props(self._layout, self._layout_defaults) + if removed_props: + # print(f'Removed_props: {removed_props}') + self._py2js_removeLayoutProps = removed_props + self._py2js_removeLayoutProps = None + + self._dispatch_change_callbacks_relayout(delta_transform) + self._relayout_in_process = False + while self._waiting_relayout_callbacks: + # Call callbacks + self._waiting_relayout_callbacks.pop()() + + @observe('_js2py_relayout') + def handler_js2py_relayout(self, change): + relayout_data = change['new'] + # print('Relayout (JS->Py):') + # pprint(relayout_data) + + self._js2py_relayout = None + + if not relayout_data: + return + + if 'lastInputTime' in relayout_data: + # Remove 'lastInputTime'. Seems to be an internal plotly property that is introduced for some plot types + relayout_data.pop('lastInputTime') + + self.relayout(relayout_data) + + @observe('_js2py_pointsCallback') + def handler_plotly_pointsCallback(self, change): + callback_data = change['new'] + self._js2py_pointsCallback = None + + if not callback_data: + return + + # Get event type + # -------------- + event_type = callback_data['event_type'] + + # Build Selector Object + # --------------------- + if callback_data.get('selector', None): + selector_data = callback_data['selector'] + selector_type = selector_data['type'] + if selector_type == 'box': + selector = BoxSelector(**selector_data) + elif selector_type == 'lasso': + selector = LassoSelector(**selector_data) + else: + raise ValueError('Unsupported selector type: %s' % selector_type) + else: + selector = None + + # Build State Object + # ------------------ + if callback_data.get('state', None): + state_data = callback_data['state'] + state = InputState(**state_data) + else: + state = None + + # Build Trace Points Dictionary + # ----------------------------- + points_data = callback_data['points'] + trace_points = {trace_ind: {'point_inds': [], + 'xs': [], + 'ys': [], + 'trace_name': self._data_objs[trace_ind].plotly_name, + 'trace_index': trace_ind} + for trace_ind in range(len(self._data_objs))} + + for x, y, point_ind, trace_ind in zip(points_data['xs'], + points_data['ys'], + points_data['pointNumbers'], + points_data['curveNumbers']): + + trace_dict = trace_points[trace_ind] + trace_dict['xs'].append(x) + trace_dict['ys'].append(y) + trace_dict['point_inds'].append(point_ind) + + # Dispatch callbacks + # ------------------ + for trace_ind, trace_points_data in trace_points.items(): + points = Points(**trace_points_data) + trace = self.data[trace_ind] # type: BaseTraceType + + if event_type == 'plotly_click': + trace._dispatch_on_click(points, state) + elif event_type == 'plotly_hover': + trace._dispatch_on_hover(points, state) + elif event_type == 'plotly_unhover': + trace._dispatch_on_unhover(points, state) + elif event_type == 'plotly_selected': + trace._dispatch_on_selected(points, selector) + + # Custom Messages + # --------------- + def _handler_messages(self, widget, content, buffers): + """Handle a msg from the front-end. + """ + if content.get('event', '') == 'svg': + req_id = content['req_id'] + svg_uri = content['svg_uri'] + self._do_save_image(req_id, svg_uri) + + # Validate No Frames + # ------------------ + @property + def frames(self): + return self._frame_objs + + @frames.setter + def frames(self, new_frames): + if new_frames: + BaseFigureWidget._display_frames_error() + + @staticmethod + def _display_frames_error(): + msg = ("Frames are not supported by the datatypes.FigureWidget class.\n" + "Note: Frames are supported by the datatypes.Figure class") + + raise ValueError(msg) diff --git a/plotly/callbacks.py b/plotly/callbacks.py new file mode 100644 index 00000000000..1f3653cde1a --- /dev/null +++ b/plotly/callbacks.py @@ -0,0 +1,171 @@ +import typing as typ + + +class InputState: + def __init__(self, ctrl=None, alt=None, shift=None, meta=None, button=None, buttons=None, **_): + self._ctrl = ctrl + self._alt = alt + self._meta = meta + self._shift = shift + self._button = button + self._buttons = buttons + + def __repr__(self): + return """\ +InputState(ctrl={ctrl}, + alt={alt}, + shift={shift}, + meta={meta}, + button={button}, + buttons={buttons})""" + + @property + def alt(self) -> bool: + """ + Whether alt key pressed + + Returns + ------- + bool + """ + return self._alt + + @property + def ctrl(self) -> bool: + """ + Whether ctrl key pressed + + Returns + ------- + bool + """ + return self._ctrl + + @property + def shift(self) -> bool: + """ + Whether shift key pressed + + Returns + ------- + bool + """ + return self._shift + + @property + def meta(self) -> bool: + """ + Whether meta key pressed + + Returns + ------- + bool + """ + return self._meta + + @property + def button(self) -> int: + """ + Integer code for the button that was pressed on the mouse to trigger the event + + - 0: Main button pressed, usually the left button or the un-initialized state + - 1: Auxiliary button pressed, usually the wheel button or the middle button (if present) + - 2: Secondary button pressed, usually the right button + - 3: Fourth button, typically the Browser Back button + - 4: Fifth button, typically the Browser Forward button + + Returns + ------- + int + """ + return self._button + + @property + def buttons(self) -> int: + """ + Integer code for which combination of buttons are pressed on the mouse when the event is triggered. + + - 0: No button or un-initialized + - 1: Primary button (usually left) + - 2: Secondary button (usually right) + - 4: Auxilary button (usually middle or mouse wheel button) + - 8: 4th button (typically the "Browser Back" button) + - 16: 5th button (typically the "Browser Forward" button) + + Combinations of buttons are represented as the decimal form of the bitmask of the values above. + + For example, pressing both the primary (1) and auxilary (4) buttons will result in a code of 5 + + Returns + ------- + int + """ + return self._buttons + + +class Points: + + def __init__(self, point_inds=None, xs=None, ys=None, trace_name=None, trace_index=None): + self._point_inds = point_inds + self._xs = xs + self._ys = ys + self._trace_name = trace_name + self._trace_index = trace_index + + @property + def point_inds(self) -> typ.List[int]: + return self._point_inds + + @property + def xs(self) -> typ.List: + return self._xs + + @property + def ys(self) -> typ.List: + return self._ys + + @property + def trace_name(self) -> str: + return self._trace_name + + @property + def trace_index(self) -> int: + return self._trace_index + + +class BoxSelector: + def __init__(self, xrange=None, yrange=None, **_): + self._type = 'box' + self._xrange = xrange + self._yrange = yrange + + @property + def type(self) -> str: + return self._type + + @property + def xrange(self) -> typ.Tuple[float, float]: + return self._xrange + + @property + def yrange(self) -> typ.Tuple[float, float]: + return self._yrange + + +class LassoSelector: + def __init__(self, xs=None, ys=None, **_): + self._type = 'lasso' + self._xs = xs + self._ys = ys + + @property + def type(self) -> str: + return self._type + + @property + def xs(self) -> typ.List[float]: + return self._xs + + @property + def ys(self) -> typ.List[float]: + return self._ys diff --git a/plotly/graph_objs/graph_objs.py b/plotly/graph_objs/graph_objs.py index 9f0f6ebd08c..958355f595f 100644 --- a/plotly/graph_objs/graph_objs.py +++ b/plotly/graph_objs/graph_objs.py @@ -799,1238 +799,203 @@ def create(object_name, *args, **kwargs): return PlotlyDict(*args, **kwargs) -# AUTO-GENERATED BELOW. DO NOT EDIT! See makefile. - - -class AngularAxis(PlotlyDict): - """ - Valid attributes for 'angularaxis' at path [] under parents (): - - ['categoryarray', 'categoryarraysrc', 'categoryorder', 'color', - 'direction', 'domain', 'dtick', 'endpadding', 'exponentformat', - 'gridcolor', 'gridwidth', 'hoverformat', 'layer', 'linecolor', - 'linewidth', 'nticks', 'period', 'range', 'rotation', - 'separatethousands', 'showexponent', 'showgrid', 'showline', - 'showticklabels', 'showtickprefix', 'showticksuffix', 'thetaunit', - 'tick0', 'tickangle', 'tickcolor', 'tickfont', 'tickformat', - 'tickformatstops', 'ticklen', 'tickmode', 'tickorientation', - 'tickprefix', 'ticks', 'ticksuffix', 'ticktext', 'ticktextsrc', - 'tickvals', 'tickvalssrc', 'tickwidth', 'type', 'visible'] - - Run `.help('attribute')` on any of the above. - '' is the object at [] - - """ - _name = 'angularaxis' - - -class Annotation(PlotlyDict): - """ - Valid attributes for 'annotation' at path [] under parents (): - - ['align', 'arrowcolor', 'arrowhead', 'arrowside', 'arrowsize', - 'arrowwidth', 'ax', 'axref', 'ay', 'ayref', 'bgcolor', 'bordercolor', - 'borderpad', 'borderwidth', 'captureevents', 'clicktoshow', 'font', - 'height', 'hoverlabel', 'hovertext', 'opacity', 'ref', 'showarrow', - 'standoff', 'startarrowhead', 'startarrowsize', 'startstandoff', - 'text', 'textangle', 'valign', 'visible', 'width', 'x', 'xanchor', - 'xclick', 'xref', 'xshift', 'y', 'yanchor', 'yclick', 'yref', 'yshift', - 'z'] - - Run `.help('attribute')` on any of the above. - '' is the object at [] - - """ - _name = 'annotation' - - -class Annotations(PlotlyList): - """ - Valid items for 'annotations' at path [] under parents (): - ['Annotation'] - - """ - _name = 'annotations' - - -class Area(PlotlyDict): - """ - Valid attributes for 'area' at path [] under parents (): - - ['customdata', 'customdatasrc', 'hoverinfo', 'hoverinfosrc', - 'hoverlabel', 'ids', 'idssrc', 'legendgroup', 'marker', 'name', - 'opacity', 'r', 'rsrc', 'selectedpoints', 'showlegend', 'stream', 't', - 'tsrc', 'type', 'uid', 'visible'] - - Run `.help('attribute')` on any of the above. - '' is the object at [] - - """ - _name = 'area' - - -class Bar(PlotlyDict): - """ - Valid attributes for 'bar' at path [] under parents (): - - ['bardir', 'base', 'basesrc', 'constraintext', 'customdata', - 'customdatasrc', 'dx', 'dy', 'error_x', 'error_y', 'hoverinfo', - 'hoverinfosrc', 'hoverlabel', 'hovertext', 'hovertextsrc', 'ids', - 'idssrc', 'insidetextfont', 'legendgroup', 'marker', 'name', 'offset', - 'offsetsrc', 'opacity', 'orientation', 'outsidetextfont', 'r', 'rsrc', - 'selected', 'selectedpoints', 'showlegend', 'stream', 't', 'text', - 'textfont', 'textposition', 'textpositionsrc', 'textsrc', 'tsrc', - 'type', 'uid', 'unselected', 'visible', 'width', 'widthsrc', 'x', 'x0', - 'xaxis', 'xcalendar', 'xsrc', 'y', 'y0', 'yaxis', 'ycalendar', 'ysrc'] - - Run `.help('attribute')` on any of the above. - '' is the object at [] - - """ - _name = 'bar' - - -class Box(PlotlyDict): - """ - Valid attributes for 'box' at path [] under parents (): - - ['boxmean', 'boxpoints', 'customdata', 'customdatasrc', 'fillcolor', - 'hoverinfo', 'hoverinfosrc', 'hoverlabel', 'hoveron', 'ids', 'idssrc', - 'jitter', 'legendgroup', 'line', 'marker', 'name', 'notched', - 'notchwidth', 'opacity', 'orientation', 'pointpos', 'selected', - 'selectedpoints', 'showlegend', 'stream', 'text', 'textsrc', 'type', - 'uid', 'unselected', 'visible', 'whiskerwidth', 'x', 'x0', 'xaxis', - 'xcalendar', 'xsrc', 'y', 'y0', 'yaxis', 'ycalendar', 'ysrc'] - - Run `.help('attribute')` on any of the above. - '' is the object at [] - - """ - _name = 'box' - - -class Candlestick(PlotlyDict): - """ - Valid attributes for 'candlestick' at path [] under parents (): - - ['close', 'closesrc', 'customdata', 'customdatasrc', 'decreasing', - 'high', 'highsrc', 'hoverinfo', 'hoverinfosrc', 'hoverlabel', 'ids', - 'idssrc', 'increasing', 'legendgroup', 'line', 'low', 'lowsrc', 'name', - 'opacity', 'open', 'opensrc', 'selectedpoints', 'showlegend', 'stream', - 'text', 'textsrc', 'type', 'uid', 'visible', 'whiskerwidth', 'x', - 'xaxis', 'xcalendar', 'xsrc', 'yaxis'] - - Run `.help('attribute')` on any of the above. - '' is the object at [] - - """ - _name = 'candlestick' - - -class Carpet(PlotlyDict): - """ - Valid attributes for 'carpet' at path [] under parents (): - - ['a', 'a0', 'aaxis', 'asrc', 'b', 'b0', 'baxis', 'bsrc', 'carpet', - 'cheaterslope', 'color', 'customdata', 'customdatasrc', 'da', 'db', - 'font', 'hoverinfo', 'hoverinfosrc', 'hoverlabel', 'ids', 'idssrc', - 'legendgroup', 'name', 'opacity', 'selectedpoints', 'showlegend', - 'stream', 'type', 'uid', 'visible', 'x', 'xaxis', 'xsrc', 'y', 'yaxis', - 'ysrc'] - - Run `.help('attribute')` on any of the above. - '' is the object at [] - - """ - _name = 'carpet' - - -class Choropleth(PlotlyDict): - """ - Valid attributes for 'choropleth' at path [] under parents (): - - ['autocolorscale', 'colorbar', 'colorscale', 'customdata', - 'customdatasrc', 'geo', 'hoverinfo', 'hoverinfosrc', 'hoverlabel', - 'ids', 'idssrc', 'legendgroup', 'locationmode', 'locations', - 'locationssrc', 'marker', 'name', 'opacity', 'reversescale', - 'selected', 'selectedpoints', 'showlegend', 'showscale', 'stream', - 'text', 'textsrc', 'type', 'uid', 'unselected', 'visible', 'z', - 'zauto', 'zmax', 'zmin', 'zsrc'] - - Run `.help('attribute')` on any of the above. - '' is the object at [] +from plotly.datatypes import FigureWidget - """ - _name = 'choropleth' - - -class ColorBar(PlotlyDict): - """ - Valid attributes for 'colorbar' at path [] under parents (): - - ['bgcolor', 'bordercolor', 'borderwidth', 'dtick', 'exponentformat', - 'len', 'lenmode', 'nticks', 'outlinecolor', 'outlinewidth', - 'separatethousands', 'showexponent', 'showticklabels', - 'showtickprefix', 'showticksuffix', 'thickness', 'thicknessmode', - 'tick0', 'tickangle', 'tickcolor', 'tickfont', 'tickformat', - 'tickformatstops', 'ticklen', 'tickmode', 'tickprefix', 'ticks', - 'ticksuffix', 'ticktext', 'ticktextsrc', 'tickvals', 'tickvalssrc', - 'tickwidth', 'title', 'titlefont', 'titleside', 'x', 'xanchor', 'xpad', - 'y', 'yanchor', 'ypad'] - - Run `.help('attribute')` on any of the above. - '' is the object at [] - - """ - _name = 'colorbar' - - -class Contour(PlotlyDict): - """ - Valid attributes for 'contour' at path [] under parents (): - - ['autocolorscale', 'autocontour', 'colorbar', 'colorscale', - 'connectgaps', 'contours', 'customdata', 'customdatasrc', 'dx', 'dy', - 'fillcolor', 'hoverinfo', 'hoverinfosrc', 'hoverlabel', 'ids', - 'idssrc', 'legendgroup', 'line', 'name', 'ncontours', 'opacity', - 'reversescale', 'selectedpoints', 'showlegend', 'showscale', 'stream', - 'text', 'textsrc', 'transpose', 'type', 'uid', 'visible', 'x', 'x0', - 'xaxis', 'xcalendar', 'xsrc', 'xtype', 'y', 'y0', 'yaxis', 'ycalendar', - 'ysrc', 'ytype', 'z', 'zauto', 'zhoverformat', 'zmax', 'zmin', 'zsrc'] - - Run `.help('attribute')` on any of the above. - '' is the object at [] - - """ - _name = 'contour' - - -class Contourcarpet(PlotlyDict): - """ - Valid attributes for 'contourcarpet' at path [] under parents (): - - ['a', 'a0', 'asrc', 'atype', 'autocolorscale', 'autocontour', 'b', - 'b0', 'bsrc', 'btype', 'carpet', 'colorbar', 'colorscale', 'contours', - 'customdata', 'customdatasrc', 'da', 'db', 'fillcolor', 'hoverinfo', - 'hoverinfosrc', 'hoverlabel', 'ids', 'idssrc', 'legendgroup', 'line', - 'name', 'ncontours', 'opacity', 'reversescale', 'selectedpoints', - 'showlegend', 'showscale', 'stream', 'text', 'textsrc', 'transpose', - 'type', 'uid', 'visible', 'xaxis', 'yaxis', 'z', 'zauto', 'zmax', - 'zmin', 'zsrc'] - - Run `.help('attribute')` on any of the above. - '' is the object at [] - - """ - _name = 'contourcarpet' - - -class Contours(PlotlyDict): - """ - Valid attributes for 'contours' at path [] under parents (): - - ['coloring', 'end', 'labelfont', 'labelformat', 'operation', - 'showlabels', 'showlines', 'size', 'start', 'type', 'value', 'x', 'y', - 'z'] - - Run `.help('attribute')` on any of the above. - '' is the object at [] - - """ - _name = 'contours' - - -class Data(PlotlyList): - """ - Valid items for 'data' at path [] under parents (): - ['Area', 'Bar', 'Box', 'Candlestick', 'Carpet', 'Choropleth', - 'Contour', 'Contourcarpet', 'Heatmap', 'Heatmapgl', 'Histogram', - 'Histogram2d', 'Histogram2dcontour', 'Mesh3d', 'Ohlc', 'Parcoords', - 'Pie', 'Pointcloud', 'Sankey', 'Scatter', 'Scatter3d', 'Scattercarpet', - 'Scattergeo', 'Scattergl', 'Scattermapbox', 'Scatterpolar', - 'Scatterpolargl', 'Scatterternary', 'Surface', 'Table', 'Violin'] - - """ - _name = 'data' - def _value_to_graph_object(self, index, value, _raise=True): - - if not isinstance(value, dict): - if _raise: - notes = ['Entry should subclass dict.'] - path = self._get_path() + (index, ) - raise exceptions.PlotlyListEntryError(self, path, - notes=notes) - else: - return - - item = value.get('type', 'scatter') - if item not in graph_reference.ARRAYS['data']['items']: - if _raise: - path = self._get_path() + (0, ) - raise exceptions.PlotlyDataTypeError(self, path) - - return GraphObjectFactory.create(item, _raise=_raise, - _parent=self, - _parent_key=index, **value) - - def get_data(self, flatten=False): - """ - Returns the JSON for the plot with non-data elements stripped. - - :param (bool) flatten: {'a': {'b': ''}} --> {'a.b': ''} - :returns: (dict|list) Depending on (flat|unflat) - - """ - if flatten: - data = [v.get_data(flatten=flatten) for v in self] - d = {} - taken_names = [] - for i, trace in enumerate(data): - - # we want to give the traces helpful names - # however, we need to be sure they're unique too... - trace_name = trace.pop('name', 'trace_{0}'.format(i)) - if trace_name in taken_names: - j = 1 - new_trace_name = "{0}_{1}".format(trace_name, j) - while new_trace_name in taken_names: - new_trace_name = ( - "{0}_{1}".format(trace_name, j) - ) - j += 1 - trace_name = new_trace_name - taken_names.append(trace_name) - - # finish up the dot-concatenation - for k, v in trace.items(): - key = "{0}.{1}".format(trace_name, k) - d[key] = v - return d - else: - return super(Data, self).get_data(flatten=flatten) - - -class ErrorX(PlotlyDict): - """ - Valid attributes for 'error_x' at path [] under parents (): - - ['array', 'arrayminus', 'arrayminussrc', 'arraysrc', 'color', - 'copy_ystyle', 'copy_zstyle', 'opacity', 'symmetric', 'thickness', - 'traceref', 'tracerefminus', 'type', 'value', 'valueminus', 'visible', - 'width'] - - Run `.help('attribute')` on any of the above. - '' is the object at [] - - """ - _name = 'error_x' - - -class ErrorY(PlotlyDict): - """ - Valid attributes for 'error_y' at path [] under parents (): - - ['array', 'arrayminus', 'arrayminussrc', 'arraysrc', 'color', - 'copy_ystyle', 'copy_zstyle', 'opacity', 'symmetric', 'thickness', - 'traceref', 'tracerefminus', 'type', 'value', 'valueminus', 'visible', - 'width'] - - Run `.help('attribute')` on any of the above. - '' is the object at [] - - """ - _name = 'error_y' - - -class ErrorZ(PlotlyDict): - """ - Valid attributes for 'error_z' at path [] under parents (): - - ['array', 'arrayminus', 'arrayminussrc', 'arraysrc', 'color', - 'copy_ystyle', 'copy_zstyle', 'opacity', 'symmetric', 'thickness', - 'traceref', 'tracerefminus', 'type', 'value', 'valueminus', 'visible', - 'width'] - - Run `.help('attribute')` on any of the above. - '' is the object at [] - - """ - _name = 'error_z' - - -class Figure(PlotlyDict): - """ - Valid attributes for 'figure' at path [] under parents (): - - ['data', 'frames', 'layout'] - - Run `.help('attribute')` on any of the above. - '' is the object at [] - - """ - _name = 'figure' - - def __init__(self, *args, **kwargs): - super(Figure, self).__init__(*args, **kwargs) - if 'data' not in self: - self.data = Data(_parent=self, _parent_key='data') - - def get_data(self, flatten=False): - """ - Returns the JSON for the plot with non-data elements stripped. - - Flattening may increase the utility of the result. - - :param (bool) flatten: {'a': {'b': ''}} --> {'a.b': ''} - :returns: (dict|list) Depending on (flat|unflat) - - """ - return self.data.get_data(flatten=flatten) - - def to_dataframe(self): - """ - Create a dataframe with trace names and keys as column names. - - :return: (DataFrame) - - """ - data = self.get_data(flatten=True) - from pandas import DataFrame, Series - return DataFrame( - dict([(k, Series(v)) for k, v in data.items()])) - - def print_grid(self): - """ - Print a visual layout of the figure's axes arrangement. - - This is only valid for figures that are created - with plotly.tools.make_subplots. - - """ - try: - grid_str = self.__dict__['_grid_str'] - except AttributeError: - raise Exception("Use plotly.tools.make_subplots " - "to create a subplot grid.") - print(grid_str) - - def append_trace(self, trace, row, col): - """ - Add a trace to your figure bound to axes at the row, col index. +# AUTO-GENERATED BELOW. DO NOT EDIT! See makefile. +class AngularAxis(dict): + pass - The row, col index is generated from figures created with - plotly.tools.make_subplots and can be viewed with - Figure.print_grid. - :param (dict) trace: The data trace to be bound. - :param (int) row: Subplot row index (see Figure.print_grid). - :param (int) col: Subplot column index (see Figure.print_grid). +class Annotation(dict): + pass - Example: - # stack two subplots vertically - fig = tools.make_subplots(rows=2) - This is the format of your plot grid: - [ (1,1) x1,y1 ] - [ (2,1) x2,y2 ] +class Annotations(list): + pass - fig.append_trace(Scatter(x=[1,2,3], y=[2,1,2]), 1, 1) - fig.append_trace(Scatter(x=[1,2,3], y=[2,1,2]), 2, 1) - """ - try: - grid_ref = self._grid_ref - except AttributeError: - raise Exception("In order to use Figure.append_trace, " - "you must first use " - "plotly.tools.make_subplots " - "to create a subplot grid.") - if row <= 0: - raise Exception("Row value is out of range. " - "Note: the starting cell is (1, 1)") - if col <= 0: - raise Exception("Col value is out of range. " - "Note: the starting cell is (1, 1)") - try: - ref = grid_ref[row-1][col-1] - except IndexError: - raise Exception("The (row, col) pair sent is out of " - "range. Use Figure.print_grid to view the " - "subplot grid. ") - if 'scene' in ref[0]: - trace['scene'] = ref[0] - if ref[0] not in self['layout']: - raise Exception("Something went wrong. " - "The scene object for ({r},{c}) " - "subplot cell " - "got deleted.".format(r=row, c=col)) - else: - xaxis_key = "xaxis{ref}".format(ref=ref[0][1:]) - yaxis_key = "yaxis{ref}".format(ref=ref[1][1:]) - if (xaxis_key not in self['layout'] - or yaxis_key not in self['layout']): - raise Exception("Something went wrong. " - "An axis object for ({r},{c}) subplot " - "cell got deleted." - .format(r=row, c=col)) - trace['xaxis'] = ref[0] - trace['yaxis'] = ref[1] - self['data'] += [trace] - - -class Font(PlotlyDict): - """ - Valid attributes for 'font' at path [] under parents (): - - ['color', 'colorsrc', 'family', 'familysrc', 'size', 'sizesrc'] - - Run `.help('attribute')` on any of the above. - '' is the object at [] +from plotly.datatypes.trace import Area - """ - _name = 'font' +from plotly.datatypes.trace import Bar -class Frames(PlotlyList): - """ - Valid items for 'frames' at path [] under parents (): - ['dict'] - """ - _name = 'frames' +from plotly.datatypes.trace import Box - def _value_to_graph_object(self, index, value, _raise=True): - if isinstance(value, six.string_types): - return value - return super(Frames, self)._value_to_graph_object(index, value, - _raise=_raise) - def to_string(self, level=0, indent=4, eol='\n', - pretty=True, max_chars=80): - """Get formatted string by calling `to_string` on children items.""" - if not len(self): - return "{name}()".format(name=self._get_class_name()) - string = "{name}([{eol}{indent}".format( - name=self._get_class_name(), - eol=eol, - indent=' ' * indent * (level + 1)) - for index, entry in enumerate(self): - if isinstance(entry, six.string_types): - string += repr(entry) - else: - string += entry.to_string(level=level+1, - indent=indent, - eol=eol, - pretty=pretty, - max_chars=max_chars) - if index < len(self) - 1: - string += ",{eol}{indent}".format( - eol=eol, - indent=' ' * indent * (level + 1)) - string += ( - "{eol}{indent}])").format(eol=eol, indent=' ' * indent * level) - return string +from plotly.datatypes.trace import Candlestick -class Heatmap(PlotlyDict): - """ - Valid attributes for 'heatmap' at path [] under parents (): - - ['autocolorscale', 'colorbar', 'colorscale', 'connectgaps', - 'customdata', 'customdatasrc', 'dx', 'dy', 'hoverinfo', 'hoverinfosrc', - 'hoverlabel', 'ids', 'idssrc', 'legendgroup', 'name', 'opacity', - 'reversescale', 'selectedpoints', 'showlegend', 'showscale', 'stream', - 'text', 'textsrc', 'transpose', 'type', 'uid', 'visible', 'x', 'x0', - 'xaxis', 'xcalendar', 'xgap', 'xsrc', 'xtype', 'y', 'y0', 'yaxis', - 'ycalendar', 'ygap', 'ysrc', 'ytype', 'z', 'zauto', 'zhoverformat', - 'zmax', 'zmin', 'zsmooth', 'zsrc'] - - Run `.help('attribute')` on any of the above. - '' is the object at [] +from plotly.datatypes.trace import Carpet - """ - _name = 'heatmap' +from plotly.datatypes.trace import Choropleth -class Heatmapgl(PlotlyDict): - """ - Valid attributes for 'heatmapgl' at path [] under parents (): - - ['autocolorscale', 'colorbar', 'colorscale', 'customdata', - 'customdatasrc', 'dx', 'dy', 'hoverinfo', 'hoverinfosrc', 'hoverlabel', - 'ids', 'idssrc', 'legendgroup', 'name', 'opacity', 'reversescale', - 'selectedpoints', 'showlegend', 'showscale', 'stream', 'text', - 'textsrc', 'transpose', 'type', 'uid', 'visible', 'x', 'x0', 'xaxis', - 'xsrc', 'xtype', 'y', 'y0', 'yaxis', 'ysrc', 'ytype', 'z', 'zauto', - 'zmax', 'zmin', 'zsrc'] - - Run `.help('attribute')` on any of the above. - '' is the object at [] - - """ - _name = 'heatmapgl' - - -class Histogram(PlotlyDict): - """ - Valid attributes for 'histogram' at path [] under parents (): - - ['autobinx', 'autobiny', 'bardir', 'cumulative', 'customdata', - 'customdatasrc', 'error_x', 'error_y', 'histfunc', 'histnorm', - 'hoverinfo', 'hoverinfosrc', 'hoverlabel', 'ids', 'idssrc', - 'legendgroup', 'marker', 'name', 'nbinsx', 'nbinsy', 'opacity', - 'orientation', 'selected', 'selectedpoints', 'showlegend', 'stream', - 'text', 'textsrc', 'type', 'uid', 'unselected', 'visible', 'x', - 'xaxis', 'xbins', 'xcalendar', 'xsrc', 'y', 'yaxis', 'ybins', - 'ycalendar', 'ysrc'] - - Run `.help('attribute')` on any of the above. - '' is the object at [] - - """ - _name = 'histogram' - - -class Histogram2d(PlotlyDict): - """ - Valid attributes for 'histogram2d' at path [] under parents (): - - ['autobinx', 'autobiny', 'autocolorscale', 'colorbar', 'colorscale', - 'customdata', 'customdatasrc', 'histfunc', 'histnorm', 'hoverinfo', - 'hoverinfosrc', 'hoverlabel', 'ids', 'idssrc', 'legendgroup', 'marker', - 'name', 'nbinsx', 'nbinsy', 'opacity', 'reversescale', - 'selectedpoints', 'showlegend', 'showscale', 'stream', 'type', 'uid', - 'visible', 'x', 'xaxis', 'xbins', 'xcalendar', 'xgap', 'xsrc', 'y', - 'yaxis', 'ybins', 'ycalendar', 'ygap', 'ysrc', 'z', 'zauto', - 'zhoverformat', 'zmax', 'zmin', 'zsmooth', 'zsrc'] - - Run `.help('attribute')` on any of the above. - '' is the object at [] - - """ - _name = 'histogram2d' +class ColorBar(dict): + pass -class Histogram2dContour(PlotlyDict): - """ - Valid attributes for 'histogram2dcontour' at path [] under parents (): - - ['autobinx', 'autobiny', 'autocolorscale', 'autocontour', 'colorbar', - 'colorscale', 'contours', 'customdata', 'customdatasrc', 'histfunc', - 'histnorm', 'hoverinfo', 'hoverinfosrc', 'hoverlabel', 'ids', 'idssrc', - 'legendgroup', 'line', 'marker', 'name', 'nbinsx', 'nbinsy', - 'ncontours', 'opacity', 'reversescale', 'selectedpoints', 'showlegend', - 'showscale', 'stream', 'type', 'uid', 'visible', 'x', 'xaxis', 'xbins', - 'xcalendar', 'xsrc', 'y', 'yaxis', 'ybins', 'ycalendar', 'ysrc', 'z', - 'zauto', 'zhoverformat', 'zmax', 'zmin', 'zsrc'] - - Run `.help('attribute')` on any of the above. - '' is the object at [] - """ - _name = 'histogram2dcontour' +from plotly.datatypes.trace import Contour -class Histogram2dcontour(PlotlyDict): - """ - Valid attributes for 'histogram2dcontour' at path [] under parents (): - - ['autobinx', 'autobiny', 'autocolorscale', 'autocontour', 'colorbar', - 'colorscale', 'contours', 'customdata', 'customdatasrc', 'histfunc', - 'histnorm', 'hoverinfo', 'hoverinfosrc', 'hoverlabel', 'ids', 'idssrc', - 'legendgroup', 'line', 'marker', 'name', 'nbinsx', 'nbinsy', - 'ncontours', 'opacity', 'reversescale', 'selectedpoints', 'showlegend', - 'showscale', 'stream', 'type', 'uid', 'visible', 'x', 'xaxis', 'xbins', - 'xcalendar', 'xsrc', 'y', 'yaxis', 'ybins', 'ycalendar', 'ysrc', 'z', - 'zauto', 'zhoverformat', 'zmax', 'zmin', 'zsrc'] - - Run `.help('attribute')` on any of the above. - '' is the object at [] +from plotly.datatypes.trace import Contourcarpet - """ - _name = 'histogram2dcontour' +class Contours(dict): + pass -class Layout(PlotlyDict): - """ - Valid attributes for 'layout' at path [] under parents (): - - ['angularaxis', 'annotations', 'autosize', 'bargap', 'bargroupgap', - 'barmode', 'barnorm', 'boxgap', 'boxgroupgap', 'boxmode', 'calendar', - 'colorway', 'datarevision', 'direction', 'dragmode', 'font', 'geo', - 'height', 'hiddenlabels', 'hiddenlabelssrc', 'hidesources', - 'hoverdistance', 'hoverlabel', 'hovermode', 'images', 'legend', - 'mapbox', 'margin', 'orientation', 'paper_bgcolor', 'plot_bgcolor', - 'polar', 'radialaxis', 'scene', 'separators', 'shapes', 'showlegend', - 'sliders', 'spikedistance', 'ternary', 'title', 'titlefont', - 'updatemenus', 'violingap', 'violingroupgap', 'violinmode', 'width', - 'xaxis', 'yaxis'] - - Run `.help('attribute')` on any of the above. - '' is the object at [] - """ - _name = 'layout' +class Data(list): + pass -class Legend(PlotlyDict): - """ - Valid attributes for 'legend' at path [] under parents (): - - ['bgcolor', 'bordercolor', 'borderwidth', 'font', 'orientation', - 'tracegroupgap', 'traceorder', 'x', 'xanchor', 'y', 'yanchor'] - - Run `.help('attribute')` on any of the above. - '' is the object at [] +class ErrorX(dict): + pass - """ - _name = 'legend' +class ErrorY(dict): + pass -class Line(PlotlyDict): - """ - Valid attributes for 'line' at path [] under parents (): - - ['autocolorscale', 'cauto', 'cmax', 'cmin', 'color', 'colorbar', - 'colorscale', 'colorsrc', 'dash', 'outliercolor', 'outlierwidth', - 'reversescale', 'shape', 'showscale', 'simplify', 'smoothing', 'width', - 'widthsrc'] - - Run `.help('attribute')` on any of the above. - '' is the object at [] - """ - _name = 'line' +class ErrorZ(dict): + pass -class Margin(PlotlyDict): - """ - Valid attributes for 'margin' at path [] under parents (): - - ['autoexpand', 'b', 'l', 'pad', 'r', 't'] - - Run `.help('attribute')` on any of the above. - '' is the object at [] +from plotly.datatypes import Figure - """ - _name = 'margin' +class Font(dict): + pass -class Marker(PlotlyDict): - """ - Valid attributes for 'marker' at path [] under parents (): - - ['autocolorscale', 'blend', 'border', 'cauto', 'cmax', 'cmin', 'color', - 'colorbar', 'colors', 'colorscale', 'colorsrc', 'colorssrc', - 'gradient', 'line', 'maxdisplayed', 'opacity', 'opacitysrc', - 'outliercolor', 'reversescale', 'showscale', 'size', 'sizemax', - 'sizemin', 'sizemode', 'sizeref', 'sizesrc', 'symbol', 'symbolsrc'] - - Run `.help('attribute')` on any of the above. - '' is the object at [] - """ - _name = 'marker' +class Frames(list): + pass -class Mesh3d(PlotlyDict): - """ - Valid attributes for 'mesh3d' at path [] under parents (): - - ['alphahull', 'autocolorscale', 'cauto', 'cmax', 'cmin', 'color', - 'colorbar', 'colorscale', 'contour', 'customdata', 'customdatasrc', - 'delaunayaxis', 'facecolor', 'facecolorsrc', 'flatshading', - 'hoverinfo', 'hoverinfosrc', 'hoverlabel', 'i', 'ids', 'idssrc', - 'intensity', 'intensitysrc', 'isrc', 'j', 'jsrc', 'k', 'ksrc', - 'legendgroup', 'lighting', 'lightposition', 'name', 'opacity', - 'reversescale', 'scene', 'selectedpoints', 'showlegend', 'showscale', - 'stream', 'text', 'textsrc', 'type', 'uid', 'vertexcolor', - 'vertexcolorsrc', 'visible', 'x', 'xcalendar', 'xsrc', 'y', - 'ycalendar', 'ysrc', 'z', 'zcalendar', 'zsrc'] - - Run `.help('attribute')` on any of the above. - '' is the object at [] +from plotly.datatypes.trace import Heatmap - """ - _name = 'mesh3d' +from plotly.datatypes.trace import Heatmapgl -class Ohlc(PlotlyDict): - """ - Valid attributes for 'ohlc' at path [] under parents (): - - ['close', 'closesrc', 'customdata', 'customdatasrc', 'decreasing', - 'high', 'highsrc', 'hoverinfo', 'hoverinfosrc', 'hoverlabel', 'ids', - 'idssrc', 'increasing', 'legendgroup', 'line', 'low', 'lowsrc', 'name', - 'opacity', 'open', 'opensrc', 'selectedpoints', 'showlegend', 'stream', - 'text', 'textsrc', 'tickwidth', 'type', 'uid', 'visible', 'x', 'xaxis', - 'xcalendar', 'xsrc', 'yaxis'] - - Run `.help('attribute')` on any of the above. - '' is the object at [] - """ - _name = 'ohlc' +from plotly.datatypes.trace import Histogram -class Parcoords(PlotlyDict): - """ - Valid attributes for 'parcoords' at path [] under parents (): - - ['customdata', 'customdatasrc', 'dimensions', 'domain', 'hoverinfo', - 'hoverinfosrc', 'hoverlabel', 'ids', 'idssrc', 'labelfont', - 'legendgroup', 'line', 'name', 'opacity', 'rangefont', - 'selectedpoints', 'showlegend', 'stream', 'tickfont', 'type', 'uid', - 'visible'] - - Run `.help('attribute')` on any of the above. - '' is the object at [] +from plotly.datatypes.trace import Histogram2d - """ - _name = 'parcoords' +from plotly.datatypes.trace import Histogram2dContour -class Pie(PlotlyDict): - """ - Valid attributes for 'pie' at path [] under parents (): - - ['customdata', 'customdatasrc', 'direction', 'dlabel', 'domain', - 'hole', 'hoverinfo', 'hoverinfosrc', 'hoverlabel', 'hovertext', - 'hovertextsrc', 'ids', 'idssrc', 'insidetextfont', 'label0', 'labels', - 'labelssrc', 'legendgroup', 'marker', 'name', 'opacity', - 'outsidetextfont', 'pull', 'pullsrc', 'rotation', 'scalegroup', - 'selectedpoints', 'showlegend', 'sort', 'stream', 'text', 'textfont', - 'textinfo', 'textposition', 'textpositionsrc', 'textsrc', 'type', - 'uid', 'values', 'valuessrc', 'visible'] - - Run `.help('attribute')` on any of the above. - '' is the object at [] - """ - _name = 'pie' +from plotly.datatypes import Layout -class Pointcloud(PlotlyDict): - """ - Valid attributes for 'pointcloud' at path [] under parents (): - - ['customdata', 'customdatasrc', 'hoverinfo', 'hoverinfosrc', - 'hoverlabel', 'ids', 'idssrc', 'indices', 'indicessrc', 'legendgroup', - 'marker', 'name', 'opacity', 'selectedpoints', 'showlegend', 'stream', - 'text', 'textsrc', 'type', 'uid', 'visible', 'x', 'xaxis', 'xbounds', - 'xboundssrc', 'xsrc', 'xy', 'xysrc', 'y', 'yaxis', 'ybounds', - 'yboundssrc', 'ysrc'] - - Run `.help('attribute')` on any of the above. - '' is the object at [] +class Legend(dict): + pass - """ - _name = 'pointcloud' +class Line(dict): + pass -class RadialAxis(PlotlyDict): - """ - Valid attributes for 'radialaxis' at path [] under parents (): - - ['angle', 'autorange', 'calendar', 'categoryarray', 'categoryarraysrc', - 'categoryorder', 'color', 'domain', 'dtick', 'endpadding', - 'exponentformat', 'gridcolor', 'gridwidth', 'hoverformat', 'layer', - 'linecolor', 'linewidth', 'nticks', 'orientation', 'range', - 'rangemode', 'separatethousands', 'showexponent', 'showgrid', - 'showline', 'showticklabels', 'showtickprefix', 'showticksuffix', - 'side', 'tick0', 'tickangle', 'tickcolor', 'tickfont', 'tickformat', - 'tickformatstops', 'ticklen', 'tickmode', 'tickorientation', - 'tickprefix', 'ticks', 'ticksuffix', 'ticktext', 'ticktextsrc', - 'tickvals', 'tickvalssrc', 'tickwidth', 'title', 'titlefont', 'type', - 'visible'] - - Run `.help('attribute')` on any of the above. - '' is the object at [] - """ - _name = 'radialaxis' +class Margin(dict): + pass -class Sankey(PlotlyDict): - """ - Valid attributes for 'sankey' at path [] under parents (): - - ['arrangement', 'customdata', 'customdatasrc', 'domain', 'hoverinfo', - 'hoverinfosrc', 'hoverlabel', 'ids', 'idssrc', 'legendgroup', 'link', - 'name', 'node', 'opacity', 'orientation', 'selectedpoints', - 'showlegend', 'stream', 'textfont', 'type', 'uid', 'valueformat', - 'valuesuffix', 'visible'] - - Run `.help('attribute')` on any of the above. - '' is the object at [] +class Marker(dict): + pass - """ - _name = 'sankey' +from plotly.datatypes.trace import Mesh3d -class Scatter(PlotlyDict): - """ - Valid attributes for 'scatter' at path [] under parents (): - - ['cliponaxis', 'connectgaps', 'customdata', 'customdatasrc', 'dx', - 'dy', 'error_x', 'error_y', 'fill', 'fillcolor', 'hoverinfo', - 'hoverinfosrc', 'hoverlabel', 'hoveron', 'hovertext', 'hovertextsrc', - 'ids', 'idssrc', 'legendgroup', 'line', 'marker', 'mode', 'name', - 'opacity', 'r', 'rsrc', 'selected', 'selectedpoints', 'showlegend', - 'stream', 't', 'text', 'textfont', 'textposition', 'textpositionsrc', - 'textsrc', 'tsrc', 'type', 'uid', 'unselected', 'visible', 'x', 'x0', - 'xaxis', 'xcalendar', 'xsrc', 'y', 'y0', 'yaxis', 'ycalendar', 'ysrc'] - - Run `.help('attribute')` on any of the above. - '' is the object at [] - """ - _name = 'scatter' +from plotly.datatypes.trace import Ohlc -class Scatter3d(PlotlyDict): - """ - Valid attributes for 'scatter3d' at path [] under parents (): - - ['connectgaps', 'customdata', 'customdatasrc', 'error_x', 'error_y', - 'error_z', 'hoverinfo', 'hoverinfosrc', 'hoverlabel', 'hovertext', - 'hovertextsrc', 'ids', 'idssrc', 'legendgroup', 'line', 'marker', - 'mode', 'name', 'opacity', 'projection', 'scene', 'selectedpoints', - 'showlegend', 'stream', 'surfaceaxis', 'surfacecolor', 'text', - 'textfont', 'textposition', 'textpositionsrc', 'textsrc', 'type', - 'uid', 'visible', 'x', 'xcalendar', 'xsrc', 'y', 'ycalendar', 'ysrc', - 'z', 'zcalendar', 'zsrc'] - - Run `.help('attribute')` on any of the above. - '' is the object at [] +from plotly.datatypes.trace import Parcoords - """ - _name = 'scatter3d' +from plotly.datatypes.trace import Pie -class Scattercarpet(PlotlyDict): - """ - Valid attributes for 'scattercarpet' at path [] under parents (): - - ['a', 'asrc', 'b', 'bsrc', 'carpet', 'connectgaps', 'customdata', - 'customdatasrc', 'fill', 'fillcolor', 'hoverinfo', 'hoverinfosrc', - 'hoverlabel', 'hoveron', 'ids', 'idssrc', 'legendgroup', 'line', - 'marker', 'mode', 'name', 'opacity', 'selected', 'selectedpoints', - 'showlegend', 'stream', 'text', 'textfont', 'textposition', - 'textpositionsrc', 'textsrc', 'type', 'uid', 'unselected', 'visible', - 'xaxis', 'yaxis'] - - Run `.help('attribute')` on any of the above. - '' is the object at [] - """ - _name = 'scattercarpet' +from plotly.datatypes.trace import Pointcloud -class Scattergeo(PlotlyDict): - """ - Valid attributes for 'scattergeo' at path [] under parents (): - - ['connectgaps', 'customdata', 'customdatasrc', 'fill', 'fillcolor', - 'geo', 'hoverinfo', 'hoverinfosrc', 'hoverlabel', 'hovertext', - 'hovertextsrc', 'ids', 'idssrc', 'lat', 'latsrc', 'legendgroup', - 'line', 'locationmode', 'locations', 'locationssrc', 'lon', 'lonsrc', - 'marker', 'mode', 'name', 'opacity', 'selected', 'selectedpoints', - 'showlegend', 'stream', 'text', 'textfont', 'textposition', - 'textpositionsrc', 'textsrc', 'type', 'uid', 'unselected', 'visible'] - - Run `.help('attribute')` on any of the above. - '' is the object at [] +class RadialAxis(dict): + pass - """ - _name = 'scattergeo' +from plotly.datatypes.trace import Sankey -class Scattergl(PlotlyDict): - """ - Valid attributes for 'scattergl' at path [] under parents (): - - ['connectgaps', 'customdata', 'customdatasrc', 'dx', 'dy', 'error_x', - 'error_y', 'fill', 'fillcolor', 'hoverinfo', 'hoverinfosrc', - 'hoverlabel', 'hoveron', 'ids', 'idssrc', 'legendgroup', 'line', - 'marker', 'mode', 'name', 'opacity', 'selected', 'selectedpoints', - 'showlegend', 'stream', 'text', 'textsrc', 'type', 'uid', 'unselected', - 'visible', 'x', 'x0', 'xaxis', 'xcalendar', 'xsrc', 'y', 'y0', 'yaxis', - 'ycalendar', 'ysrc'] - - Run `.help('attribute')` on any of the above. - '' is the object at [] - """ - _name = 'scattergl' +from plotly.datatypes.trace import Scatter -class Scattermapbox(PlotlyDict): - """ - Valid attributes for 'scattermapbox' at path [] under parents (): - - ['connectgaps', 'customdata', 'customdatasrc', 'fill', 'fillcolor', - 'hoverinfo', 'hoverinfosrc', 'hoverlabel', 'hovertext', 'hovertextsrc', - 'ids', 'idssrc', 'lat', 'latsrc', 'legendgroup', 'line', 'lon', - 'lonsrc', 'marker', 'mode', 'name', 'opacity', 'selected', - 'selectedpoints', 'showlegend', 'stream', 'subplot', 'text', - 'textfont', 'textposition', 'textsrc', 'type', 'uid', 'unselected', - 'visible'] - - Run `.help('attribute')` on any of the above. - '' is the object at [] +from plotly.datatypes.trace import Scatter3d - """ - _name = 'scattermapbox' +from plotly.datatypes.trace import Scattercarpet -class Scatterpolar(PlotlyDict): - """ - Valid attributes for 'scatterpolar' at path [] under parents (): - - ['cliponaxis', 'connectgaps', 'customdata', 'customdatasrc', 'fill', - 'fillcolor', 'hoverinfo', 'hoverinfosrc', 'hoverlabel', 'hoveron', - 'hovertext', 'hovertextsrc', 'ids', 'idssrc', 'legendgroup', 'line', - 'marker', 'mode', 'name', 'opacity', 'r', 'rsrc', 'selected', - 'selectedpoints', 'showlegend', 'stream', 'subplot', 'text', - 'textfont', 'textposition', 'textpositionsrc', 'textsrc', 'theta', - 'thetasrc', 'thetaunit', 'type', 'uid', 'unselected', 'visible'] - - Run `.help('attribute')` on any of the above. - '' is the object at [] - """ - _name = 'scatterpolar' +from plotly.datatypes.trace import Scattergeo -class Scatterpolargl(PlotlyDict): - """ - Valid attributes for 'scatterpolargl' at path [] under parents (): - - ['connectgaps', 'customdata', 'customdatasrc', 'fill', 'fillcolor', - 'hoverinfo', 'hoverinfosrc', 'hoverlabel', 'hoveron', 'ids', 'idssrc', - 'legendgroup', 'line', 'marker', 'mode', 'name', 'opacity', 'r', - 'rsrc', 'selected', 'selectedpoints', 'showlegend', 'stream', - 'subplot', 'text', 'textsrc', 'theta', 'thetasrc', 'thetaunit', 'type', - 'uid', 'unselected', 'visible'] - - Run `.help('attribute')` on any of the above. - '' is the object at [] +from plotly.datatypes.trace import Scattergl - """ - _name = 'scatterpolargl' +from plotly.datatypes.trace import Scattermapbox -class Scatterternary(PlotlyDict): - """ - Valid attributes for 'scatterternary' at path [] under parents (): - - ['a', 'asrc', 'b', 'bsrc', 'c', 'cliponaxis', 'connectgaps', 'csrc', - 'customdata', 'customdatasrc', 'fill', 'fillcolor', 'hoverinfo', - 'hoverinfosrc', 'hoverlabel', 'hoveron', 'hovertext', 'hovertextsrc', - 'ids', 'idssrc', 'legendgroup', 'line', 'marker', 'mode', 'name', - 'opacity', 'selected', 'selectedpoints', 'showlegend', 'stream', - 'subplot', 'sum', 'text', 'textfont', 'textposition', - 'textpositionsrc', 'textsrc', 'type', 'uid', 'unselected', 'visible'] - - Run `.help('attribute')` on any of the above. - '' is the object at [] - """ - _name = 'scatterternary' +from plotly.datatypes.trace import Scatterpolar -class Scene(PlotlyDict): - """ - Valid attributes for 'scene' at path [] under parents (): - - ['annotations', 'aspectmode', 'aspectratio', 'bgcolor', 'camera', - 'cameraposition', 'domain', 'dragmode', 'hovermode', 'xaxis', 'yaxis', - 'zaxis'] - - Run `.help('attribute')` on any of the above. - '' is the object at [] +from plotly.datatypes.trace import Scatterpolargl - """ - _name = 'scene' +from plotly.datatypes.trace import Scatterternary -class Stream(PlotlyDict): - """ - Valid attributes for 'stream' at path [] under parents (): - - ['maxpoints', 'token'] - - Run `.help('attribute')` on any of the above. - '' is the object at [] - """ - _name = 'stream' +class Scene(dict): + pass -class Surface(PlotlyDict): - """ - Valid attributes for 'surface' at path [] under parents (): - - ['autocolorscale', 'cauto', 'cmax', 'cmin', 'colorbar', 'colorscale', - 'contours', 'customdata', 'customdatasrc', 'hidesurface', 'hoverinfo', - 'hoverinfosrc', 'hoverlabel', 'ids', 'idssrc', 'legendgroup', - 'lighting', 'lightposition', 'name', 'opacity', 'reversescale', - 'scene', 'selectedpoints', 'showlegend', 'showscale', 'stream', - 'surfacecolor', 'surfacecolorsrc', 'text', 'textsrc', 'type', 'uid', - 'visible', 'x', 'xcalendar', 'xsrc', 'y', 'ycalendar', 'ysrc', 'z', - 'zauto', 'zcalendar', 'zmax', 'zmin', 'zsrc'] - - Run `.help('attribute')` on any of the above. - '' is the object at [] +class Stream(dict): + pass - """ - _name = 'surface' +from plotly.datatypes.trace import Surface -class Table(PlotlyDict): - """ - Valid attributes for 'table' at path [] under parents (): - - ['cells', 'columnorder', 'columnordersrc', 'columnwidth', - 'columnwidthsrc', 'customdata', 'customdatasrc', 'domain', 'header', - 'hoverinfo', 'hoverinfosrc', 'hoverlabel', 'ids', 'idssrc', - 'legendgroup', 'name', 'opacity', 'selectedpoints', 'showlegend', - 'stream', 'type', 'uid', 'visible'] - - Run `.help('attribute')` on any of the above. - '' is the object at [] - """ - _name = 'table' +from plotly.datatypes.trace import Table class Trace(dict): pass -class Violin(PlotlyDict): - """ - Valid attributes for 'violin' at path [] under parents (): - - ['bandwidth', 'box', 'customdata', 'customdatasrc', 'fillcolor', - 'hoverinfo', 'hoverinfosrc', 'hoverlabel', 'hoveron', 'ids', 'idssrc', - 'jitter', 'legendgroup', 'line', 'marker', 'meanline', 'name', - 'opacity', 'orientation', 'pointpos', 'points', 'scalegroup', - 'scalemode', 'selected', 'selectedpoints', 'showlegend', 'side', - 'span', 'spanmode', 'stream', 'text', 'textsrc', 'type', 'uid', - 'unselected', 'visible', 'x', 'x0', 'xaxis', 'xsrc', 'y', 'y0', - 'yaxis', 'ysrc'] - - Run `.help('attribute')` on any of the above. - '' is the object at [] - - """ - _name = 'violin' - - -class XAxis(PlotlyDict): - """ - Valid attributes for 'xaxis' at path [] under parents (): - - ['anchor', 'autorange', 'autotick', 'backgroundcolor', 'calendar', - 'categoryarray', 'categoryarraysrc', 'categoryorder', 'color', - 'constrain', 'constraintoward', 'domain', 'dtick', 'exponentformat', - 'fixedrange', 'gridcolor', 'gridwidth', 'hoverformat', 'layer', - 'linecolor', 'linewidth', 'mirror', 'nticks', 'overlaying', 'position', - 'range', 'rangemode', 'rangeselector', 'rangeslider', 'scaleanchor', - 'scaleratio', 'separatethousands', 'showaxeslabels', 'showbackground', - 'showexponent', 'showgrid', 'showline', 'showspikes', 'showticklabels', - 'showtickprefix', 'showticksuffix', 'side', 'spikecolor', 'spikedash', - 'spikemode', 'spikesides', 'spikesnap', 'spikethickness', 'tick0', - 'tickangle', 'tickcolor', 'tickfont', 'tickformat', 'tickformatstops', - 'ticklen', 'tickmode', 'tickprefix', 'ticks', 'ticksuffix', 'ticktext', - 'ticktextsrc', 'tickvals', 'tickvalssrc', 'tickwidth', 'title', - 'titlefont', 'type', 'visible', 'zeroline', 'zerolinecolor', - 'zerolinewidth'] - - Run `.help('attribute')` on any of the above. - '' is the object at [] +from plotly.datatypes.trace import Violin - """ - _name = 'xaxis' +class XAxis(dict): + pass -class XBins(PlotlyDict): - """ - Valid attributes for 'xbins' at path [] under parents (): - - ['end', 'size', 'start'] - - Run `.help('attribute')` on any of the above. - '' is the object at [] - - """ - _name = 'xbins' +class XBins(dict): + pass -class YAxis(PlotlyDict): - """ - Valid attributes for 'yaxis' at path [] under parents (): - - ['anchor', 'autorange', 'autotick', 'backgroundcolor', 'calendar', - 'categoryarray', 'categoryarraysrc', 'categoryorder', 'color', - 'constrain', 'constraintoward', 'domain', 'dtick', 'exponentformat', - 'fixedrange', 'gridcolor', 'gridwidth', 'hoverformat', 'layer', - 'linecolor', 'linewidth', 'mirror', 'nticks', 'overlaying', 'position', - 'range', 'rangemode', 'scaleanchor', 'scaleratio', 'separatethousands', - 'showaxeslabels', 'showbackground', 'showexponent', 'showgrid', - 'showline', 'showspikes', 'showticklabels', 'showtickprefix', - 'showticksuffix', 'side', 'spikecolor', 'spikedash', 'spikemode', - 'spikesides', 'spikesnap', 'spikethickness', 'tick0', 'tickangle', - 'tickcolor', 'tickfont', 'tickformat', 'tickformatstops', 'ticklen', - 'tickmode', 'tickprefix', 'ticks', 'ticksuffix', 'ticktext', - 'ticktextsrc', 'tickvals', 'tickvalssrc', 'tickwidth', 'title', - 'titlefont', 'type', 'visible', 'zeroline', 'zerolinecolor', - 'zerolinewidth'] - - Run `.help('attribute')` on any of the above. - '' is the object at [] - - """ - _name = 'yaxis' +class YAxis(dict): + pass -class YBins(PlotlyDict): - """ - Valid attributes for 'ybins' at path [] under parents (): - - ['end', 'size', 'start'] - - Run `.help('attribute')` on any of the above. - '' is the object at [] - """ - _name = 'ybins' +class YBins(dict): + pass -class ZAxis(PlotlyDict): - """ - Valid attributes for 'zaxis' at path [] under parents (): - - ['autorange', 'backgroundcolor', 'calendar', 'categoryarray', - 'categoryarraysrc', 'categoryorder', 'color', 'dtick', - 'exponentformat', 'gridcolor', 'gridwidth', 'hoverformat', 'linecolor', - 'linewidth', 'mirror', 'nticks', 'range', 'rangemode', - 'separatethousands', 'showaxeslabels', 'showbackground', - 'showexponent', 'showgrid', 'showline', 'showspikes', 'showticklabels', - 'showtickprefix', 'showticksuffix', 'spikecolor', 'spikesides', - 'spikethickness', 'tick0', 'tickangle', 'tickcolor', 'tickfont', - 'tickformat', 'tickformatstops', 'ticklen', 'tickmode', 'tickprefix', - 'ticks', 'ticksuffix', 'ticktext', 'ticktextsrc', 'tickvals', - 'tickvalssrc', 'tickwidth', 'title', 'titlefont', 'type', 'visible', - 'zeroline', 'zerolinecolor', 'zerolinewidth'] - - Run `.help('attribute')` on any of the above. - '' is the object at [] +class ZAxis(dict): + pass - """ - _name = 'zaxis' -__all__ = [cls for cls in graph_reference.CLASSES.keys() if cls in globals()] +__all__ = [cls for cls in graph_reference.CLASSES.keys() if cls in globals()] + ["FigureWidget"] diff --git a/plotly/graph_reference.py b/plotly/graph_reference.py index dd78bb30d92..e01b610e2d2 100644 --- a/plotly/graph_reference.py +++ b/plotly/graph_reference.py @@ -557,8 +557,10 @@ def _get_classes(): # add all the objects we had before, but mark them if they no longer # exist in the graph reference + backwards_compat_object_names = set() for class_name, class_dict in _BACKWARDS_COMPAT_CLASS_NAMES.items(): object_name = class_dict['object_name'] + backwards_compat_object_names.add(object_name) base_type = class_dict['base_type'] if object_name in OBJECTS or object_name in ARRAYS: classes[class_name] = {'object_name': object_name, @@ -568,8 +570,10 @@ def _get_classes(): # always keep the trace dicts up to date for object_name in TRACE_NAMES: - class_name = string_to_class_name(object_name) - classes[class_name] = {'object_name': object_name, 'base_type': dict} + if object_name not in backwards_compat_object_names: + # Only add trace if it wasn't included in _BACKWARDS_COMPAT_CLASS_NAMES + class_name = string_to_class_name(object_name) + classes[class_name] = {'object_name': object_name, 'base_type': dict} return classes diff --git a/plotly/matplotlylib/mplexporter/exporter.py b/plotly/matplotlylib/mplexporter/exporter.py index be2530c83f0..19a61eca334 100644 --- a/plotly/matplotlylib/mplexporter/exporter.py +++ b/plotly/matplotlylib/mplexporter/exporter.py @@ -162,8 +162,8 @@ def crawl_legend(self, ax, legend): if isinstance(child, matplotlib.patches.Patch): self.draw_patch(ax, child, force_trans=ax.transAxes) elif isinstance(child, matplotlib.text.Text): - if (child is not legend.get_children()[-1] - and child.get_text() != 'None'): + if not (child is legend.get_children()[-1] + and child.get_text() == 'None'): self.draw_text(ax, child, force_trans=ax.transAxes) elif isinstance(child, matplotlib.lines.Line2D): self.draw_line(ax, child, force_trans=ax.transAxes) diff --git a/plotly/offline/offline.py b/plotly/offline/offline.py index 6ab50476448..16d2d14997d 100644 --- a/plotly/offline/offline.py +++ b/plotly/offline/offline.py @@ -150,16 +150,8 @@ def init_notebook_mode(connected=False): def _plot_html(figure_or_data, config, validate, default_width, default_height, global_requirejs): - # force no validation if frames is in the call - # TODO - add validation for frames in call - #605 - if 'frames' in figure_or_data: - figure = tools.return_figure_from_figure_or_data( - figure_or_data, False - ) - else: - figure = tools.return_figure_from_figure_or_data( - figure_or_data, validate - ) + + figure = tools.return_figure_from_figure_or_data(figure_or_data, validate) width = figure.get('layout', {}).get('width', default_width) height = figure.get('layout', {}).get('height', default_height) diff --git a/plotly/plotly/plotly.py b/plotly/plotly/plotly.py index b14d4912697..e0e6c7ba03d 100644 --- a/plotly/plotly/plotly.py +++ b/plotly/plotly/plotly.py @@ -714,14 +714,7 @@ def get(figure_or_data, format='png', width=None, height=None, scale=None): """ # TODO: format is a built-in name... we shouldn't really use it - if isinstance(figure_or_data, dict): - figure = figure_or_data - elif isinstance(figure_or_data, list): - figure = {'data': figure_or_data} - else: - raise exceptions.PlotlyEmptyDataError( - "`figure_or_data` must be a dict or a list." - ) + figure = tools.return_figure_from_figure_or_data(figure_or_data, True) if format not in ['png', 'svg', 'jpeg', 'pdf']: raise exceptions.PlotlyError( diff --git a/plotly/serializers.py b/plotly/serializers.py new file mode 100644 index 00000000000..97651a44abe --- /dev/null +++ b/plotly/serializers.py @@ -0,0 +1,41 @@ + +# Create sentinal Undefined object +from traitlets import Undefined +import numpy as np + +def _py_to_js(v, widget_manager): + # print('_py_to_js') + # print(v) + if isinstance(v, dict): + return {k: _py_to_js(v, widget_manager) for k, v in v.items()} + elif isinstance(v, (list, tuple)): + return [_py_to_js(v, widget_manager) for v in v] + elif isinstance(v, np.ndarray): + if v.ndim == 1 and v.dtype.kind in ['u', 'i', 'f']: # (un)signed integer or float + return {'buffer': memoryview(v), 'dtype': str(v.dtype), 'shape': v.shape} + else: + return v.tolist() + else: + if v is Undefined: + return '_undefined_' + else: + return v + + +def _js_to_py(v, widget_manager): + # print('_js_to_py') + # print(v) + if isinstance(v, dict): + return {k: _js_to_py(v, widget_manager) for k, v in v.items()} + elif isinstance(v, (list, tuple)): + return [_js_to_py(v, widget_manager) for v in v] + elif isinstance(v, str) and v == '_undefined_': + return Undefined + else: + return v + + +custom_serializers = { + 'from_json': _js_to_py, + 'to_json': _py_to_js +} diff --git a/plotly/tests/test_core/test_graph_objs/test_scatter.py b/plotly/tests/test_core/test_graph_objs/test_scatter.py index 13af593784f..3f18c581094 100644 --- a/plotly/tests/test_core/test_graph_objs/test_scatter.py +++ b/plotly/tests/test_core/test_graph_objs/test_scatter.py @@ -14,8 +14,8 @@ def test_trivial(): print(Scatter()) - assert Scatter() == dict(type='scatter') - + assert Scatter().to_plotly_json() == dict(type='scatter', xaxis='x', yaxis='y') + #assert Scatter() == dict(type='scatter') # @raises(PlotlyError) # TODO: decide if this SHOULD raise error... # def test_instantiation_error(): diff --git a/plotly/tools.py b/plotly/tools.py index b24c391833f..8892b626d4c 100644 --- a/plotly/tools.py +++ b/plotly/tools.py @@ -1439,19 +1439,26 @@ def _repr_html_(self): def return_figure_from_figure_or_data(figure_or_data, validate_figure): - from plotly.graph_objs import graph_objs + from plotly.datatypes import Figure + from plotly.basedatatypes import BaseFigure + + validated = False if isinstance(figure_or_data, dict): figure = figure_or_data elif isinstance(figure_or_data, list): figure = {'data': figure_or_data} + elif isinstance(figure_or_data, BaseFigure): + figure = figure_or_data.to_dict() + validated = True else: raise exceptions.PlotlyError("The `figure_or_data` positional " - "argument must be either " - "`dict`-like or `list`-like.") - if validate_figure: + "argument must be " + "`dict`-like, `list`-like, or an instance of plotly.graph_objs.Figure") + + if validate_figure and not validated: try: - graph_objs.Figure(figure) + Figure(**figure) except exceptions.PlotlyError as err: raise exceptions.PlotlyError("Invalid 'figure_or_data' argument. " "Plotly will not be able to properly " diff --git a/plotlywidget/__init__.py b/plotlywidget/__init__.py new file mode 100644 index 00000000000..1e592f72173 --- /dev/null +++ b/plotlywidget/__init__.py @@ -0,0 +1,9 @@ +def _jupyter_nbextension_paths(): + return [{ + 'section': 'notebook', + 'src': 'static', + 'dest': 'plotlywidget', + 'require': 'plotlywidget/extension' + }] + +__frontend_version__ = '^0.1' \ No newline at end of file diff --git a/setup.py b/setup.py index d12b3c75989..0089be96f7a 100644 --- a/setup.py +++ b/setup.py @@ -1,13 +1,144 @@ -from setuptools import setup +from setuptools import setup, Command +from setuptools.command.build_py import build_py +from setuptools.command.egg_info import egg_info +from setuptools.command.sdist import sdist +from subprocess import check_call +from distutils import log -exec (open('plotly/version.py').read()) +import os +import sys +import platform +exec(open('plotly/version.py').read()) + +here = os.path.dirname(os.path.abspath(__file__)) +node_root = os.path.join(here, 'js') +is_repo = os.path.exists(os.path.join(here, '.git')) + +npm_path = os.pathsep.join([ + os.path.join(node_root, 'node_modules', '.bin'), + os.environ.get('PATH', os.defpath), +]) def readme(): with open('README.rst') as f: return f.read() +def js_prerelease(command, strict=False): + """decorator for building minified js/css prior to another command""" + class DecoratedCommand(command): + def run(self): + jsdeps = self.distribution.get_command_obj('jsdeps') + if not is_repo and all(os.path.exists(t) for t in jsdeps.targets): + # sdist, nothing to do + command.run(self) + return + + try: + self.distribution.run_command('jsdeps') + except Exception as e: + missing = [t for t in jsdeps.targets if not os.path.exists(t)] + if strict or missing: + log.warn('rebuilding js and css failed') + if missing: + log.error('missing files: %s' % missing) + raise e + else: + log.warn('rebuilding js and css failed (not a problem)') + log.warn(str(e)) + command.run(self) + update_package_data(self.distribution) + return DecoratedCommand + + +def update_package_data(distribution): + """update package_data to catch changes during setup""" + build_py = distribution.get_command_obj('build_py') + # distribution.package_data = find_package_data() + # re-init build_py options which load package_data + build_py.finalize_options() + + +class NPM(Command): + description = 'install package.json dependencies using npm' + + user_options = [] + + node_modules = os.path.join(node_root, 'node_modules') + + targets = [ + os.path.join(here, 'plotlywidget', 'static', 'extension.js'), + os.path.join(here, 'plotlywidget', 'static', 'index.js') + ] + + def initialize_options(self): + pass + + def finalize_options(self): + pass + + def get_npm_name(self): + npmName = 'npm' + if platform.system() == 'Windows': + npmName = 'npm.cmd' + + return npmName + + def has_npm(self): + npmName = self.get_npm_name(); + try: + check_call([npmName, '--version']) + return True + except: + return False + + def should_run_npm_install(self): + package_json = os.path.join(node_root, 'package.json') + node_modules_exists = os.path.exists(self.node_modules) + return self.has_npm() + + def run(self): + has_npm = self.has_npm() + if not has_npm: + log.error( + "`npm` unavailable. If you're running this command using sudo, make sure `npm` is available to sudo") + + env = os.environ.copy() + env['PATH'] = npm_path + + if self.should_run_npm_install(): + log.info("Installing build dependencies with npm. This may take a while...") + npmName = self.get_npm_name(); + check_call([npmName, 'install'], cwd=node_root, stdout=sys.stdout, stderr=sys.stderr) + os.utime(self.node_modules, None) + + for t in self.targets: + if not os.path.exists(t): + msg = 'Missing file: %s' % t + if not has_npm: + msg += '\nnpm is required to build a development version of widgetsnbextension' + raise ValueError(msg) + + # update package data in case this created new files + update_package_data(self.distribution) + + +class CodegenCommand(Command): + description = 'Generate class hierarchy from Plotly JSON schema' + user_options = [] + + def initialize_options(self): + pass + + def finalize_options(self): + pass + + def run(self): + from codegen import perform_codegen + perform_codegen() + + setup(name='plotly', version=__version__, use_2to3=False, @@ -31,6 +162,7 @@ def readme(): ], license='MIT', packages=['plotly', + 'plotlywidget', 'plotly/api', 'plotly/api/v1', 'plotly/api/v2', @@ -46,10 +178,25 @@ def readme(): 'plotly/matplotlylib', 'plotly/matplotlylib/mplexporter', 'plotly/matplotlylib/mplexporter/renderers'], - package_data={'plotly': ['package_data/*']}, + package_data={'plotly': ['package_data/*'], 'plotlywidget': ['static/*']}, + data_files=[ + ('share/jupyter/nbextensions/plotlywidget', [ + 'plotlywidget/static/extension.js', + 'plotlywidget/static/index.js', + 'plotlywidget/static/index.js.map', + ]), + ], install_requires=['decorator>=4.0.6', 'nbformat>=4.2', 'pytz', 'requests', 'six'], - zip_safe=False) + zip_safe=False, + cmdclass={ + 'build_py': js_prerelease(build_py), + 'egg_info': js_prerelease(egg_info), + 'sdist': js_prerelease(sdist, strict=True), + 'jsdeps': NPM, + 'codegen': CodegenCommand, + }, +) diff --git a/specs/ipyplotly_integration/Compatibility Notes.ipynb b/specs/ipyplotly_integration/Compatibility Notes.ipynb new file mode 100644 index 00000000000..48d2da13982 --- /dev/null +++ b/specs/ipyplotly_integration/Compatibility Notes.ipynb @@ -0,0 +1,350 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Overview\n", + "This notebook will contain a running set of examples of backward compatibility considerations." + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + "
\"),void 0!==t.yLabel&&(i+=\"y: \"+t.yLabel+\"
\"),i+=(i?\"z: \":\"\")+t.zLabel):z&&t[a+\"Label\"]===M?i=t[(\"x\"===a?\"y\":\"x\")+\"Label\"]||\"\":void 0===t.xLabel?void 0!==t.yLabel&&(i=t.yLabel):i=void 0===t.yLabel?t.xLabel:\"(\"+t.xLabel+\", \"+t.yLabel+\")\",t.text&&!Array.isArray(t.text)&&(i+=(i?\"
\":\"\")+t.text),\"\"===i&&(\"\"===n&&e.remove(),i=n);var y=e.select(\"text.nums\").call(m.font,t.fontFamily||h,t.fontSize||p,t.fontColor||f).text(i).attr(\"data-notex\",1).call(d.positionText,0,0).call(d.convertToTspans,r),x=e.select(\"text.name\"),b=0;n&&n!==i?(x.call(m.font,t.fontFamily||h,t.fontSize||p,u).text(n).attr(\"data-notex\",1).call(d.positionText,0,0).call(d.convertToTspans,r),b=x.node().getBoundingClientRect().width+2*E):(x.remove(),e.select(\"rect\").remove()),e.select(\"path\").style({fill:u,stroke:f});var _,k,A=y.node().getBoundingClientRect(),D=t.xa._offset+(t.x0+t.x1)/2,I=t.ya._offset+(t.y0+t.y1)/2,P=Math.abs(t.x1-t.x0),O=Math.abs(t.y1-t.y0),F=A.width+S+E+b;t.ty0=T-A.top,t.bx=A.width+2*E,t.by=A.height+2*E,t.anchor=\"start\",t.txwidth=A.width,t.tx2width=b,t.offset=0,o?(t.pos=D,_=I+O/2+F<=C,k=I-O/2-F>=0,\"top\"!==t.idealAlign&&_||!k?_?(I+=O/2,t.anchor=\"start\"):t.anchor=\"middle\":(I-=O/2,t.anchor=\"end\")):(t.pos=I,_=D+P/2+F<=L,k=D-P/2-F>=0,\"left\"!==t.idealAlign&&_||!k?_?(D+=P/2,t.anchor=\"start\"):t.anchor=\"middle\":(D-=P/2,t.anchor=\"end\")),y.attr(\"text-anchor\",t.anchor),b&&x.attr(\"text-anchor\",t.anchor),e.attr(\"transform\",\"translate(\"+D+\",\"+I+\")\"+(o?\"rotate(\"+w+\")\":\"\"))}),P}function a(t,e){t.each(function(t){var r=l.select(this);if(t.del)r.remove();else{var n=\"end\"===t.anchor?-1:1,i=r.select(\"text.nums\"),a={start:1,end:-1,middle:0}[t.anchor],o=a*(S+E),s=o+a*(t.txwidth+E),c=0,u=t.offset;\"middle\"===t.anchor&&(o-=t.tx2width/2,s-=t.tx2width/2),e&&(u*=-T,c=t.offset*A),r.select(\"path\").attr(\"d\",\"middle\"===t.anchor?\"M-\"+t.bx/2+\",-\"+t.by/2+\"h\"+t.bx+\"v\"+t.by+\"h-\"+t.bx+\"Z\":\"M0,0L\"+(n*S+c)+\",\"+(S+u)+\"v\"+(t.by/2-S)+\"h\"+n*t.bx+\"v-\"+t.by+\"H\"+(n*S+c)+\"V\"+(u-S)+\"Z\"),i.call(d.positionText,o+c,u+t.ty0-t.by/2+E),t.tx2width&&(r.select(\"text.name\").call(d.positionText,s+a*E+c,u+t.ty0-t.by/2+E),r.select(\"rect\").call(m.setRect,s+(a-1)*t.tx2width/2+c,u-t.by/2-1,t.tx2width,t.by+2))}})}function o(t,e){var r,n,i=e.container,a=e.fullLayout,o=e.event,s=!!t.hLinePoint,l=!!t.vLinePoint;if(i.selectAll(\".spikeline\").remove(),l||s){var c=g.combine(a.plot_bgcolor,a.paper_bgcolor);if(s){var f,h,d=t.hLinePoint;r=d&&d.xa;\"cursor\"===(n=d&&d.ya).spikesnap?(f=o.pointerX,h=o.pointerY):(f=r._offset+(d.x0+d.x1)/2,h=n._offset+(d.y0+d.y1)/2);var p,v,y=u.readability(d.color,c)<1.5?g.contrast(c):d.color,x=n.spikemode,b=n.spikethickness,_=n.spikecolor||y,w=n._boundingBox,M=(w.left+w.right)/2=2/3},r.isCenterAnchor=function(t){return\"center\"===t.xanchor||\"auto\"===t.xanchor&&t.x>1/3&&t.x<2/3},r.isBottomAnchor=function(t){return\"bottom\"===t.yanchor||\"auto\"===t.yanchor&&t.y<=1/3},r.isMiddleAnchor=function(t){return\"middle\"===t.yanchor||\"auto\"===t.yanchor&&t.y>1/3&&t.y<2/3}},{}],670:[function(t,e,r){\"use strict\";var n=t(\"../../plots/font_attributes\"),i=t(\"../color/attributes\");e.exports={bgcolor:{valType:\"color\",editType:\"legend\"},bordercolor:{valType:\"color\",dflt:i.defaultLine,editType:\"legend\"},borderwidth:{valType:\"number\",min:0,dflt:0,editType:\"legend\"},font:n({editType:\"legend\"}),orientation:{valType:\"enumerated\",values:[\"v\",\"h\"],dflt:\"v\",editType:\"legend\"},traceorder:{valType:\"flaglist\",flags:[\"reversed\",\"grouped\"],extras:[\"normal\"],editType:\"legend\"},tracegroupgap:{valType:\"number\",min:0,dflt:10,editType:\"legend\"},x:{valType:\"number\",min:-2,max:3,dflt:1.02,editType:\"legend\"},xanchor:{valType:\"enumerated\",values:[\"auto\",\"left\",\"center\",\"right\"],dflt:\"left\",editType:\"legend\"},y:{valType:\"number\",min:-2,max:3,dflt:1,editType:\"legend\"},yanchor:{valType:\"enumerated\",values:[\"auto\",\"top\",\"middle\",\"bottom\"],dflt:\"auto\",editType:\"legend\"},editType:\"legend\"}},{\"../../plots/font_attributes\":816,\"../color/attributes\":617}],671:[function(t,e,r){\"use strict\";e.exports={scrollBarWidth:4,scrollBarHeight:20,scrollBarColor:\"#808BA4\",scrollBarMargin:4}},{}],672:[function(t,e,r){\"use strict\";var n=t(\"../../registry\"),i=t(\"../../lib\"),a=t(\"./attributes\"),o=t(\"../../plots/layout_attributes\"),s=t(\"./helpers\");e.exports=function(t,e,r){function l(t,e){return i.coerce(d,p,a,t,e)}for(var c,u,f,h,d=t.legend||{},p=e.legend={},m=0,g=\"normal\",v=0;v1)){if(l(\"bgcolor\",e.paper_bgcolor),l(\"bordercolor\"),l(\"borderwidth\"),i.coerceFont(l,\"font\",e.font),l(\"orientation\"),\"h\"===p.orientation){var x=t.xaxis;x&&x.rangeslider&&x.rangeslider.visible?(c=0,f=\"left\",u=1.1,h=\"bottom\"):(c=0,f=\"left\",u=-.1,h=\"top\")}l(\"traceorder\",g),s.isGrouped(e.legend)&&l(\"tracegroupgap\"),l(\"x\",c),l(\"xanchor\",f),l(\"y\",u),l(\"yanchor\",h),i.noneOrAll(d,p,[\"x\",\"y\"])}}},{\"../../lib\":743,\"../../plots/layout_attributes\":843,\"../../registry\":873,\"./attributes\":670,\"./helpers\":676}],673:[function(t,e,r){\"use strict\";function n(t,e){function r(r){m.convertToTspans(r,e,function(){!function(t,e){var r=t.data()[0][0];if(!r.trace.showlegend)return void t.remove();var n,i,a=t.select(\"g[class*=math-group]\"),o=a.node(),s=e._fullLayout.legend.font.size*x;if(o){var l=d.bBox(o);n=l.height,i=l.width,d.setTranslate(a,0,n/4)}else{var c=t.select(\".legendtext\"),u=m.lineCount(c),f=c.node();n=s*u,i=f?d.bBox(f).width:0;var h=s*(.3+(1-u)/2);m.positionText(c,40,h)}n=Math.max(n,16)+3,r.height=n,r.width=i}(t,e)})}var n=t.data()[0][0],i=e._fullLayout,a=n.trace,o=f.traceIs(a,\"pie\"),s=a.index,u=o?n.label:a.name,h=t.selectAll(\"text.legendtext\").data([0]);h.enter().append(\"text\").classed(\"legendtext\",!0),h.attr(\"text-anchor\",\"start\").classed(\"user-select-none\",!0).call(d.font,i.legend.font).text(u),e._context.edits.legendText&&!o?h.call(m.makeEditable,{gd:e}).call(r).on(\"edit\",function(t){this.text(t).call(r);var i=t;this.text()||(t=\" \");var a,o=n.trace._fullInput||{},u={};if(-1!==[\"ohlc\",\"candlestick\"].indexOf(o.type))u[(a=n.trace.transforms)[a.length-1].direction+\".name\"]=t;else if(f.hasTransform(o,\"groupby\")){var h=f.getTransformIndices(o,\"groupby\"),d=h[h.length-1],p=c.keyedContainer(o,\"transforms[\"+d+\"].styles\",\"target\",\"value.name\");\"\"===i?p.remove(n.trace._group):p.set(n.trace._group,t),u=p.constructUpdate()}else u.name=t;return l.restyle(e,u,s)}):h.call(r)}function i(t,e){var r,n=1,i=t.selectAll(\"rect\").data([0]);i.enter().append(\"rect\").classed(\"legendtoggle\",!0).style(\"cursor\",\"pointer\").attr(\"pointer-events\",\"all\").call(p.fill,\"rgba(0,0,0,0)\"),i.on(\"mousedown\",function(){(r=(new Date).getTime())-e._legendMouseDownTimek&&(n=Math.max(n-1,1)),1===n?r._clickTimeout=setTimeout(function(){g(t,e,n)},k):2===n&&(r._clickTimeout&&clearTimeout(r._clickTimeout),e._legendMouseDownTime=0,g(t,e,n))}})}function a(t,e,r){var n=t._fullLayout,i=n.legend,a=i.borderwidth,o=w.isGrouped(i),l=0;if(i.width=0,i.height=0,w.isVertical(i))o&&e.each(function(t,e){d.setTranslate(this,0,e*i.tracegroupgap)}),r.each(function(t){var e=t[0],r=e.height,n=e.width;d.setTranslate(this,a,5+a+i.height+r/2),i.height+=r,i.width=Math.max(i.width,n)}),i.width+=45+2*a,i.height+=10+2*a,o&&(i.height+=(i._lgroupsLength-1)*i.tracegroupgap),l=40;else if(o){for(var c=[i.width],u=e.data(),f=0,h=u.length;fa+_-M,r.each(function(t){var e=t[0],r=g?40+t[0].width:x;a+b+M+r>n.width-(n.margin.r+n.margin.l)&&(b=0,v+=y,i.height=i.height+y,y=0),d.setTranslate(this,a+b,5+a+e.height/2+v),i.width+=M+r,i.height=Math.max(i.height,e.height),b+=M+r,y=Math.max(e.height,y)}),i.width+=2*a,i.height+=10+2*a}i.width=Math.ceil(i.width),i.height=Math.ceil(i.height),r.each(function(e){var r=e[0];s.select(this).select(\".legendtoggle\").call(d.setRect,0,-r.height/2,(t._context.edits.legendText?0:i.width)+l,r.height)})}function o(t){var e=t._fullLayout.legend,r=\"left\";M.isRightAnchor(e)?r=\"right\":M.isCenterAnchor(e)&&(r=\"center\");var n=\"top\";M.isBottomAnchor(e)?n=\"bottom\":M.isMiddleAnchor(e)&&(n=\"middle\"),u.autoMargin(t,\"legend\",{x:e.x,y:e.y,l:e.width*({right:1,center:.5}[r]||0),r:e.width*({left:1,center:.5}[r]||0),b:e.height*({top:1,middle:.5}[n]||0),t:e.height*({bottom:1,middle:.5}[n]||0)})}var s=t(\"d3\"),l=t(\"../../plotly\"),c=t(\"../../lib\"),u=t(\"../../plots/plots\"),f=t(\"../../registry\"),h=t(\"../dragelement\"),d=t(\"../drawing\"),p=t(\"../color\"),m=t(\"../../lib/svg_text_utils\"),g=t(\"./handle_click\"),v=t(\"./constants\"),y=t(\"../../constants/interactions\"),x=t(\"../../constants/alignment\").LINE_SPACING,b=t(\"./get_legend_data\"),_=t(\"./style\"),w=t(\"./helpers\"),M=t(\"./anchor_utils\"),k=y.DBLCLICKDELAY;e.exports=function(t){function e(t,e){E.attr(\"data-scroll\",e).call(d.setTranslate,0,e),L.call(d.setRect,N,t,v.scrollBarWidth,v.scrollBarHeight),T.select(\"rect\").attr({y:y.borderwidth-e})}var r=t._fullLayout,m=\"legend\"+r._uid;if(r._infolayer&&t.calcdata){t._legendMouseDownTime||(t._legendMouseDownTime=0);var y=r.legend,x=r.showlegend&&b(t.calcdata,y),w=r.hiddenlabels||[];if(!r.showlegend||!x.length)return r._infolayer.selectAll(\".legend\").remove(),r._topdefs.select(\"#\"+m).remove(),void u.autoMargin(t,\"legend\");var A=r._infolayer.selectAll(\"g.legend\").data([0]);A.enter().append(\"g\").attr({class:\"legend\",\"pointer-events\":\"all\"});var T=r._topdefs.selectAll(\"#\"+m).data([0]);T.enter().append(\"clipPath\").attr(\"id\",m).append(\"rect\");var S=A.selectAll(\"rect.bg\").data([0]);S.enter().append(\"rect\").attr({class:\"bg\",\"shape-rendering\":\"crispEdges\"}),S.call(p.stroke,y.bordercolor),S.call(p.fill,y.bgcolor),S.style(\"stroke-width\",y.borderwidth+\"px\");var E=A.selectAll(\"g.scrollbox\").data([0]);E.enter().append(\"g\").attr(\"class\",\"scrollbox\");var L=A.selectAll(\"rect.scrollbar\").data([0]);L.enter().append(\"rect\").attr({class:\"scrollbar\",rx:20,ry:2,width:0,height:0}).call(p.fill,\"#808BA4\");var C=E.selectAll(\"g.groups\").data(x);C.enter().append(\"g\").attr(\"class\",\"groups\"),C.exit().remove();var z=C.selectAll(\"g.traces\").data(c.identity);z.enter().append(\"g\").attr(\"class\",\"traces\"),z.exit().remove(),z.call(_,t).style(\"opacity\",function(t){var e=t[0].trace;return f.traceIs(e,\"pie\")?-1!==w.indexOf(t[0].label)?.5:1:\"legendonly\"===e.visible?.5:1}).each(function(){s.select(this).call(n,t).call(i,t)});var D=0!==A.enter().size();D&&(a(t,C,z),o(t));var I=r.width,P=r.height;a(t,C,z),y.height>P?function(t){var e=t._fullLayout.legend,r=\"left\";M.isRightAnchor(e)?r=\"right\":M.isCenterAnchor(e)&&(r=\"center\"),u.autoMargin(t,\"legend\",{x:e.x,y:.5,l:e.width*({right:1,center:.5}[r]||0),r:e.width*({left:1,center:.5}[r]||0),b:0,t:0})}(t):o(t);var O=r._size,F=O.l+O.w*y.x,R=O.t+O.h*(1-y.y);M.isRightAnchor(y)?F-=y.width:M.isCenterAnchor(y)&&(F-=y.width/2),M.isBottomAnchor(y)?R-=y.height:M.isMiddleAnchor(y)&&(R-=y.height/2);var N=y.width,j=O.w;N>j?(F=O.l,N=j):(F+N>I&&(F=I-N),F<0&&(F=0),N=Math.min(I-F,y.width));var B=y.height,U=O.h;B>U?(R=O.t,B=U):(R+B>P&&(R=P-B),R<0&&(R=0),B=Math.min(P-R,y.height)),d.setTranslate(A,F,R);var V,q,H=B-v.scrollBarHeight-2*v.scrollBarMargin,G=y.height-B;if(y.height<=B||t._context.staticPlot)S.attr({width:N-y.borderwidth,height:B-y.borderwidth,x:y.borderwidth/2,y:y.borderwidth/2}),d.setTranslate(E,0,0),T.select(\"rect\").attr({width:N-2*y.borderwidth,height:B-2*y.borderwidth,x:y.borderwidth,y:y.borderwidth}),E.call(d.setClipUrl,m);else{V=v.scrollBarMargin,q=E.attr(\"data-scroll\")||0,S.attr({width:N-2*y.borderwidth+v.scrollBarWidth+v.scrollBarMargin,height:B-y.borderwidth,x:y.borderwidth/2,y:y.borderwidth/2}),T.select(\"rect\").attr({width:N-2*y.borderwidth+v.scrollBarWidth+v.scrollBarMargin,height:B-2*y.borderwidth,x:y.borderwidth,y:y.borderwidth-q}),E.call(d.setClipUrl,m),D&&e(V,q),A.on(\"wheel\",null),A.on(\"wheel\",function(){q=c.constrain(E.attr(\"data-scroll\")-s.event.deltaY/H*G,-G,0),e(V=v.scrollBarMargin-q/G*H,q),0!==q&&q!==-G&&s.event.preventDefault()}),L.on(\".drag\",null),E.on(\".drag\",null);var Y=s.behavior.drag().on(\"drag\",function(){V=c.constrain(s.event.y-v.scrollBarHeight/2,v.scrollBarMargin,v.scrollBarMargin+H),q=-(V-v.scrollBarMargin)/H*G,e(V,q)});L.call(Y),E.call(Y)}if(t._context.edits.legendPosition){var W,X,Z,J;A.classed(\"cursor-move\",!0),h.init({element:A.node(),gd:t,prepFn:function(){var t=d.getTranslate(A);Z=t.x,J=t.y},moveFn:function(t,e){var r=Z+t,n=J+e;d.setTranslate(A,r,n),W=h.align(r,0,O.l,O.l+O.w,y.xanchor),X=h.align(n,0,O.t+O.h,O.t,y.yanchor)},doneFn:function(){void 0!==W&&void 0!==X&&l.relayout(t,{\"legend.x\":W,\"legend.y\":X})},clickFn:function(e,n){var i=r._infolayer.selectAll(\"g.traces\").filter(function(){var t=this.getBoundingClientRect();return n.clientX>=t.left&&n.clientX<=t.right&&n.clientY>=t.top&&n.clientY<=t.bottom});i.size()>0&&(1===e?A._clickTimeout=setTimeout(function(){g(i,t,e)},k):2===e&&(A._clickTimeout&&clearTimeout(A._clickTimeout),g(i,t,e)))}})}}}},{\"../../constants/alignment\":716,\"../../constants/interactions\":720,\"../../lib\":743,\"../../lib/svg_text_utils\":766,\"../../plotly\":784,\"../../plots/plots\":852,\"../../registry\":873,\"../color\":618,\"../dragelement\":640,\"../drawing\":643,\"./anchor_utils\":669,\"./constants\":671,\"./get_legend_data\":674,\"./handle_click\":675,\"./helpers\":676,\"./style\":678,d3:128}],674:[function(t,e,r){\"use strict\";var n=t(\"../../registry\"),i=t(\"./helpers\");e.exports=function(t,e){function r(t,r){if(\"\"!==t&&i.isGrouped(e))-1===l.indexOf(t)?(l.push(t),c=!0,s[t]=[[r]]):s[t].push([r]);else{var n=\"~~i\"+f;l.push(n),s[n]=[[r]],f++}}var a,o,s={},l=[],c=!1,u={},f=0;for(a=0;ar[1])return r[1]}return i}function i(t){return t[0]}var s,c,u=t[0],f=u.trace,h=l.hasMarkers(f),d=l.hasText(f),p=l.hasLines(f);if(h||d||p){var m={},g={};h&&(m.mc=r(\"marker.color\",i),m.mo=r(\"marker.opacity\",a.mean,[.2,1]),m.ms=r(\"marker.size\",a.mean,[2,16]),m.mlc=r(\"marker.line.color\",i),m.mlw=r(\"marker.line.width\",a.mean,[0,5]),g.marker={sizeref:1,sizemin:1,sizemode:\"diameter\"}),p&&(g.line={width:r(\"line.width\",i,[0,10])}),d&&(m.tx=\"Aa\",m.tp=r(\"textposition\",i),m.ts=10,m.tc=r(\"textfont.color\",i),m.tf=r(\"textfont.family\",i)),s=[a.minExtend(u,m)],c=a.minExtend(f,g)}var v=n.select(this).select(\"g.legendpoints\"),y=v.selectAll(\"path.scatterpts\").data(h?s:[]);y.enter().append(\"path\").classed(\"scatterpts\",!0).attr(\"transform\",\"translate(20,0)\"),y.exit().remove(),y.call(o.pointStyle,c,e),h&&(s[0].mrc=3);var x=v.selectAll(\"g.pointtext\").data(d?s:[]);x.enter().append(\"g\").classed(\"pointtext\",!0).append(\"text\").attr(\"transform\",\"translate(20,0)\"),x.exit().remove(),x.selectAll(\"text\").call(o.textPointStyle,c,e)})}},{\"../../lib\":743,\"../../registry\":873,\"../../traces/pie/style_one\":1052,\"../../traces/scatter/subtypes\":1088,\"../color\":618,\"../drawing\":643,d3:128}],679:[function(t,e,r){\"use strict\";function n(t,e){var r,n,i=e.currentTarget,a=i.getAttribute(\"data-attr\"),o=i.getAttribute(\"data-val\")||!0,s=t._fullLayout,l={},c=h.list(t,null,!0),f=\"on\";if(\"zoom\"===a){var d,p=\"in\"===o?.5:2,m=(1+p)/2,g=(1-p)/2;for(n=0;n1)return n([\"resetViews\",\"toggleHover\"]),i(x,r);h&&(n([\"zoom3d\",\"pan3d\",\"orbitRotation\",\"tableRotation\"]),n([\"resetCameraDefault3d\",\"resetCameraLastSave3d\"]),n([\"hoverClosest3d\"]));var b=function(t){for(var e=a.list({_fullLayout:t},null,!0),r=0;r0)){var d=function(t,e,r){for(var n=r.filter(function(r){return e[r].anchor===t._id}),i=0,a=0;ad&&(d=f)));return d>=h?[h,d]:void 0}}var i=t(\"../../lib\"),a=t(\"../../plots/cartesian/axes\"),o=t(\"./constants\"),s=t(\"./helpers\");e.exports=function(t){var e=t._fullLayout,r=i.filterVisible(e.shapes);if(r.length&&t._fullData.length)for(var s=0;sV&&n>q&&!t.shiftKey?f.getCursor(i/r,1-a/n):\"move\";h(e,o),U=o.split(\"-\")[0]}var c,u,d,m,g,v,y,x,b,_,w,M,k,A,T,S,E,L,C,z,D,I,P,O,F,R,N,j,B,U,V=10,q=10,H={element:e.node(),gd:t,prepFn:function(o){O=l.getFromId(t,r.xref),F=l.getFromId(t,r.yref),R=p.getDataToPixel(t,O),N=p.getDataToPixel(t,F,!0),j=p.getPixelToData(t,O),B=p.getPixelToData(t,F,!0);var f=\"shapes[\"+n+\"]\";\"path\"===r.type?(I=r.path,P=f+\".path\"):(u=R(r.x0),d=N(r.y0),m=R(r.x1),g=N(r.y1),v=f+\".x0\",y=f+\".y0\",x=f+\".x1\",b=f+\".y1\");uq&&(c[A]=r[L]=B(u),c[T]=r[C]=B(f)),d-h>V&&(c[S]=r[z]=j(h),c[E]=r[D]=j(d))}e.attr(\"d\",i(t,r))}},doneFn:function(){h(e),o.relayout(t,c)}},G=H.element.getBoundingClientRect();f.init(H),e.node().onmousemove=s}(t,m,s,e)}t._fullLayout._paperdiv.selectAll('.shapelayer [data-index=\"'+e+'\"]').remove();var n=(t.layout.shapes||[])[e],s=t._fullLayout.shapes[e];if(n&&!1!==s.visible)if(\"below\"!==s.layer)r(t._fullLayout._shapeUpperLayer);else if(\"paper\"===s.xref||\"paper\"===s.yref)r(t._fullLayout._shapeLowerLayer);else{var d=t._fullLayout._plots[s.xref+s.yref];if(d){r((d.mainplotinfo||d).shapelayer)}else r(t._fullLayout._shapeLowerLayer)}}function i(t,e){var r,n,i,a,o=e.type,c=l.getFromId(t,e.xref),u=l.getFromId(t,e.yref),f=t._fullLayout._size;if(c?(r=p.shapePositionToRange(c),n=function(t){return c._offset+c.r2p(r(t,!0))}):n=function(t){return f.l+f.w*t},u?(i=p.shapePositionToRange(u),a=function(t){return u._offset+u.r2p(i(t,!0))}):a=function(t){return f.t+f.h*(1-t)},\"path\"===o)return c&&\"date\"===c.type&&(n=p.decodeDate(n)),u&&\"date\"===u.type&&(a=p.decodeDate(a)),function(t,e,r){return t.replace(d.segmentRE,function(t){var n=0,i=t.charAt(0),a=d.paramIsX[i],o=d.paramIsY[i],l=d.numParams[i],c=t.substr(1).replace(d.paramRE,function(t){return a[n]?t=e(t):o[n]&&(t=r(t)),++n>l&&(t=\"X\"),t});return n>l&&(c=c.replace(/[\\s,]*X.*/,\"\"),s.log(\"Ignoring extra params in segment \"+t)),i+c})}(e.path,n,a);var h=n(e.x0),m=n(e.x1),g=a(e.y0),v=a(e.y1);if(\"line\"===o)return\"M\"+h+\",\"+g+\"L\"+m+\",\"+v;if(\"rect\"===o)return\"M\"+h+\",\"+g+\"H\"+m+\"V\"+v+\"H\"+h+\"Z\";var y=(h+m)/2,x=(g+v)/2,b=Math.abs(y-h),_=Math.abs(x-g),w=\"A\"+b+\",\"+_,M=y+b+\",\"+x;return\"M\"+M+w+\" 0 1,1 \"+(y+\",\"+(x-_))+w+\" 0 0,1 \"+M+\"Z\"}function a(t,e,r){return t.replace(d.segmentRE,function(t){var n=0,i=t.charAt(0),a=d.paramIsX[i],o=d.paramIsY[i],s=d.numParams[i];return i+t.substr(1).replace(d.paramRE,function(t){return n>=s?t:(a[n]?t=e(t):o[n]&&(t=r(t)),n++,t)})})}var o=t(\"../../plotly\"),s=t(\"../../lib\"),l=t(\"../../plots/cartesian/axes\"),c=t(\"../color\"),u=t(\"../drawing\"),f=t(\"../dragelement\"),h=t(\"../../lib/setcursor\"),d=t(\"./constants\"),p=t(\"./helpers\");e.exports={draw:function(t){var e=t._fullLayout;e._shapeUpperLayer.selectAll(\"path\").remove(),e._shapeLowerLayer.selectAll(\"path\").remove(),e._shapeSubplotLayers.selectAll(\"path\").remove();for(var r=0;r0)){n(\"active\"),n(\"x\"),n(\"y\"),i.noneOrAll(t,e,[\"x\",\"y\"]),n(\"xanchor\"),n(\"yanchor\"),n(\"len\"),n(\"lenmode\"),n(\"pad.t\"),n(\"pad.r\"),n(\"pad.b\"),n(\"pad.l\"),i.coerceFont(n,\"font\",r.font);n(\"currentvalue.visible\")&&(n(\"currentvalue.xanchor\"),n(\"currentvalue.prefix\"),n(\"currentvalue.suffix\"),n(\"currentvalue.offset\"),i.coerceFont(n,\"currentvalue.font\",e.font)),n(\"transition.duration\"),n(\"transition.easing\"),n(\"bgcolor\"),n(\"activebgcolor\"),n(\"bordercolor\"),n(\"borderwidth\"),n(\"ticklen\"),n(\"tickwidth\"),n(\"tickcolor\"),n(\"minorticklen\")}}var i=t(\"../../lib\"),a=t(\"../../plots/array_container_defaults\"),o=t(\"./attributes\"),s=t(\"./constants\").name,l=o.steps;e.exports=function(t,e){a(t,e,{name:s,handleItemDefaults:n})}},{\"../../lib\":743,\"../../plots/array_container_defaults\":786,\"./attributes\":704,\"./constants\":705}],707:[function(t,e,r){\"use strict\";function n(t){return t._index}function i(t,e,r){if(e.currentvalue.visible){var n,i,a=t.selectAll(\"text\").data([0]);switch(e.currentvalue.xanchor){case\"right\":n=e.inputAreaLength-M.currentValueInset-e.currentValueMaxWidth,i=\"left\";break;case\"center\":n=.5*e.inputAreaLength,i=\"middle\";break;default:n=M.currentValueInset,i=\"left\"}a.enter().append(\"text\").classed(M.labelClass,!0).classed(\"user-select-none\",!0).attr({\"text-anchor\":i,\"data-notex\":1});var o=e.currentvalue.prefix?e.currentvalue.prefix:\"\";if(\"string\"==typeof r)o+=r;else{o+=e.steps[e.active].label}e.currentvalue.suffix&&(o+=e.currentvalue.suffix),a.call(b.font,e.currentvalue.font).text(o).call(_.convertToTspans,e.gd);var s=_.lineCount(a),l=(e.currentValueMaxLines+1-s)*e.currentvalue.font.size*k;return _.positionText(a,n,l),a}}function a(t,e,r){var n=t.selectAll(\"rect.\"+M.gripRectClass).data([0]);n.enter().append(\"rect\").classed(M.gripRectClass,!0).call(u,e,t,r).style(\"pointer-events\",\"all\"),n.attr({width:M.gripWidth,height:M.gripHeight,rx:M.gripRadius,ry:M.gripRadius}).call(x.stroke,r.bordercolor).call(x.fill,r.bgcolor).style(\"stroke-width\",r.borderwidth+\"px\")}function o(t,e,r){var n=t.selectAll(\"text\").data([0]);return n.enter().append(\"text\").classed(M.labelClass,!0).classed(\"user-select-none\",!0).attr({\"text-anchor\":\"middle\",\"data-notex\":1}),n.call(b.font,r.font).text(e.step.label).call(_.convertToTspans,r.gd),n}function s(t,e){var r=t.selectAll(\"g.\"+M.labelsClass).data([0]);r.enter().append(\"g\").classed(M.labelsClass,!0);var n=r.selectAll(\"g.\"+M.labelGroupClass).data(e.labelSteps);n.enter().append(\"g\").classed(M.labelGroupClass,!0),n.exit().remove(),n.each(function(t){var r=v.select(this);r.call(o,t,e),b.setTranslate(r,d(e,t.fraction),M.tickOffset+e.ticklen+e.font.size*k+M.labelOffset+e.currentValueTotalHeight)})}function l(t,e,r,n,i){var a=Math.round(n*(r.steps.length-1));a!==r.active&&c(t,e,r,a,!0,i)}function c(t,e,r,n,a,o){var s=r.active;r._input.active=r.active=n;var l=r.steps[r.active];e.call(h,r,r.active/(r.steps.length-1),o),e.call(i,r),t.emit(\"plotly_sliderchange\",{slider:r,step:r.steps[r.active],interaction:a,previousActive:s}),l&&l.method&&a&&(e._nextMethod?(e._nextMethod.step=l,e._nextMethod.doCallback=a,e._nextMethod.doTransition=o):(e._nextMethod={step:l,doCallback:a,doTransition:o},e._nextMethodRaf=window.requestAnimationFrame(function(){var r=e._nextMethod.step;r.method&&(r.execute&&y.executeAPICommand(t,r.method,r.args),e._nextMethod=null,e._nextMethodRaf=null)})))}function u(t,e,r){function n(){return r.data()[0]}var i=r.node(),a=v.select(e);t.on(\"mousedown\",function(){var t=n();e.emit(\"plotly_sliderstart\",{slider:t});var o=r.select(\".\"+M.gripRectClass);v.event.stopPropagation(),v.event.preventDefault(),o.call(x.fill,t.activebgcolor);var s=p(t,v.mouse(i)[0]);l(e,r,t,s,!0),t._dragging=!0,a.on(\"mousemove\",function(){var t=n(),a=p(t,v.mouse(i)[0]);l(e,r,t,a,!1)}),a.on(\"mouseup\",function(){var t=n();t._dragging=!1,o.call(x.fill,t.bgcolor),a.on(\"mouseup\",null),a.on(\"mousemove\",null),e.emit(\"plotly_sliderend\",{slider:t,step:t.steps[t.active]})})})}function f(t,e){var r=t.selectAll(\"rect.\"+M.tickRectClass).data(e.steps);r.enter().append(\"rect\").classed(M.tickRectClass,!0),r.exit().remove(),r.attr({width:e.tickwidth+\"px\",\"shape-rendering\":\"crispEdges\"}),r.each(function(t,r){var n=r%e.labelStride==0,i=v.select(this);i.attr({height:n?e.ticklen:e.minorticklen}).call(x.fill,e.tickcolor),b.setTranslate(i,d(e,r/(e.steps.length-1))-.5*e.tickwidth,(n?M.tickOffset:M.minorTickOffset)+e.currentValueTotalHeight)})}function h(t,e,r,n){var i=t.select(\"rect.\"+M.gripRectClass),a=d(e,r);if(!e._invokingCommand){var o=i;n&&e.transition.duration>0&&(o=o.transition().duration(e.transition.duration).ease(e.transition.easing)),o.attr(\"transform\",\"translate(\"+(a-.5*M.gripWidth)+\",\"+e.currentValueTotalHeight+\")\")}}function d(t,e){return t.inputAreaStart+M.stepInset+(t.inputAreaLength-2*M.stepInset)*Math.min(1,Math.max(0,e))}function p(t,e){return Math.min(1,Math.max(0,(e-M.stepInset-t.inputAreaStart)/(t.inputAreaLength-2*M.stepInset-2*t.inputAreaStart)))}function m(t,e,r){var n=t.selectAll(\"rect.\"+M.railTouchRectClass).data([0]);n.enter().append(\"rect\").classed(M.railTouchRectClass,!0).call(u,e,t,r).style(\"pointer-events\",\"all\"),n.attr({width:r.inputAreaLength,height:Math.max(r.inputAreaWidth,M.tickOffset+r.ticklen+r.labelHeight)}).call(x.fill,r.bgcolor).attr(\"opacity\",0),b.setTranslate(n,0,r.currentValueTotalHeight)}function g(t,e){var r=t.selectAll(\"rect.\"+M.railRectClass).data([0]);r.enter().append(\"rect\").classed(M.railRectClass,!0);var n=e.inputAreaLength-2*M.railInset;r.attr({width:n,height:M.railWidth,rx:M.railRadius,ry:M.railRadius,\"shape-rendering\":\"crispEdges\"}).call(x.stroke,e.bordercolor).call(x.fill,e.bgcolor).style(\"stroke-width\",e.borderwidth+\"px\"),b.setTranslate(r,M.railInset,.5*(e.inputAreaWidth-M.railWidth)+e.currentValueTotalHeight)}var v=t(\"d3\"),y=t(\"../../plots/plots\"),x=t(\"../color\"),b=t(\"../drawing\"),_=t(\"../../lib/svg_text_utils\"),w=t(\"../legend/anchor_utils\"),M=t(\"./constants\"),k=t(\"../../constants/alignment\").LINE_SPACING;e.exports=function(t){var e=t._fullLayout,r=function(t,e){for(var r=t[M.name],n=[],i=0;i0?[0]:[]);if(l.enter().append(\"g\").classed(M.containerClassName,!0).style(\"cursor\",\"ew-resize\"),l.exit().remove(),l.exit().size()&&function(t){for(var e=t._fullLayout._pushmargin||{},r=Object.keys(e),n=0;n=r.steps.length&&(r.active=0),e.call(i,r).call(g,r).call(s,r).call(f,r).call(m,t,r).call(a,t,r),b.setTranslate(e,r.lx+r.pad.l,r.ly+r.pad.t),e.call(h,r,r.active/(r.steps.length-1),!1),e.call(i,r)}(t,v.select(this),e)}})}}},{\"../../constants/alignment\":716,\"../../lib/svg_text_utils\":766,\"../../plots/plots\":852,\"../color\":618,\"../drawing\":643,\"../legend/anchor_utils\":669,\"./constants\":705,d3:128}],708:[function(t,e,r){\"use strict\";var n=t(\"./constants\");e.exports={moduleType:\"component\",name:n.name,layoutAttributes:t(\"./attributes\"),supplyLayoutDefaults:t(\"./defaults\"),draw:t(\"./draw\")}},{\"./attributes\":704,\"./constants\":705,\"./defaults\":706,\"./draw\":707}],709:[function(t,e,r){\"use strict\";var n=t(\"d3\"),i=t(\"fast-isnumeric\"),a=t(\"../../plotly\"),o=t(\"../../plots/plots\"),s=t(\"../../lib\"),l=t(\"../drawing\"),c=t(\"../color\"),u=t(\"../../lib/svg_text_utils\"),f=t(\"../../constants/interactions\"),h=/ [XY][0-9]* /;(e.exports={}).draw=function(t,e,r){function d(t){s.syncOrAsync([p,m],t)}function p(e){var r;return M?(r=\"\",M.rotate&&(r+=\"rotate(\"+[M.rotate,w.x,w.y]+\")\"),M.offset&&(r+=\"translate(0, \"+M.offset+\")\")):r=null,e.attr(\"transform\",r),e.style({\"font-family\":S,\"font-size\":n.round(E,2)+\"px\",fill:c.rgb(L),opacity:C*c.opacity(L),\"font-weight\":o.fontWeight}).attr(w).call(u.convertToTspans,t),o.previousPromises(t)}function m(t){var e=n.select(t.node().parentNode);if(_&&_.selection&&_.side&&D){e.attr(\"transform\",null);var r=0,a={left:\"right\",right:\"left\",top:\"bottom\",bottom:\"top\"}[_.side],o=-1!==[\"left\",\"top\"].indexOf(_.side)?-1:1,c=i(_.pad)?_.pad:2,u=l.bBox(e.node()),f={left:0,top:0,right:A.width,bottom:A.height},h=_.maxShift||(f[_.side]-u[_.side])*(\"left\"===_.side||\"top\"===_.side?-1:1);if(h<0)r=h;else{var d=_.offsetLeft||0,p=_.offsetTop||0;u.left-=d,u.right-=d,u.top-=p,u.bottom-=p,_.selection.each(function(){var t=l.bBox(this);s.bBoxIntersect(u,t,c)&&(r=Math.max(r,o*(t[_.side]-u[a])+c))}),r=Math.min(h,r)}if(r>0||h<0){var m={left:[-r,0],right:[r,0],top:[0,-r],bottom:[0,r]}[_.side];e.attr(\"transform\",\"translate(\"+m+\")\")}}}var g,v=r.propContainer,y=r.propName,x=r.placeholder,b=r.traceIndex,_=r.avoid||{},w=r.attributes,M=r.transform,k=r.containerGroup,A=t._fullLayout,T=v.titlefont||{},S=T.family,E=T.size,L=T.color,C=1,z=!1,D=(v.title||\"\").trim();\"title\"===y?g=\"titleText\":-1!==y.indexOf(\"axis\")?g=\"axisTitleText\":y.indexOf(!0)&&(g=\"colorbarTitleText\");var I=t._context.edits[g];\"\"===D?C=0:D.replace(h,\" % \")===x.replace(h,\" % \")&&(C=.2,z=!0,I||(D=\"\"));var P=D||I;k||(k=A._infolayer.selectAll(\".g-\"+e).data([0])).enter().append(\"g\").classed(\"g-\"+e,!0);var O=k.selectAll(\"text\").data(P?[0]:[]);return O.enter().append(\"text\"),O.text(D).attr(\"class\",e),O.exit().remove(),P?(O.call(d),I&&(D?O.on(\".opacity\",null):(C=0,z=!0,O.text(x).on(\"mouseover.opacity\",function(){n.select(this).transition().duration(f.SHOW_PLACEHOLDER).style(\"opacity\",1)}).on(\"mouseout.opacity\",function(){n.select(this).transition().duration(f.HIDE_PLACEHOLDER).style(\"opacity\",0)})),O.call(u.makeEditable,{gd:t}).on(\"edit\",function(e){void 0!==b?a.restyle(t,y,e,b):a.relayout(t,y,e)}).on(\"cancel\",function(){this.text(this.attr(\"data-unformatted\")).call(d)}).on(\"input\",function(t){this.text(t||\" \").call(u.positionText,w.x,w.y)})),O.classed(\"js-placeholder\",z),k):k}},{\"../../constants/interactions\":720,\"../../lib\":743,\"../../lib/svg_text_utils\":766,\"../../plotly\":784,\"../../plots/plots\":852,\"../color\":618,\"../drawing\":643,d3:128,\"fast-isnumeric\":140}],710:[function(t,e,r){\"use strict\";var n=t(\"../../plots/font_attributes\"),i=t(\"../color/attributes\"),a=t(\"../../lib/extend\").extendFlat,o=t(\"../../plot_api/edit_types\").overrideAll,s=t(\"../../plots/pad_attributes\");e.exports=o({_isLinkedToArray:\"updatemenu\",_arrayAttrRegexps:[/^updatemenus\\[(0|[1-9][0-9]+)\\]\\.buttons/],visible:{valType:\"boolean\"},type:{valType:\"enumerated\",values:[\"dropdown\",\"buttons\"],dflt:\"dropdown\"},direction:{valType:\"enumerated\",values:[\"left\",\"right\",\"up\",\"down\"],dflt:\"down\"},active:{valType:\"integer\",min:-1,dflt:0},showactive:{valType:\"boolean\",dflt:!0},buttons:{_isLinkedToArray:\"button\",method:{valType:\"enumerated\",values:[\"restyle\",\"relayout\",\"animate\",\"update\",\"skip\"],dflt:\"restyle\"},args:{valType:\"info_array\",freeLength:!0,items:[{valType:\"any\"},{valType:\"any\"},{valType:\"any\"}]},label:{valType:\"string\",dflt:\"\"},execute:{valType:\"boolean\",dflt:!0}},x:{valType:\"number\",min:-2,max:3,dflt:-.05},xanchor:{valType:\"enumerated\",values:[\"auto\",\"left\",\"center\",\"right\"],dflt:\"right\"},y:{valType:\"number\",min:-2,max:3,dflt:1},yanchor:{valType:\"enumerated\",values:[\"auto\",\"top\",\"middle\",\"bottom\"],dflt:\"top\"},pad:a({},s,{}),font:n({}),bgcolor:{valType:\"color\"},bordercolor:{valType:\"color\",dflt:i.borderLine},borderwidth:{valType:\"number\",min:0,dflt:1,editType:\"arraydraw\"}},\"arraydraw\",\"from-root\")},{\"../../lib/extend\":732,\"../../plot_api/edit_types\":773,\"../../plots/font_attributes\":816,\"../../plots/pad_attributes\":851,\"../color/attributes\":617}],711:[function(t,e,r){\"use strict\";e.exports={name:\"updatemenus\",containerClassName:\"updatemenu-container\",headerGroupClassName:\"updatemenu-header-group\",headerClassName:\"updatemenu-header\",headerArrowClassName:\"updatemenu-header-arrow\",dropdownButtonGroupClassName:\"updatemenu-dropdown-button-group\",dropdownButtonClassName:\"updatemenu-dropdown-button\",buttonClassName:\"updatemenu-button\",itemRectClassName:\"updatemenu-item-rect\",itemTextClassName:\"updatemenu-item-text\",menuIndexAttrName:\"updatemenu-active-index\",autoMarginIdRoot:\"updatemenu-\",blankHeaderOpts:{label:\" \"},minWidth:30,minHeight:30,textPadX:24,arrowPadX:16,rx:2,ry:2,textOffsetX:12,textOffsetY:3,arrowOffsetX:4,gapButtonHeader:5,gapButton:2,activeColor:\"#F4FAFF\",hoverColor:\"#F4FAFF\",arrowSymbol:{left:\"\\u25c4\",right:\"\\u25ba\",up:\"\\u25b2\",down:\"\\u25bc\"}}},{}],712:[function(t,e,r){\"use strict\";function n(t,e,r){function n(r,n){return i.coerce(t,e,o,r,n)}n(\"visible\",function(t,e){function r(t,e){return i.coerce(n,a,l,t,e)}var n,a,o=t.buttons||[],s=e.buttons=[];for(var c=0;c0)&&(n(\"active\"),n(\"direction\"),n(\"type\"),n(\"showactive\"),n(\"x\"),n(\"y\"),i.noneOrAll(t,e,[\"x\",\"y\"]),n(\"xanchor\"),n(\"yanchor\"),n(\"pad.t\"),n(\"pad.r\"),n(\"pad.b\"),n(\"pad.l\"),i.coerceFont(n,\"font\",r.font),n(\"bgcolor\",r.paper_bgcolor),n(\"bordercolor\"),n(\"borderwidth\"))}var i=t(\"../../lib\"),a=t(\"../../plots/array_container_defaults\"),o=t(\"./attributes\"),s=t(\"./constants\").name,l=o.buttons;e.exports=function(t,e){a(t,e,{name:s,handleItemDefaults:n})}},{\"../../lib\":743,\"../../plots/array_container_defaults\":786,\"./attributes\":710,\"./constants\":711}],713:[function(t,e,r){\"use strict\";function n(t){return t._index}function i(t,e){return+t.attr(M.menuIndexAttrName)===e._index}function a(t,e,r,n,i,a,l,c){e._input.active=e.active=l,\"buttons\"===e.type?s(t,n,null,null,e):\"dropdown\"===e.type&&(i.attr(M.menuIndexAttrName,\"-1\"),o(t,n,i,a,e),c||s(t,n,i,a,e))}function o(t,e,r,n,a){var o=e.selectAll(\"g.\"+M.headerClassName).data([0]);o.enter().append(\"g\").classed(M.headerClassName,!0).style(\"pointer-events\",\"all\");var c=a.active,u=a.buttons[c]||M.blankHeaderOpts,f={y:a.pad.t,yPad:0,x:a.pad.l,xPad:0,index:0},g={width:a.headerWidth,height:a.headerHeight};o.call(l,a,u,t).call(p,a,f,g);var v=e.selectAll(\"text.\"+M.headerArrowClassName).data([0]);v.enter().append(\"text\").classed(M.headerArrowClassName,!0).classed(\"user-select-none\",!0).attr(\"text-anchor\",\"end\").call(x.font,a.font).text(M.arrowSymbol[a.direction]),v.attr({x:a.headerWidth-M.arrowOffsetX+a.pad.l,y:a.headerHeight/2+M.textOffsetY+a.pad.t}),o.on(\"click\",function(){r.call(m),r.attr(M.menuIndexAttrName,i(r,a)?-1:String(a._index)),s(t,e,r,n,a)}),o.on(\"mouseover\",function(){o.call(h)}),o.on(\"mouseout\",function(){o.call(d,a)}),x.setTranslate(e,a.lx,a.ly)}function s(t,e,r,n,i){r||(r=e).attr(\"pointer-events\",\"all\");var o=function(t){return-1==+t.attr(M.menuIndexAttrName)}(r)&&\"buttons\"!==i.type?[]:i.buttons,s=\"dropdown\"===i.type?M.dropdownButtonClassName:M.buttonClassName,c=r.selectAll(\"g.\"+s).data(o),u=c.enter().append(\"g\").classed(s,!0),m=c.exit();\"dropdown\"===i.type?(u.attr(\"opacity\",\"0\").transition().attr(\"opacity\",\"1\"),m.transition().attr(\"opacity\",\"0\").remove()):m.remove();var y=0,x=0,b=-1!==[\"up\",\"down\"].indexOf(i.direction);\"dropdown\"===i.type&&(b?x=i.headerHeight+M.gapButtonHeader:y=i.headerWidth+M.gapButtonHeader),\"dropdown\"===i.type&&\"up\"===i.direction&&(x=-M.gapButtonHeader+M.gapButton-i.openHeight),\"dropdown\"===i.type&&\"left\"===i.direction&&(y=-M.gapButtonHeader+M.gapButton-i.openWidth);var _={x:i.lx+y+i.pad.l,y:i.ly+x+i.pad.t,yPad:M.gapButton,xPad:M.gapButton,index:0},w={l:_.x+i.borderwidth,t:_.y+i.borderwidth};c.each(function(o,s){var u=g.select(this);u.call(l,i,o,t).call(p,i,_),u.on(\"click\",function(){g.event.defaultPrevented||(a(t,i,0,e,r,n,s),o.execute&&v.executeAPICommand(t,o.method,o.args),t.emit(\"plotly_buttonclicked\",{menu:i,button:o,active:i.active}))}),u.on(\"mouseover\",function(){u.call(h)}),u.on(\"mouseout\",function(){u.call(d,i),c.call(f,i)})}),c.call(f,i),b?(w.w=Math.max(i.openWidth,i.headerWidth),w.h=_.y-w.t):(w.w=_.x-w.l,w.h=Math.max(i.openHeight,i.headerHeight)),w.direction=i.direction,n&&(c.size()?function(t,e,r,n,i,a){var o,s,l,c=i.direction,u=\"up\"===c||\"down\"===c,f=i.active;if(u)for(s=0,l=0;l0?[0]:[]);if(c.enter().append(\"g\").classed(M.containerClassName,!0).style(\"cursor\",\"pointer\"),c.exit().remove(),c.exit().size()&&function(t){for(var e=t._fullLayout._pushmargin||{},r=Object.keys(e),n=0;nw,A=n.barLength+2*n.barPad,T=n.barWidth+2*n.barPad,S=p,E=g+v;E+T>c&&(E=c-T);var L=this.container.selectAll(\"rect.scrollbar-horizontal\").data(k?[0]:[]);L.exit().on(\".drag\",null).remove(),L.enter().append(\"rect\").classed(\"scrollbar-horizontal\",!0).call(a.fill,n.barColor),k?(this.hbar=L.attr({rx:n.barRadius,ry:n.barRadius,x:S,y:E,width:A,height:T}),this._hbarXMin=S+A/2,this._hbarTranslateMax=w-A):(delete this.hbar,delete this._hbarXMin,delete this._hbarTranslateMax);var C=v>M,z=n.barWidth+2*n.barPad,D=n.barLength+2*n.barPad,I=p+m,P=g;I+z>l&&(I=l-z);var O=this.container.selectAll(\"rect.scrollbar-vertical\").data(C?[0]:[]);O.exit().on(\".drag\",null).remove(),O.enter().append(\"rect\").classed(\"scrollbar-vertical\",!0).call(a.fill,n.barColor),C?(this.vbar=O.attr({rx:n.barRadius,ry:n.barRadius,x:I,y:P,width:z,height:D}),this._vbarYMin=P+D/2,this._vbarTranslateMax=M-D):(delete this.vbar,delete this._vbarYMin,delete this._vbarTranslateMax);var F=this.id,R=u-.5,N=C?f+z+.5:f+.5,j=h-.5,B=k?d+T+.5:d+.5,U=s._topdefs.selectAll(\"#\"+F).data(k||C?[0]:[]);if(U.exit().remove(),U.enter().append(\"clipPath\").attr(\"id\",F).append(\"rect\"),k||C?(this._clipRect=U.select(\"rect\").attr({x:Math.floor(R),y:Math.floor(j),width:Math.ceil(N)-Math.floor(R),height:Math.ceil(B)-Math.floor(j)}),this.container.call(o.setClipUrl,F),this.bg.attr({x:p,y:g,width:m,height:v})):(this.bg.attr({width:0,height:0}),this.container.on(\"wheel\",null).on(\".drag\",null).call(o.setClipUrl,null),delete this._clipRect),k||C){var V=i.behavior.drag().on(\"dragstart\",function(){i.event.sourceEvent.preventDefault()}).on(\"drag\",this._onBoxDrag.bind(this));this.container.on(\"wheel\",null).on(\"wheel\",this._onBoxWheel.bind(this)).on(\".drag\",null).call(V);var q=i.behavior.drag().on(\"dragstart\",function(){i.event.sourceEvent.preventDefault(),i.event.sourceEvent.stopPropagation()}).on(\"drag\",this._onBarDrag.bind(this));k&&this.hbar.on(\".drag\",null).call(q),C&&this.vbar.on(\".drag\",null).call(q)}this.setTranslate(e,r)},n.prototype.disable=function(){(this.hbar||this.vbar)&&(this.bg.attr({width:0,height:0}),this.container.on(\"wheel\",null).on(\".drag\",null).call(o.setClipUrl,null),delete this._clipRect),this.hbar&&(this.hbar.on(\".drag\",null),this.hbar.remove(),delete this.hbar,delete this._hbarXMin,delete this._hbarTranslateMax),this.vbar&&(this.vbar.on(\".drag\",null),this.vbar.remove(),delete this.vbar,delete this._vbarYMin,delete this._vbarTranslateMax)},n.prototype._onBoxDrag=function(){var t=this.translateX,e=this.translateY;this.hbar&&(t-=i.event.dx),this.vbar&&(e-=i.event.dy),this.setTranslate(t,e)},n.prototype._onBoxWheel=function(){var t=this.translateX,e=this.translateY;this.hbar&&(t+=i.event.deltaY),this.vbar&&(e+=i.event.deltaY),this.setTranslate(t,e)},n.prototype._onBarDrag=function(){var t=this.translateX,e=this.translateY;if(this.hbar){var r=t+this._hbarXMin,n=r+this._hbarTranslateMax;t=(s.constrain(i.event.x,r,n)-r)/(n-r)*(this.position.w-this._box.w)}if(this.vbar){var a=e+this._vbarYMin,o=a+this._vbarTranslateMax;e=(s.constrain(i.event.y,a,o)-a)/(o-a)*(this.position.h-this._box.h)}this.setTranslate(t,e)},n.prototype.setTranslate=function(t,e){var r=this.position.w-this._box.w,n=this.position.h-this._box.h;if(t=s.constrain(t||0,0,r),e=s.constrain(e||0,0,n),this.translateX=t,this.translateY=e,this.container.call(o.setTranslate,this._box.l-this.position.l-t,this._box.t-this.position.t-e),this._clipRect&&this._clipRect.attr({x:Math.floor(this.position.l+t-.5),y:Math.floor(this.position.t+e-.5)}),this.hbar){var i=t/r;this.hbar.call(o.setTranslate,t+i*this._hbarTranslateMax,e)}if(this.vbar){var a=e/n;this.vbar.call(o.setTranslate,t,e+a*this._vbarTranslateMax)}}},{\"../../lib\":743,\"../color\":618,\"../drawing\":643,d3:128}],716:[function(t,e,r){\"use strict\";e.exports={FROM_BL:{left:0,center:.5,right:1,bottom:0,middle:.5,top:1},FROM_TL:{left:0,center:.5,right:1,bottom:1,middle:.5,top:0},LINE_SPACING:1.3,MID_SHIFT:.35,OPPOSITE_SIDE:{left:\"right\",right:\"left\",top:\"bottom\",bottom:\"top\"}}},{}],717:[function(t,e,r){\"use strict\";e.exports={solid:[1],dot:[1,1],dash:[4,1],longdash:[8,1],dashdot:[4,1,1,1],longdashdot:[8,1,1,1]}},{}],718:[function(t,e,r){\"use strict\";e.exports={solid:[[],0],dot:[[.5,1],200],dash:[[.5,1],50],longdash:[[.5,1],10],dashdot:[[.5,.625,.875,1],50],longdashdot:[[.5,.7,.8,1],10]}},{}],719:[function(t,e,r){\"use strict\";e.exports={circle:\"\\u25cf\",\"circle-open\":\"\\u25cb\",square:\"\\u25a0\",\"square-open\":\"\\u25a1\",diamond:\"\\u25c6\",\"diamond-open\":\"\\u25c7\",cross:\"+\",x:\"\\u274c\"}},{}],720:[function(t,e,r){\"use strict\";e.exports={SHOW_PLACEHOLDER:100,HIDE_PLACEHOLDER:1e3,DBLCLICKDELAY:300,DESELECTDIM:.2}},{}],721:[function(t,e,r){\"use strict\";e.exports={BADNUM:void 0,FP_SAFE:Number.MAX_VALUE/1e4,ONEAVGYEAR:315576e5,ONEAVGMONTH:26298e5,ONEDAY:864e5,ONEHOUR:36e5,ONEMIN:6e4,ONESEC:1e3,EPOCHJD:2440587.5,ALMOST_EQUAL:1-1e-6,MINUS_SIGN:\"\\u2212\"}},{}],722:[function(t,e,r){\"use strict\";e.exports={entityToUnicode:{mu:\"\\u03bc\",\"#956\":\"\\u03bc\",amp:\"&\",\"#28\":\"&\",lt:\"<\",\"#60\":\"<\",gt:\">\",\"#62\":\">\",nbsp:\"\\xa0\",\"#160\":\"\\xa0\",times:\"\\xd7\",\"#215\":\"\\xd7\",plusmn:\"\\xb1\",\"#177\":\"\\xb1\",deg:\"\\xb0\",\"#176\":\"\\xb0\"}}},{}],723:[function(t,e,r){\"use strict\";r.xmlns=\"http://www.w3.org/2000/xmlns/\",r.svg=\"http://www.w3.org/2000/svg\",r.xlink=\"http://www.w3.org/1999/xlink\",r.svgAttrs={xmlns:r.svg,\"xmlns:xlink\":r.xlink}},{}],724:[function(t,e,r){\"use strict\";var n=t(\"./plotly\");r.version=\"1.33.1\",t(\"es6-promise\").polyfill(),t(\"../build/plotcss\"),t(\"./fonts/mathjax_config\"),r.plot=n.plot,r.newPlot=n.newPlot,r.restyle=n.restyle,r.relayout=n.relayout,r.redraw=n.redraw,r.update=n.update,r.extendTraces=n.extendTraces,r.prependTraces=n.prependTraces,r.addTraces=n.addTraces,r.deleteTraces=n.deleteTraces,r.moveTraces=n.moveTraces,r.purge=n.purge,r.setPlotConfig=t(\"./plot_api/set_plot_config\"),r.register=t(\"./plot_api/register\"),r.toImage=t(\"./plot_api/to_image\"),r.downloadImage=t(\"./snapshot/download\"),r.validate=t(\"./plot_api/validate\"),r.addFrames=n.addFrames,r.deleteFrames=n.deleteFrames,r.animate=n.animate,r.register(t(\"./traces/scatter\")),r.register([t(\"./components/fx\"),t(\"./components/legend\"),t(\"./components/annotations\"),t(\"./components/annotations3d\"),t(\"./components/shapes\"),t(\"./components/images\"),t(\"./components/updatemenus\"),t(\"./components/sliders\"),t(\"./components/rangeslider\"),t(\"./components/rangeselector\")]),r.register([t(\"./locale-en\"),t(\"./locale-en-us\")]),r.Icons=t(\"../build/ploticon\"),r.Plots=n.Plots,r.Fx=t(\"./components/fx\"),r.Snapshot=t(\"./snapshot\"),r.PlotSchema=t(\"./plot_api/plot_schema\"),r.Queue=t(\"./lib/queue\"),r.d3=t(\"d3\")},{\"../build/plotcss\":1,\"../build/ploticon\":2,\"./components/annotations\":609,\"./components/annotations3d\":614,\"./components/fx\":660,\"./components/images\":668,\"./components/legend\":677,\"./components/rangeselector\":689,\"./components/rangeslider\":695,\"./components/shapes\":702,\"./components/sliders\":708,\"./components/updatemenus\":714,\"./fonts/mathjax_config\":725,\"./lib/queue\":757,\"./locale-en\":771,\"./locale-en-us\":770,\"./plot_api/plot_schema\":778,\"./plot_api/register\":779,\"./plot_api/set_plot_config\":780,\"./plot_api/to_image\":782,\"./plot_api/validate\":783,\"./plotly\":784,\"./snapshot\":878,\"./snapshot/download\":875,\"./traces/scatter\":1078,d3:128,\"es6-promise\":137}],725:[function(t,e,r){\"use strict\";\"undefined\"!=typeof MathJax?(r.MathJax=!0,MathJax.Hub.Config({messageStyle:\"none\",skipStartupTypeset:!0,displayAlign:\"left\",tex2jax:{inlineMath:[[\"$\",\"$\"],[\"\\\\(\",\"\\\\)\"]]}}),MathJax.Hub.Configured()):r.MathJax=!1},{}],726:[function(t,e,r){\"use strict\";var n=Math.PI;r.deg2rad=function(t){return t/180*n},r.rad2deg=function(t){return t/n*180},r.wrap360=function(t){var e=t%360;return e<0?e+360:e},r.wrap180=function(t){return Math.abs(t)>180&&(t-=360*Math.round(t/360)),t}},{}],727:[function(t,e,r){\"use strict\";var n=t(\"fast-isnumeric\"),i=t(\"../constants/numerical\").BADNUM,a=/^['\"%,$#\\s']+|[, ]|['\"%,$#\\s']+$/g;e.exports=function(t){return\"string\"==typeof t&&(t=t.replace(a,\"\")),n(t)?Number(t):i}},{\"../constants/numerical\":721,\"fast-isnumeric\":140}],728:[function(t,e,r){\"use strict\";var n=t(\"fast-isnumeric\"),i=t(\"tinycolor2\"),a=t(\"../plots/attributes\"),o=t(\"../components/colorscale/get_scale\"),s=(Object.keys(t(\"../components/colorscale/scales\")),t(\"./nested_property\")),l=t(\"./regex\").counter,c=t(\"../constants/interactions\").DESELECTDIM,u=t(\"./angles\").wrap180;r.valObjectMeta={data_array:{coerceFunction:function(t,e,r){Array.isArray(t)?e.set(t):void 0!==r&&e.set(r)}},enumerated:{coerceFunction:function(t,e,r,n){n.coerceNumber&&(t=+t),-1===n.values.indexOf(t)?e.set(r):e.set(t)},validateFunction:function(t,e){e.coerceNumber&&(t=+t);for(var r=e.values,n=0;ni.max?e.set(r):e.set(+t)}},integer:{coerceFunction:function(t,e,r,i){t%1||!n(t)||void 0!==i.min&&ti.max?e.set(r):e.set(+t)}},string:{coerceFunction:function(t,e,r,n){if(\"string\"!=typeof t){var i=\"number\"==typeof t;!0!==n.strict&&i?e.set(String(t)):e.set(r)}else n.noBlank&&!t?e.set(r):e.set(t)}},color:{coerceFunction:function(t,e,r){i(t).isValid()?e.set(t):e.set(r)}},colorlist:{coerceFunction:function(t,e,r){Array.isArray(t)&&t.length&&t.every(function(t){return i(t).isValid()})?e.set(t):e.set(r)}},colorscale:{coerceFunction:function(t,e,r){e.set(o(t,r))}},angle:{coerceFunction:function(t,e,r){\"auto\"===t?e.set(\"auto\"):n(t)?e.set(u(+t)):e.set(r)}},subplotid:{coerceFunction:function(t,e,r){\"string\"==typeof t&&l(r).test(t)?e.set(t):e.set(r)},validateFunction:function(t,e){var r=e.dflt;return t===r||\"string\"==typeof t&&!!l(r).test(t)}},flaglist:{coerceFunction:function(t,e,r,n){if(\"string\"==typeof t)if(-1===(n.extras||[]).indexOf(t)){for(var i=t.split(\"+\"),a=0;a0&&(a=a.replace(/0+$/,\"\").replace(/[\\.]$/,\"\")),n+=\":\"+a}return n}function s(t){return t.formatDate(\"yyyy\")}var l=t(\"d3\"),c=t(\"fast-isnumeric\"),u=t(\"./loggers\"),f=t(\"./mod\"),h=t(\"../constants/numerical\"),d=h.BADNUM,p=h.ONEDAY,m=h.ONEHOUR,g=h.ONEMIN,v=h.ONESEC,y=h.EPOCHJD,x=t(\"../registry\"),b=l.time.format.utc,_=/^\\s*(-?\\d\\d\\d\\d|\\d\\d)(-(\\d?\\d)(-(\\d?\\d)([ Tt]([01]?\\d|2[0-3])(:([0-5]\\d)(:([0-5]\\d(\\.\\d+)?))?(Z|z|[+\\-]\\d\\d:?\\d\\d)?)?)?)?)?\\s*$/m,w=/^\\s*(-?\\d\\d\\d\\d|\\d\\d)(-(\\d?\\di?)(-(\\d?\\d)([ Tt]([01]?\\d|2[0-3])(:([0-5]\\d)(:([0-5]\\d(\\.\\d+)?))?(Z|z|[+\\-]\\d\\d:?\\d\\d)?)?)?)?)?\\s*$/m,M=(new Date).getFullYear()-70;r.dateTick0=function(t,e){return n(t)?e?x.getComponentMethod(\"calendars\",\"CANONICAL_SUNDAY\")[t]:x.getComponentMethod(\"calendars\",\"CANONICAL_TICK\")[t]:e?\"2000-01-02\":\"2000-01-01\"},r.dfltRange=function(t){return n(t)?x.getComponentMethod(\"calendars\",\"DFLTRANGE\")[t]:[\"2000-01-01\",\"2001-01-01\"]},r.isJSDate=function(t){return\"object\"==typeof t&&null!==t&&\"function\"==typeof t.getTime};var k,A;r.dateTime2ms=function(t,e){if(r.isJSDate(t))return(t=Number(t)-t.getTimezoneOffset()*g)>=k&&t<=A?t:d;if(\"string\"!=typeof t&&\"number\"!=typeof t)return d;t=String(t);var i=n(e),a=t.charAt(0);!i||\"G\"!==a&&\"g\"!==a||(t=t.substr(1),e=\"\");var o=i&&\"chinese\"===e.substr(0,7),s=t.match(o?w:_);if(!s)return d;var l=s[1],c=s[3]||\"1\",u=Number(s[5]||1),f=Number(s[7]||0),h=Number(s[9]||0),b=Number(s[11]||0);if(i){if(2===l.length)return d;l=Number(l);var T;try{var S=x.getComponentMethod(\"calendars\",\"getCal\")(e);if(o){var E=\"i\"===c.charAt(c.length-1);c=parseInt(c,10),T=S.newDate(l,S.toMonthIndex(l,c,E),u)}else T=S.newDate(l,Number(c),u)}catch(t){return d}return T?(T.toJD()-y)*p+f*m+h*g+b*v:d}l=2===l.length?(Number(l)+2e3-M)%100+M:Number(l),c-=1;var L=new Date(Date.UTC(2e3,c,u,f,h));return L.setUTCFullYear(l),L.getUTCMonth()!==c?d:L.getUTCDate()!==u?d:L.getTime()+b*v},k=r.MIN_MS=r.dateTime2ms(\"-9999\"),A=r.MAX_MS=r.dateTime2ms(\"9999-12-31 23:59:59.9999\"),r.isDateTime=function(t,e){return r.dateTime2ms(t,e)!==d};var T=90*p,S=3*m,E=5*g;r.ms2DateTime=function(t,e,r){if(\"number\"!=typeof t||!(t>=k&&t<=A))return d;e||(e=0);var i,o,s,l,c,u,h=Math.floor(10*f(t+.05,1)),_=Math.round(t-h/10);if(n(r)){var w=Math.floor(_/p)+y,M=Math.floor(f(t,p));try{i=x.getComponentMethod(\"calendars\",\"getCal\")(r).fromJD(w).formatDate(\"yyyy-mm-dd\")}catch(t){i=b(\"G%Y-%m-%d\")(new Date(_))}if(\"-\"===i.charAt(0))for(;i.length<11;)i=\"-0\"+i.substr(1);else for(;i.length<10;)i=\"0\"+i;o=e=k+p&&t<=A-p))return d;var e=Math.floor(10*f(t+.05,1)),r=new Date(Math.round(t-e/10));return a(l.time.format(\"%Y-%m-%d\")(r),r.getHours(),r.getMinutes(),r.getSeconds(),10*r.getUTCMilliseconds()+e)},r.cleanDate=function(t,e,i){if(r.isJSDate(t)||\"number\"==typeof t){if(n(i))return u.error(\"JS Dates and milliseconds are incompatible with world calendars\",t),e;if(!(t=r.ms2DateTimeLocal(+t))&&void 0!==e)return e}else if(!r.isDateTime(t,i))return u.error(\"unrecognized date\",t),e;return t};var L=/%\\d?f/g,C=[59,59.9,59.99,59.999,59.9999];r.formatDate=function(t,e,r,i,a){var l,c;if(a=n(a)&&a,e)return function(t,e,r,i){t=t.replace(L,function(t){var r=Math.min(+t.charAt(1)||6,6);return(e/1e3%1+2).toFixed(r).substr(2).replace(/0+$/,\"\")||\"0\"});var a=new Date(Math.floor(e+.05));if(n(i))try{t=x.getComponentMethod(\"calendars\",\"worldCalFmt\")(t,e,i)}catch(t){return\"Invalid\"}return r(t)(a)}(e,t,i,a);if(a)try{var u=Math.floor((t+.05)/p)+y,f=x.getComponentMethod(\"calendars\",\"getCal\")(a).fromJD(u);\"y\"===r?c=s(f):\"m\"===r?c=function(t){return t.formatDate(\"M yyyy\")}(f):\"d\"===r?(l=s(f),c=function(t){return t.formatDate(\"M d\")}(f)):(l=function(t){return t.formatDate(\"M d, yyyy\")}(f),c=o(t,r))}catch(t){return\"Invalid\"}else{var h=new Date(Math.floor(t+.05));\"y\"===r?c=i(\"%Y\")(h):\"m\"===r?c=i(\"%b %Y\")(h):\"d\"===r?(l=i(\"%Y\")(h),c=i(\"%b %-d\")(h)):(l=i(\"%b %-d, %Y\")(h),c=o(t,r))}return c+(l?\"\\n\"+l:\"\")};var z=3*p;r.incrementMonth=function(t,e,r){r=n(r)&&r;var i=f(t,p);if(t=Math.round(t-i),r)try{var a=Math.round(t/p)+y,o=x.getComponentMethod(\"calendars\",\"getCal\")(r),s=o.fromJD(a);return e%12?o.add(s,e,\"m\"):o.add(s,e/12,\"y\"),(s.toJD()-y)*p+i}catch(e){u.error(\"invalid ms \"+t+\" in calendar \"+r)}var l=new Date(t+z);return l.setUTCMonth(l.getUTCMonth()+e)+i-z},r.findExactDates=function(t,e){for(var r,i,a=0,o=0,s=0,l=0,u=n(e)&&x.getComponentMethod(\"calendars\",\"getCal\")(e),f=0;f0&&(r.push(i),i=[])}return i.length>0&&r.push(i),r},r.makeLine=function(t){return 1===t.length?{type:\"LineString\",coordinates:t[0]}:{type:\"MultiLineString\",coordinates:t}},r.makePolygon=function(t){if(1===t.length)return{type:\"Polygon\",coordinates:t};for(var e=new Array(t.length),r=0;r1||m<0||m>1?null:{x:t+l*m,y:e+f*m}}function i(t,e,r,n,i){var a=n*t+i*e;if(a<0)return n*n+i*i;if(a>r){var o=n-t,s=i-e;return o*o+s*s}var l=n*e-i*t;return l*l/r}var a=t(\"./mod\");r.segmentsIntersect=n,r.segmentDistance=function(t,e,r,a,o,s,l,c){if(n(t,e,r,a,o,s,l,c))return 0;var u=r-t,f=a-e,h=l-o,d=c-s,p=u*u+f*f,m=h*h+d*d,g=Math.min(i(u,f,p,o-t,s-e),i(u,f,p,l-t,c-e),i(h,d,m,t-o,e-s),i(h,d,m,r-o,a-s));return Math.sqrt(g)};var o,s,l;r.getTextLocation=function(t,e,r,n){if(t===s&&n===l||(o={},s=t,l=n),o[r])return o[r];var i=t.getPointAtLength(a(r-n/2,e)),c=t.getPointAtLength(a(r+n/2,e)),u=Math.atan((c.y-i.y)/(c.x-i.x)),f=t.getPointAtLength(a(r,e)),h={x:(4*f.x+i.x+c.x)/6,y:(4*f.y+i.y+c.y)/6,theta:u};return o[r]=h,h},r.clearLocationCache=function(){s=null},r.getVisibleSegment=function(t,e,r){function n(e){var r=t.getPointAtLength(e);0===e?i=r:e===f&&(a=r);var n=r.xs?r.x-s:0,u=r.yc?r.y-c:0;return Math.sqrt(n*n+u*u)}for(var i,a,o=e.left,s=e.right,l=e.top,c=e.bottom,u=0,f=t.getTotalLength(),h=f,d=n(u);d;){if((u+=d+r)>h)return;d=n(u)}for(d=n(h);d;){if(h-=d+r,u>h)return;d=n(h)}return{min:u,max:h,len:h-u,total:f,isClosed:0===u&&h===f&&Math.abs(i.x-a.x)<.1&&Math.abs(i.y-a.y)<.1}},r.findPointOnPath=function(t,e,r,n){for(var i,a,o,s=(n=n||{}).pathLength||t.getTotalLength(),l=n.tolerance||.001,c=n.iterationLimit||30,u=t.getPointAtLength(0)[r]>t.getPointAtLength(s)[r]?-1:1,f=0,h=0,d=s;f0?d=i:h=i,f++}return a}},{\"./mod\":750}],738:[function(t,e,r){\"use strict\";e.exports=function(t){var e;if(\"string\"==typeof t){if(null===(e=document.getElementById(t)))throw new Error(\"No DOM element with id '\"+t+\"' exists on the page.\");return e}if(null===t||void 0===t)throw new Error(\"DOM element provided is null or undefined\");return t}},{}],739:[function(t,e,r){\"use strict\";function n(t,e){var r=t;return r[3]*=e,r}function i(t){if(o(t))return u;var e=s(t);return e.length?e:u}function a(t){return o(t)?t:f}var o=t(\"fast-isnumeric\"),s=t(\"color-normalize\"),l=t(\"../components/colorscale\"),c=t(\"../components/color/attributes\").defaultLine,u=s(c),f=1;e.exports=function(t,e,r){var o,c,h,d,p,m=t.color,g=Array.isArray(m),v=Array.isArray(e),y=[];if(o=void 0!==t.colorscale?l.makeColorScaleFunc(l.extractScale(t.colorscale,t.cmin,t.cmax)):i,c=g?function(t,e){return void 0===t[e]?u:s(o(t[e]))}:i,h=v?function(t,e){return void 0===t[e]?f:a(t[e])}:a,g||v)for(var x=0;x=0;){var n=t.indexOf(\";\",r);if(n/g,\"\")}(function(t){for(var e=0;(e=t.indexOf(\"\",e))>=0;){var r=t.indexOf(\"\",e);if(r/g,\"\\n\")}(t))))}},{\"../constants/string_mappings\":722,\"superscript-text\":539}],742:[function(t,e,r){\"use strict\";e.exports=function(t){return t}},{}],743:[function(t,e,r){\"use strict\";var n=t(\"d3\"),i=t(\"fast-isnumeric\"),a=t(\"../constants/numerical\"),o=a.FP_SAFE,s=a.BADNUM,l=e.exports={};l.nestedProperty=t(\"./nested_property\"),l.keyedContainer=t(\"./keyed_container\"),l.relativeAttr=t(\"./relative_attr\"),l.isPlainObject=t(\"./is_plain_object\"),l.isArray=t(\"./is_array\"),l.mod=t(\"./mod\"),l.toLogRange=t(\"./to_log_range\"),l.relinkPrivateKeys=t(\"./relink_private\"),l.ensureArray=t(\"./ensure_array\");var c=t(\"./coerce\");l.valObjectMeta=c.valObjectMeta,l.coerce=c.coerce,l.coerce2=c.coerce2,l.coerceFont=c.coerceFont,l.coerceHoverinfo=c.coerceHoverinfo,l.coerceSelectionMarkerOpacity=c.coerceSelectionMarkerOpacity,l.validate=c.validate;var u=t(\"./dates\");l.dateTime2ms=u.dateTime2ms,l.isDateTime=u.isDateTime,l.ms2DateTime=u.ms2DateTime,l.ms2DateTimeLocal=u.ms2DateTimeLocal,l.cleanDate=u.cleanDate,l.isJSDate=u.isJSDate,l.formatDate=u.formatDate,l.incrementMonth=u.incrementMonth,l.dateTick0=u.dateTick0,l.dfltRange=u.dfltRange,l.findExactDates=u.findExactDates,l.MIN_MS=u.MIN_MS,l.MAX_MS=u.MAX_MS;var f=t(\"./search\");l.findBin=f.findBin,l.sorterAsc=f.sorterAsc,l.sorterDes=f.sorterDes,l.distinctVals=f.distinctVals,l.roundUp=f.roundUp;var h=t(\"./stats\");l.aggNums=h.aggNums,l.len=h.len,l.mean=h.mean,l.variance=h.variance,l.stdev=h.stdev,l.interp=h.interp;var d=t(\"./matrix\");l.init2dArray=d.init2dArray,l.transposeRagged=d.transposeRagged,l.dot=d.dot,l.translationMatrix=d.translationMatrix,l.rotationMatrix=d.rotationMatrix,l.rotationXYMatrix=d.rotationXYMatrix,l.apply2DTransform=d.apply2DTransform,l.apply2DTransform2=d.apply2DTransform2;var p=t(\"./angles\");l.deg2rad=p.deg2rad,l.rad2deg=p.rad2deg,l.wrap360=p.wrap360,l.wrap180=p.wrap180;var m=t(\"./geometry2d\");l.segmentsIntersect=m.segmentsIntersect,l.segmentDistance=m.segmentDistance,l.getTextLocation=m.getTextLocation,l.clearLocationCache=m.clearLocationCache,l.getVisibleSegment=m.getVisibleSegment,l.findPointOnPath=m.findPointOnPath;var g=t(\"./extend\");l.extendFlat=g.extendFlat,l.extendDeep=g.extendDeep,l.extendDeepAll=g.extendDeepAll,l.extendDeepNoArrays=g.extendDeepNoArrays;var v=t(\"./loggers\");l.log=v.log,l.warn=v.warn,l.error=v.error;var y=t(\"./regex\");l.counterRegex=y.counter;var x=t(\"./throttle\");l.throttle=x.throttle,l.throttleDone=x.done,l.clearThrottle=x.clear,l.getGraphDiv=t(\"./get_graph_div\"),l._=t(\"./localize\"),l.notifier=t(\"./notifier\"),l.filterUnique=t(\"./filter_unique\"),l.filterVisible=t(\"./filter_visible\"),l.pushUnique=t(\"./push_unique\"),l.cleanNumber=t(\"./clean_number\"),l.ensureNumber=function(t){return i(t)?(t=Number(t))<-o||t>o?s:i(t)?Number(t):s:s},l.noop=t(\"./noop\"),l.identity=t(\"./identity\"),l.swapAttrs=function(t,e,r,n){r||(r=\"x\"),n||(n=\"y\");for(var i=0;ir?Math.max(r,Math.min(e,t)):Math.max(e,Math.min(r,t))},l.bBoxIntersect=function(t,e,r){return r=r||0,t.left<=e.right+r&&e.left<=t.right+r&&t.top<=e.bottom+r&&e.top<=t.bottom+r},l.simpleMap=function(t,e,r,n){for(var i=t.length,a=new Array(i),o=0;o-1||c!==1/0&&c>=Math.pow(2,r)?t(e,r,n):s},l.OptionControl=function(t,e){t||(t={}),e||(e=\"opt\");var r={};return r.optionList=[],r._newoption=function(n){n[e]=t,r[n.name]=n,r.optionList.push(n)},r[\"_\"+e]=t,r},l.smooth=function(t,e){if((e=Math.round(e)||0)<2)return t;var r,n,i,a,o=t.length,s=2*o,l=2*e-1,c=new Array(l),u=new Array(o);for(r=0;r=s&&(i-=s*Math.floor(i/s)),i<0?i=-1-i:i>=o&&(i=s-1-i),a+=t[i]*c[n];u[r]=a}return u},l.syncOrAsync=function(t,e,r){function n(){return l.syncOrAsync(t,e,r)}for(var i,a;t.length;)if(a=t.splice(0,1)[0],(i=a(e))&&i.then)return i.then(n).then(void 0,l.promiseError);return r&&r(e)},l.stripTrailingSlash=function(t){return\"/\"===t.substr(-1)?t.substr(0,t.length-1):t},l.noneOrAll=function(t,e,r){if(t){var n,i,a=!1,o=!0;for(n=0;n=0&&t%1==0}function a(e){return void 0!==e&&e1?i+o[1]:\"\";if(a&&(o.length>1||s.length>4||r))for(;n.test(s);)s=s.replace(n,\"$1\"+a+\"$2\");return s+l};var w=/%{([^\\s%{}]*)}/g,M=/^\\w*$/;l.templateString=function(t,e){var r={};return t.replace(w,function(t,n){return M.test(n)?e[n]||\"\":(r[n]=r[n]||l.nestedProperty(e,n).get,r[n]()||\"\")})};l.subplotSort=function(t,e){for(var r=Math.min(t.length,e.length)+1,n=0,i=0,a=0;a=48&&o<=57,c=s>=48&&s<=57;if(l&&(n=10*n+o-48),c&&(i=10*i+s-48),!l||!c){if(n!==i)return n-i;if(o!==s)return o-s}}return i-n},l.eventListenerOptionsSupported=function(){var t=!1;try{var e=Object.defineProperty({},\"passive\",{get:function(){t=!0}});window.addEventListener(\"test\",null,e),window.removeEventListener(\"test\",null,e)}catch(e){t=!1}return t}},{\"../constants/numerical\":721,\"./angles\":726,\"./clean_number\":727,\"./coerce\":728,\"./dates\":729,\"./ensure_array\":730,\"./extend\":732,\"./filter_unique\":733,\"./filter_visible\":734,\"./geometry2d\":737,\"./get_graph_div\":738,\"./identity\":742,\"./is_array\":744,\"./is_plain_object\":745,\"./keyed_container\":746,\"./localize\":747,\"./loggers\":748,\"./matrix\":749,\"./mod\":750,\"./nested_property\":751,\"./noop\":752,\"./notifier\":753,\"./push_unique\":756,\"./regex\":758,\"./relative_attr\":759,\"./relink_private\":760,\"./search\":761,\"./stats\":764,\"./throttle\":767,\"./to_log_range\":768,d3:128,\"fast-isnumeric\":140}],744:[function(t,e,r){\"use strict\";var n=\"undefined\"!=typeof ArrayBuffer&&ArrayBuffer.isView?ArrayBuffer:{isView:function(){return!1}};e.exports=function(t){return Array.isArray(t)||n.isView(t)}},{}],745:[function(t,e,r){\"use strict\";e.exports=function(t){return window&&window.process&&window.process.versions?\"[object Object]\"===Object.prototype.toString.call(t):\"[object Object]\"===Object.prototype.toString.call(t)&&Object.getPrototypeOf(t)===Object.prototype}},{}],746:[function(t,e,r){\"use strict\";var n=t(\"./nested_property\"),i=/^\\w*$/;e.exports=function(t,e,r,a){r=r||\"name\",a=a||\"value\";var o,s,l={};s=e&&e.length?n(t,e).get():t,e=e||\"\",s=s||[];var c={};for(o=0;o2)return l[e]=2|l[e],f.set(t,null);if(u){for(o=e;o1){for(var t=[\"LOG:\"],e=0;e0){for(var t=[\"WARN:\"],e=0;e0){for(var t=[\"ERROR:\"],e=0;e=0;e--){if(n=t[e][0],a=t[e][1],l=!1,c(n))for(r=n.length-1;r>=0;r--)i(n[r],o(a,r))?l?n[r]=void 0:n.pop():l=!0;else if(\"object\"==typeof n&&null!==n)for(s=Object.keys(n),l=!1,r=s.length-1;r>=0;r--)i(n[s[r]],o(a,s[r]))?delete n[s[r]]:l=!0;if(l)return}}(d)):f[e[u]]=n}}function o(t,e){var r=e;return l(e)?r=\"[\"+e+\"]\":t&&(r=\".\"+e),t+r}function s(t,e,r,n){if(void 0===t[e]){if(n)return!1;t[e]=\"number\"==typeof r?[]:{}}return!0}var l=t(\"fast-isnumeric\"),c=t(\"./is_array\"),u=t(\"./is_plain_object\"),f=t(\"../plot_api/container_array_match\");e.exports=function(t,e){if(l(e))e=String(e);else if(\"string\"!=typeof e||\"[-1]\"===e.substr(e.length-4))throw\"bad property string\";for(var r,i,o,s=0,c=e.split(\".\");s/g),s=0;so||a===i||al||e&&c(t))}:function(t,e){var a=t[0],c=t[1];if(a===i||ao||c===i||cl)return!1;var u,f,h,d,p,m=r.length,g=r[0][0],v=r[0][1],y=0;for(u=1;uMath.max(f,g)||c>Math.max(h,v)))if(cu||Math.abs(n(o,h))>i)return!0;return!1};a.filter=function(t,e){function r(r){t.push(r);var s=n.length,l=i;n.splice(a+1);for(var c=l+1;c1){r(t.pop())}return{addPt:r,raw:t,filtered:n}}},{\"../constants/numerical\":721,\"./matrix\":749}],756:[function(t,e,r){\"use strict\";e.exports=function(t,e){if(e instanceof RegExp){var r,n=e.toString();for(r=0;ri.queueLength&&(t.undoQueue.queue.shift(),t.undoQueue.index--))},a.startSequence=function(t){t.undoQueue=t.undoQueue||{index:0,queue:[],sequence:!1},t.undoQueue.sequence=!0,t.undoQueue.beginSequence=!0},a.stopSequence=function(t){t.undoQueue=t.undoQueue||{index:0,queue:[],sequence:!1},t.undoQueue.sequence=!1,t.undoQueue.beginSequence=!1},a.undo=function(t){var e,r;if(t.framework&&t.framework.isPolar)t.framework.undo();else if(!(void 0===t.undoQueue||isNaN(t.undoQueue.index)||t.undoQueue.index<=0)){for(t.undoQueue.index--,e=t.undoQueue.queue[t.undoQueue.index],t.undoQueue.inSequence=!0,r=0;r=t.undoQueue.queue.length)){for(e=t.undoQueue.queue[t.undoQueue.index],t.undoQueue.inSequence=!0,r=0;r1?(e[l-1]-e[0])/(l-1):1;for(o=u>=0?r?function(t,e){return t=e}:function(t,e){return t>e},t+=1e-9*u*(r?-1:1)*(u>=0?1:-1);s90&&i.log(\"Long binary search...\"),s-1},r.sorterAsc=function(t,e){return t-e},r.sorterDes=function(t,e){return e-t},r.distinctVals=function(t){var e=t.slice();e.sort(r.sorterAsc);for(var n=e.length-1,i=e[n]-e[0]||1,a=i/(n||1)/1e4,o=[e[0]],s=0;se[s]+a&&(i=Math.min(i,e[s+1]-e[s]),o.push(e[s+1]));return{vals:o,minDiff:i}},r.roundUp=function(t,e,r){for(var n,i=0,a=e.length-1,o=0,s=r?0:1,l=r?1:0,c=r?Math.ceil:Math.floor;it.length-1)return t[t.length-1];var r=e%1;return r*t[Math.ceil(e)]+(1-r)*t[Math.floor(e)]}},{\"fast-isnumeric\":140}],765:[function(t,e,r){\"use strict\";var n=t(\"color-normalize\");e.exports=function(t){return t?n(t):[0,0,0,1]}},{\"color-normalize\":99}],766:[function(t,e,r){\"use strict\";function n(t,e){return t.node().getBoundingClientRect()[e]}function i(t,e,r){var n=\"math-output-\"+c.randstr([],64),i=l.select(\"body\").append(\"div\").attr({id:n}).style({visibility:\"hidden\",position:\"absolute\"}).style({\"font-size\":e.fontSize+\"px\"}).text(function(t){return t.replace(p,\"\\\\lt \").replace(m,\"\\\\gt \")}(t));MathJax.Hub.Queue([\"Typeset\",MathJax.Hub,i.node()],function(){var e=l.select(\"body\").select(\"#MathJax_SVG_glyphs\");if(i.select(\".MathJax_SVG\").empty()||!i.select(\"svg\").node())c.log(\"There was an error in the tex syntax.\",t),r();else{var n=i.select(\"svg\").node().getBoundingClientRect();r(i.select(\".MathJax_SVG\"),e,n)}i.remove()})}function a(t,e){if(!t)return null;var r=t.match(e);return r&&(r[3]||r[4])}function o(t,e){function r(){p++;var e=document.createElementNS(u.svg,\"tspan\");l.select(e).attr({class:\"line\",dy:p*h+\"em\"}),t.appendChild(e),s=e;var r=d;if(d=[{node:e}],r.length>1)for(var i=1;i doesnt match end tag <\"+t+\">. Pretending it did match.\",e),s=d[d.length-1].node}else c.log(\"Ignoring unexpected end tag .\",e)}e=function(t){return function(t,e){if(!t)return\"\";for(var r=0;r|>|>)/g,g={sup:\"font-size:70%\",sub:\"font-size:70%\",b:\"font-weight:bold\",i:\"font-style:italic\",a:\"cursor:pointer\",span:\"\",em:\"font-style:italic;font-weight:bold\"},v={sub:\"0.3em\",sup:\"-0.6em\"},y={sub:\"-0.21em\",sup:\"0.42em\"},x=\"\\u200b\",b=[\"http:\",\"https:\",\"mailto:\",\"\",void 0,\":\"],_=new RegExp(\"]*)?/?>\",\"g\"),w=Object.keys(f.entityToUnicode).map(function(t){return{regExp:new RegExp(\"&\"+t+\";\",\"g\"),sub:f.entityToUnicode[t]}}),M=/(\\r\\n?|\\n)/g,k=/(<[^<>]*>)/,A=/<(\\/?)([^ >]*)(\\s+(.*))?>/i,T=//i,S=/(^|[\\s\"'])style\\s*=\\s*(\"([^\"]*);?\"|'([^']*);?')/i,E=/(^|[\\s\"'])href\\s*=\\s*(\"([^\"]*)\"|'([^']*)')/i,L=/(^|[\\s\"'])target\\s*=\\s*(\"([^\"\\s]*)\"|'([^'\\s]*)')/i,C=/(^|[\\s\"'])popup\\s*=\\s*(\"([\\w=,]*)\"|'([\\w=,]*)')/i,z=/(^|;)\\s*color:/;r.plainText=function(t){return(t||\"\").replace(_,\" \")},r.lineCount=function(t){return t.selectAll(\"tspan.line\").size()||1},r.positionText=function(t,e,r){return t.each(function(){function t(t,e){return void 0===e?null===(e=n.attr(t))&&(n.attr(t,0),e=0):n.attr(t,e),e}var n=l.select(this),i=t(\"x\",e),a=t(\"y\",r);\"text\"===this.nodeName&&n.selectAll(\"tspan.line\").attr({x:i,y:a})})},r.makeEditable=function(t,e){function r(){!function(){var r=l.select(i).select(\".svg-container\"),a=r.append(\"div\"),c=t.node().style,u=parseFloat(c.fontSize||12);a.classed(\"plugin-editable editable\",!0).style({position:\"absolute\",\"font-family\":c.fontFamily||\"Arial\",\"font-size\":u,color:e.fill||c.fill||\"black\",opacity:1,\"background-color\":e.background||\"transparent\",outline:\"#ffffff33 1px solid\",margin:[-u/8+1,0,0,-1].join(\"px \")+\"px\",padding:\"0\",\"box-sizing\":\"border-box\"}).attr({contenteditable:!0}).text(e.text||t.attr(\"data-unformatted\")).call(s(t,r,e)).on(\"blur\",function(){i._editing=!1,t.text(this.textContent).style({opacity:1});var e,r=l.select(this).attr(\"class\");(e=r?\".\"+r.split(\" \")[0]+\"-math-group\":\"[class*=-math-group]\")&&l.select(t.node().parentNode).select(e).style({opacity:0});var n=this.textContent;l.select(this).transition().duration(0).remove(),l.select(document).on(\"mouseup\",null),o.edit.call(t,n)}).on(\"focus\",function(){var t=this;i._editing=!0,l.select(document).on(\"mouseup\",function(){if(l.event.target===t)return!1;document.activeElement===a.node()&&a.node().blur()})}).on(\"keyup\",function(){27===l.event.which?(i._editing=!1,t.style({opacity:1}),l.select(this).style({opacity:0}).on(\"blur\",function(){return!1}).transition().remove(),o.cancel.call(t,this.textContent)):(o.input.call(t,this.textContent),l.select(this).call(s(t,r,e)))}).on(\"keydown\",function(){13===l.event.which&&this.blur()}).call(n)}(),t.style({opacity:0});var r,a=c.attr(\"class\");(r=a?\".\"+a.split(\" \")[0]+\"-math-group\":\"[class*=-math-group]\")&&l.select(t.node().parentNode).select(r).style({opacity:0})}function n(t){var e=t.node(),r=document.createRange();r.selectNodeContents(e);var n=window.getSelection();n.removeAllRanges(),n.addRange(r),e.focus()}var i=e.gd,a=e.delegate,o=l.dispatch(\"edit\",\"input\",\"cancel\"),c=a||t;if(t.style({\"pointer-events\":a?\"none\":\"all\"}),1!==t.size())throw new Error(\"boo\");return e.immediate?r():c.on(\"click\",r),l.rebind(t,o,\"on\")}},{\"../constants/alignment\":716,\"../constants/string_mappings\":722,\"../constants/xmlns_namespaces\":723,\"../lib\":743,d3:128}],767:[function(t,e,r){\"use strict\";function n(t){t&&null!==t.timer&&(clearTimeout(t.timer),t.timer=null)}var i={};r.throttle=function(t,e,r){function a(){r(),o.ts=Date.now(),o.onDone&&(o.onDone(),o.onDone=null)}var o=i[t],s=Date.now();if(!o){for(var l in i)i[l].tso.ts+e?a():o.timer=setTimeout(function(){a(),o.timer=null},e)},r.done=function(t){var e=i[t];return e&&e.timer?new Promise(function(t){var r=e.onDone;e.onDone=function(){r&&r(),t(),e.onDone=null}}):Promise.resolve()},r.clear=function(t){if(t)n(i[t]),delete i[t];else for(var e in i)r.clear(e)}},{}],768:[function(t,e,r){\"use strict\";var n=t(\"fast-isnumeric\");e.exports=function(t,e){if(t>0)return Math.log(t)/Math.LN10;var r=Math.log(Math.min(e[0],e[1]))/Math.LN10;return n(r)||(r=Math.log(Math.max(e[0],e[1]))/Math.LN10-6),r}},{\"fast-isnumeric\":140}],769:[function(t,e,r){\"use strict\";var n=e.exports={},i=t(\"../plots/geo/constants\").locationmodeToLayer,a=t(\"topojson-client\").feature;n.getTopojsonName=function(t){return[t.scope.replace(/ /g,\"-\"),\"_\",t.resolution.toString(),\"m\"].join(\"\")},n.getTopojsonPath=function(t,e){return t+e+\".json\"},n.getTopojsonFeatures=function(t,e){var r=i[t.locationmode],n=e.objects[r];return a(e,n).features}},{\"../plots/geo/constants\":818,\"topojson-client\":549}],770:[function(t,e,r){\"use strict\";e.exports={moduleType:\"locale\",name:\"en-US\",dictionary:{\"Click to enter Colorscale title\":\"Click to enter Colorscale title\"},format:{date:\"%m/%d/%Y\"}}},{}],771:[function(t,e,r){\"use strict\";e.exports={moduleType:\"locale\",name:\"en\",dictionary:{\"Click to enter Colorscale title\":\"Click to enter Colourscale title\"},format:{days:[\"Sunday\",\"Monday\",\"Tuesday\",\"Wednesday\",\"Thursday\",\"Friday\"],shortDays:[\"Sun\",\"Mon\",\"Tue\",\"Wed\",\"Thu\",\"Fri\",\"Sat\"],months:[\"January\",\"February\",\"March\",\"April\",\"May\",\"June\",\"July\",\"August\",\"September\",\"October\",\"November\",\"December\"],shortMonths:[\"Jan\",\"Feb\",\"Mar\",\"Apr\",\"May\",\"Jun\",\"Jul\",\"Aug\",\"Sep\",\"Oct\",\"Nov\",\"Dec\"],periods:[\"AM\",\"PM\"],dateTime:\"%a %b %e %X %Y\",date:\"%d/%m/%Y\",time:\"%H:%M:%S\",decimal:\".\",thousands:\",\",grouping:[3],currency:[\"$\",\"\"]}}},{}],772:[function(t,e,r){\"use strict\";var n=t(\"../registry\");e.exports=function(t){for(var e,r,i=n.layoutArrayContainers,a=n.layoutArrayRegexes,o=t.split(\"[\")[0],s=0;s0)return t.substr(0,e)}var s=t(\"fast-isnumeric\"),l=t(\"gl-mat4/fromQuat\"),c=t(\"../registry\"),u=t(\"../lib\"),f=t(\"../plots/plots\"),h=t(\"../plots/cartesian/axis_ids\"),d=h.cleanId,p=h.getFromTrace,m=t(\"../components/color\");r.clearPromiseQueue=function(t){Array.isArray(t._promises)&&t._promises.length>0&&u.log(\"Clearing previous rejected promises from queue.\"),t._promises=[]},r.cleanLayout=function(t){var e,r;t||(t={}),t.xaxis1&&(t.xaxis||(t.xaxis=t.xaxis1),delete t.xaxis1),t.yaxis1&&(t.yaxis||(t.yaxis=t.yaxis1),delete t.yaxis1),t.scene1&&(t.scene||(t.scene=t.scene1),delete t.scene1);var i=(f.subplotsRegistry.cartesian||{}).attrRegex,o=(f.subplotsRegistry.gl3d||{}).attrRegex,s=Object.keys(t);for(e=0;e3?(T.x=1.02,T.xanchor=\"left\"):T.x<-2&&(T.x=-.02,T.xanchor=\"right\"),T.y>3?(T.y=1.02,T.yanchor=\"bottom\"):T.y<-2&&(T.y=-.02,T.yanchor=\"top\")),\"rotate\"===t.dragmode&&(t.dragmode=\"orbit\"),m.clean(t),t},r.cleanData=function(t,e){for(var n=[],o=t.concat(Array.isArray(e)?e:[]).filter(function(t){return\"uid\"in t}).map(function(t){return t.uid}),s=0;s1&&o.warn(\"Full array edits are incompatible with other edits\",f);var y=r[\"\"][\"\"];if(u(y))e.set(null);else{if(!Array.isArray(y))return o.warn(\"Unrecognized full array edit value\",f,y),!0;e.set(y)}return!m&&(h(g,v),d(t),!0)}var x,b,_,w,M,k,A,T=Object.keys(r).map(Number).sort(s),S=e.get(),E=S||[],L=n(v,f).get(),C=[],z=-1,D=E.length;for(x=0;xE.length-(A?0:1))o.warn(\"index out of range\",f,_);else if(void 0!==k)M.length>1&&o.warn(\"Insertion & removal are incompatible with edits to the same index.\",f,_),u(k)?C.push(_):A?(\"add\"===k&&(k={}),E.splice(_,0,k),L&&L.splice(_,0,{})):o.warn(\"Unrecognized full object edit value\",f,_,k),-1===z&&(z=_);else for(b=0;b=0;x--)E.splice(C[x],1),L&&L.splice(C[x],1);if(E.length?S||e.set(E):e.set(null),m)return!1;if(h(g,v),p!==a){var I;if(-1===z)I=T;else{for(D=Math.max(E.length,D),I=[],x=0;x=z);x++)I.push(_);for(x=z;x=t.data.length||i<-t.data.length)throw new Error(r+\" must be valid indices for gd.data.\");if(e.indexOf(i,n+1)>-1||i>=0&&e.indexOf(-t.data.length+i)>-1||i<0&&e.indexOf(t.data.length+i)>-1)throw new Error(\"each index in \"+r+\" must be unique.\")}}function s(t,e,r){if(!Array.isArray(t.data))throw new Error(\"gd.data must be an array.\");if(void 0===e)throw new Error(\"currentIndices is a required argument.\");if(Array.isArray(e)||(e=[e]),o(t,e,\"currentIndices\"),void 0===r||Array.isArray(r)||(r=[r]),void 0!==r&&o(t,r,\"newIndices\"),void 0!==r&&e.length!==r.length)throw new Error(\"current and new indices must be of equal length.\")}function l(t,e,r,n,i,s){!function(t,e,r,n){var i=v.isPlainObject(n);if(!Array.isArray(t.data))throw new Error(\"gd.data must be an array\");if(!v.isPlainObject(e))throw new Error(\"update must be a key:value object\");if(void 0===r)throw new Error(\"indices must be an integer or array of integers\");o(t,r,\"indices\");for(var a in e){if(!Array.isArray(e[a])||e[a].length!==r.length)throw new Error(\"attribute \"+a+\" must be an array of length equal to indices array length\");if(i&&(!(a in n)||!Array.isArray(n[a])||n[a].length!==e[a].length))throw new Error(\"when maxPoints is set as a key:value object it must contain a 1:1 corrispondence with the keys and number of traces in the update object\")}}(t,e,r,n);for(var l,c,u,f=function(t,e,r,n){var i,o,s,l,c,u=v.isPlainObject(n),f=[];Array.isArray(r)||(r=[r]),r=a(r,t.data.length-1);for(var h in e)for(var d=0;d=0&&uY.range[0]?[1,2]:[2,1]);else{var Z=Y.range[0],J=Y.range[1];W?(Z<=0&&J<=0&&r(j+\".autorange\",!0),Z<=0?Z=J/1e6:J<=0&&(J=Z/1e6),r(j+\".range[0]\",Math.log(Z)/Math.LN10),r(j+\".range[1]\",Math.log(J)/Math.LN10)):(r(j+\".range[0]\",Math.pow(10,Z)),r(j+\".range[1]\",Math.pow(10,J)))}else r(j+\".autorange\",!0);Array.isArray(u._subplots.polar)&&u._subplots.polar.length&&u[E.parts[0]]&&\"radialaxis\"===E.parts[1]&&delete u[E.parts[0]]._subplot.viewInitial[\"radialaxis.range\"],b.getComponentMethod(\"annotations\",\"convertCoords\")(t,U,L,r),b.getComponentMethod(\"images\",\"convertCoords\")(t,U,L,r)}else r(j+\".autorange\",!0),r(j+\".range\",null);v.nestedProperty(u,j+\"._inputRange\").set(null)}else if(F.match(P.AX_NAME_PATTERN)){var K=v.nestedProperty(u,S).get(),Q=(L||{}).type;Q&&\"-\"!==Q||(Q=\"linear\"),b.getComponentMethod(\"annotations\",\"convertCoords\")(t,K,Q,r),b.getComponentMethod(\"images\",\"convertCoords\")(t,K,Q,r)}var $=C.containerArrayMatch(S);if($){a=$.array,o=$.index;var tt=$.property,et=(v.nestedProperty(l,a)||[])[o]||{},rt=et,nt=q||{editType:\"calc\"},it=-1!==nt.editType.indexOf(\"calcIfAutorange\");\"\"===o?(it?M.calc=!0:I.update(M,nt),it=!1):\"\"===tt&&(rt=L,C.isAddVal(L)?A[S]=null:C.isRemoveVal(L)?(A[S]=et,rt=et):v.warn(\"unrecognized full object value\",e)),it&&(n(rt,\"x\")||n(rt,\"y\"))?M.calc=!0:I.update(M,nt),d[a]||(d[a]={});var at=d[a][o];at||(at=d[a][o]={}),at[tt]=L,delete e[S]}else\"reverse\"===F?(B.range?B.range.reverse():(r(j+\".autorange\",!0),B.range=[1,0]),U.autorange?M.calc=!0:M.plot=!0):((!u._has(\"gl2d\")&&!u._has(\"regl\")||\"dragmode\"!==S||\"lasso\"!==L&&\"select\"!==L||\"lasso\"===V||\"select\"===V)&&q?I.update(M,q):M.calc=!0,E.set(L))}}for(a in d){C.applyContainerArrayChanges(t,v.nestedProperty(l,a),d[a],M)||(M.plot=!0)}var ot=u._axisConstraintGroups||[];for(x in T)for(o=0;o=s.length?s[0]:s[t]:s}function i(t){return Array.isArray(l)?t>=l.length?l[0]:l[t]:l}function a(t,e){var r=0;return function(){if(t&&++r===e)return t()}}if(t=v.getGraphDiv(t),!v.isPlotDiv(t))throw new Error(\"This element is not a Plotly plot: \"+t+\". It's likely that you've failed to create a plot before animating it. For more details, see https://plot.ly/javascript/animations/\");var o=t._transitionData;o._frameQueue||(o._frameQueue=[]);var s=(r=w.supplyAnimationDefaults(r)).transition,l=r.frame;return void 0===o._frameWaitingCnt&&(o._frameWaitingCnt=0),new Promise(function(l,c){function u(e){if(0!==e.length){for(var s=0;so._timeToNext&&function(){o._currentFrame&&o._currentFrame.onComplete&&o._currentFrame.onComplete();var e=o._currentFrame=o._frameQueue.shift();if(e){var r=e.name?e.name.toString():null;t._fullLayout._currentFrame=r,o._lastFrameAt=Date.now(),o._timeToNext=e.frameOpts.duration,w.transition(t,e.frame.data,e.frame.layout,z.coerceTraceIndices(t,e.frame.traces),e.frameOpts,e.transitionOpts).then(function(){e.onComplete&&e.onComplete()}),t.emit(\"plotly_animatingframe\",{name:r,frame:e.frame,animation:{frame:e.frameOpts,transition:e.transitionOpts}})}else t.emit(\"plotly_animated\"),window.cancelAnimationFrame(o._animationRaf),o._animationRaf=null}()};e()}()}}function f(t){return Array.isArray(s)?p>=s.length?t.transitionOpts=s[p]:t.transitionOpts=s[0]:t.transitionOpts=s,p++,t}var h,d,p=0,m=[],g=void 0===e||null===e,y=Array.isArray(e);if(!g&&!y&&v.isPlainObject(e))m.push({type:\"object\",data:f(v.extendFlat({},e))});else if(g||-1!==[\"string\",\"number\"].indexOf(typeof e))for(h=0;h0&&__)&&M.push(d);m=M}}m.length>0?u(m):(t.emit(\"plotly_animated\"),l())})},g.addFrames=function(t,e,r){t=v.getGraphDiv(t);var n=0;if(null===e||void 0===e)return Promise.resolve();if(!v.isPlotDiv(t))throw new Error(\"This element is not a Plotly plot: \"+t+\". It's likely that you've failed to create a plot before adding frames. For more details, see https://plot.ly/javascript/animations/\");var i,a,o,s,l=t._transitionData._frames,c=t._transitionData._frameHash;if(!Array.isArray(e))throw new Error(\"addFrames failure: frameList must be an Array of frame definitions\"+e);var u=l.length+2*e.length,f=[];for(i=e.length-1;i>=0;i--)if(v.isPlainObject(e[i])){var h=(c[e[i].name]||{}).name,d=e[i].name;h&&d&&\"number\"==typeof d&&c[h]&&(n++,v.warn('addFrames: overwriting frame \"'+c[h].name+'\" with a frame whose name of type \"number\" also equates to \"'+h+'\". This is valid but may potentially lead to unexpected behavior since all plotly.js frame names are stored internally as strings.'),n>5&&v.warn(\"addFrames: This API call has yielded too many warnings. For the rest of this call, further warnings about numeric frame names will be suppressed.\")),f.push({frame:w.supplyFrameDefaults(e[i]),index:r&&void 0!==r[i]&&null!==r[i]?r[i]:u+i})}f.sort(function(t,e){return t.index>e.index?-1:t.index=0;i--){if(\"number\"==typeof(a=f[i].frame).name&&v.warn(\"Warning: addFrames accepts frames with numeric names, but the numbers areimplicitly cast to strings\"),!a.name)for(;c[a.name=\"frame \"+t._transitionData._counter++];);if(c[a.name]){for(o=0;o=0;r--)n=e[r],a.push({type:\"delete\",index:n}),o.unshift({type:\"insert\",index:n,value:i[n]});var s=w.modifyFrames,l=w.modifyFrames,c=[t,o],u=[t,a];return x&&x.add(t,s,c,l,u),w.modifyFrames(t,a)},g.purge=function(t){var e=(t=v.getGraphDiv(t))._fullLayout||{},r=t._fullData||[];return w.cleanPlot([],{},r,e),w.purge(t),y.purge(t),e._container&&e._container.remove(),delete t._context,t}},{\"../components/color\":618,\"../components/drawing\":643,\"../components/errorbars\":649,\"../constants/xmlns_namespaces\":723,\"../lib\":743,\"../lib/events\":731,\"../lib/queue\":757,\"../lib/svg_text_utils\":766,\"../plotly\":784,\"../plots/cartesian/axis_ids\":792,\"../plots/cartesian/constants\":794,\"../plots/cartesian/constraints\":796,\"../plots/cartesian/graph_interact\":798,\"../plots/plots\":852,\"../plots/polar/legacy\":860,\"../registry\":873,\"./edit_types\":773,\"./helpers\":774,\"./manage_arrays\":775,\"./plot_schema\":778,\"./subroutines\":781,d3:128,\"fast-isnumeric\":140,\"has-hover\":276}],777:[function(t,e,r){\"use strict\";e.exports={staticPlot:!1,editable:!1,edits:{annotationPosition:!1,annotationTail:!1,annotationText:!1,axisTitleText:!1,colorbarPosition:!1,colorbarTitleText:!1,legendPosition:!1,legendText:!1,shapePosition:!1,titleText:!1},autosizable:!1,queueLength:0,fillFrame:!1,frameMargins:0,scrollZoom:!1,doubleClick:\"reset+autosize\",showTips:!0,showAxisDragHandles:!0,showAxisRangeEntryBoxes:!0,showLink:!1,sendData:!0,linkText:\"Edit chart\",showSources:!1,displayModeBar:\"hover\",modeBarButtonsToRemove:[],modeBarButtonsToAdd:[],modeBarButtons:!1,displaylogo:!0,plotGlPixelRatio:2,setBackground:\"transparent\",topojsonURL:\"https://cdn.plot.ly/\",mapboxAccessToken:null,logging:1,globalTransforms:[],locale:\"en-US\",locales:{}}},{}],778:[function(t,e,r){\"use strict\";function n(t,e,r){if(!t)return!1;if(t._isLinkedToArray)if(i(e[r]))r++;else if(r=t.items.length)return!1;t=t.items[a]}}return t}function i(t){return t===Math.round(t)&&t>=0}function a(){var t,e,r={};x(r,h);for(t in c.subplotsRegistry)if((e=c.subplotsRegistry[t]).layoutAttributes)if(\"cartesian\"===e.name)s(r,e,\"xaxis\"),s(r,e,\"yaxis\");else{s(r,e,\"subplot\"===e.attr?e.name:e.attr)}r=function(t){return y(t,{radialaxis:g.radialaxis,angularaxis:g.angularaxis}),y(t,g.layout),t}(r);for(t in c.componentsRegistry){var n=(e=c.componentsRegistry[t]).schema;if(n&&(n.subplots||n.layout)){var i=n.subplots;if(i&&i.xaxis&&!i.yaxis)for(var a in i.xaxis)delete r.yaxis[a]}else e.layoutAttributes&&l(r,e.layoutAttributes,e.name)}return{layoutAttributes:o(r)}}function o(t){return function(t){r.crawl(t,function(t,e,n){r.isValObject(t)?\"data_array\"===t.valType?(t.role=\"data\",n[e+\"src\"]={valType:\"string\",editType:\"none\"}):!0===t.arrayOk&&(n[e+\"src\"]={valType:\"string\",editType:\"none\"}):u.isPlainObject(t)&&(t.role=\"object\")})}(t),function(t){r.crawl(t,function(t,e,r){if(!t)return;var n=t[_];if(!n)return;delete t[_],r[e]={items:{}},r[e].items[n]=t,r[e].role=\"object\"})}(t),t}function s(t,e,r){var n=u.nestedProperty(t,r),i=x({},e.layoutAttributes);i[b]=!0,n.set(i)}function l(t,e,r){var n=u.nestedProperty(t,r);n.set(x(n.get()||{},e))}var c=t(\"../registry\"),u=t(\"../lib\"),f=t(\"../plots/attributes\"),h=t(\"../plots/layout_attributes\"),d=t(\"../plots/frame_attributes\"),p=t(\"../plots/animation_attributes\"),m=t(\"../plots/polar/legacy/area_attributes\"),g=t(\"../plots/polar/legacy/axis_attributes\"),v=t(\"./edit_types\"),y=u.extendFlat,x=u.extendDeepAll,b=\"_isSubplotObj\",_=\"_isLinkedToArray\",w=[b,_,\"_arrayAttrRegexps\",\"_deprecated\"];r.IS_SUBPLOT_OBJ=b,r.IS_LINKED_TO_ARRAY=_,r.DEPRECATED=\"_deprecated\",r.UNDERSCORE_ATTRS=w,r.get=function(){var t={};c.allTypes.concat(\"area\").forEach(function(e){t[e]=function(t){var e,r;\"area\"===t?(e={attributes:m},r={}):r=(e=c.modules[t]._module).basePlotModule;var n={};n.type=null,x(n,f),x(n,e.attributes),r.attributes&&x(n,r.attributes),n.type=t;var i={meta:e.meta||{},attributes:o(n)};if(e.layoutAttributes){var a={};x(a,e.layoutAttributes),i.layoutAttributes=o(a)}return i}(e)});var e={};return Object.keys(c.transformsRegistry).forEach(function(t){e[t]=function(t){var e=c.transformsRegistry[t],r=x({},e.attributes);return Object.keys(c.componentsRegistry).forEach(function(e){var n=c.componentsRegistry[e];n.schema&&n.schema.transforms&&n.schema.transforms[t]&&Object.keys(n.schema.transforms[t]).forEach(function(e){l(r,n.schema.transforms[t][e],e)})}),{attributes:o(r)}}(t)}),{defs:{valObjects:u.valObjectMeta,metaKeys:w.concat([\"description\",\"role\",\"editType\",\"impliedEdits\"]),editType:{traces:v.traces,layout:v.layout},impliedEdits:{}},traces:t,layout:a(),transforms:e,frames:function(){var t={frames:u.extendDeepAll({},d)};return o(t),t.frames}(),animation:o(p)}},r.crawl=function(t,e,n,i){var a=n||0;i=i||\"\",Object.keys(t).forEach(function(n){var o=t[n];if(-1===w.indexOf(n)){var s=(i?i+\".\":\"\")+n;e(o,n,t,a,s),r.isValObject(o)||u.isPlainObject(o)&&\"impliedEdits\"!==n&&r.crawl(o,e,a+1,s)}})},r.isValObject=function(t){return t&&void 0!==t.valType},r.findArrayAttributes=function(t){function e(e,r,a,o){i=i.slice(0,o).concat([r]);if(e&&(\"data_array\"===e.valType||!0===e.arrayOk)&&!(\"colorbar\"===i[o-1]&&(\"ticktext\"===r||\"tickvals\"===r))){var s=function(t){return t.join(\".\")}(i),l=u.nestedProperty(t,s).get();Array.isArray(l)&&n.push(s)}}var n=[],i=[];if(r.crawl(f,e),t._module&&t._module.attributes&&r.crawl(t._module.attributes,e),t.transforms)for(var a=t.transforms,o=0;o=t.transforms.length)return!1;a=(r=(c.transformsRegistry[t.transforms[l].type]||{}).attributes)&&r[e[2]],s=3}else if(\"area\"===t.type)a=m[o];else{var u=t._module;if(u||(u=(c.modules[t.type||f.type.dflt]||{})._module),!u)return!1;if(r=u.attributes,!(a=r&&r[o])){var h=u.basePlotModule;h&&h.attributes&&(a=h.attributes[o])}a||(a=f[o])}return n(a,e,s)},r.getLayoutValObject=function(t,e){return n(function(t,e){var r,n,i,a,o=t._basePlotModules;if(o){var s;for(r=0;r=t[1]||i[1]<=t[0])&&a[0]e[0])return!0}return!1}(r,n,w)?(_.push(t),w.push([r,n])):i=[0];var a=e.plotgroup.selectAll(\".bg\").data(i);a.enter().append(\"rect\").classed(\"bg\",!0),a.exit().remove(),a.each(function(){e.bg=a;var t=e.plotgroup.node();t.insertBefore(this,t.childNodes[0])})});var M=l._bgLayer.selectAll(\".bg\").data(_);return M.enter().append(\"rect\").classed(\"bg\",!0),M.exit().remove(),M.each(function(t){l._plots[t].bg=o.select(this)}),b.each(function(t){function r(t){return\"M\"+k+\",\"+t+\"H\"+A}function o(t){return\"M\"+y._offset+\",\"+t+\"h\"+y._length}function s(t){return\"M\"+t+\",\"+z+\"V\"+C}function c(t){return\"M\"+t+\",\"+x._offset+\"v\"+x._length}function p(e,r,n){if(!e.showline||t!==e._mainSubplot)return\"\";if(!e._anchorAxis)return n(e._mainLinePosition);var i=r(e._mainLinePosition);return e.mirror&&(i+=r(e._mainMirrorPosition)),i}var v=l._plots[t],y=v.xaxis,x=v.yaxis;v.bg&&m&&v.bg.call(h.setRect,y._offset-u,x._offset-u,y._length+2*u,x._length+2*u).call(f.fill,l.plot_bgcolor).style(\"stroke-width\",0),v.clipId=\"clip\"+l._uid+t+\"plot\";var b=l._clips.selectAll(\"#\"+v.clipId).data([0]);b.enter().append(\"clipPath\").attr({class:\"plotclip\",id:v.clipId}).append(\"rect\"),b.selectAll(\"rect\").attr({width:y._length,height:x._length}),h.setTranslate(v.plot,y._offset,x._offset);var _,w;for(v._hasClipOnAxisFalse?(_=null,w=v.clipId):(_=v.clipId,w=null),h.setClipUrl(v.plot,_),i=0;i1&&d.push(a(\"object\",\"layout\"))),l.supplyDefaults(p);for(var m=p._fullData,g=r.length,v=0;v10||\"01-01\"!==n.substr(5)?t._tickround=\"d\":t._tickround=+e.substr(1)%12==0?\"y\":\"m\";else if(e>=T&&i<=10||e>=15*T)t._tickround=\"d\";else if(e>=E&&i<=16||e>=S)t._tickround=\"M\";else if(e>=L&&i<=19||e>=E)t._tickround=\"S\";else{var a=t.l2r(r+e).replace(/^-/,\"\").length;t._tickround=Math.max(i,a)-20}}else if(m(e)||\"L\"===e.charAt(0)){var o=t.range.map(t.r2d||Number);m(e)||(e=Number(e.substr(1))),t._tickround=2-Math.floor(Math.log(e)/Math.LN10+.01);var s=Math.max(Math.abs(o[0]),Math.abs(o[1])),l=Math.floor(Math.log(s)/Math.LN10+.01);Math.abs(l)>3&&(c(t.exponentformat)&&!u(l)?t._tickexponent=3*Math.round((l-1)/3):t._tickexponent=l)}else t._tickround=null}function s(t,e,r){var n=t.tickfont||{};return{x:e,dx:0,dy:0,text:r||\"\",fontSize:n.size,font:n.family,fontColor:n.color}}function l(t,e,r,n,i){if(\"radians\"!==t.thetaunit||r)e.text=f(e.x,t,i,n);else{var a=e.x/180;if(0===a)e.text=\"0\";else{var o=function(t){function e(t,e){return Math.abs(t-e)<=1e-6}function r(t,n){return e(n,0)?t:r(n,t%n)}var n=function(t){var r=1;for(;!e(Math.round(t*r)/r,t);)r*=10;return r}(t),i=t*n,a=Math.abs(r(i,n));return[Math.round(i/a),Math.round(n/a)]}(a);if(o[1]>=100)e.text=f(v.deg2rad(e.x),t,i,n);else{var s=e.x<0;1===o[1]?1===o[0]?e.text=\"\\u03c0\":e.text=o[0]+\"\\u03c0\":e.text=[\"\",o[0],\"\",\"\\u2044\",\"\",o[1],\"\",\"\\u03c0\"].join(\"\"),s&&(e.text=C+e.text)}}}}function c(t){return\"SI\"===t||\"B\"===t}function u(t){return t>14||t<-15}function f(t,e,r,n){var i=t<0,a=e._tickround,s=r||e.exponentformat||\"B\",l=e._tickexponent,f=I.getTickFormat(e),h=e.separatethousands;if(n){var d={exponentformat:e.exponentformat,dtick:\"none\"===e.showexponent?e.dtick:m(t)?Math.abs(t)||1:1,range:\"none\"===e.showexponent?e.range.map(e.r2d):[0,t||1]};o(d),a=(Number(d._tickround)||0)+4,l=d._tickexponent,e.hoverformat&&(f=e.hoverformat)}if(f)return e._numFormat(f)(t).replace(/-/g,C);var p=Math.pow(10,-a)/2;if(\"none\"===s&&(l=0),(t=Math.abs(t))\"+x+\"
\":\"B\"===s&&9===l?t+=\"B\":c(s)&&(t+=H[l/3+5])}return i?C+t:t}function h(t,e){for(var r=0;r2e-6||((r-t._forceTick0)/t._minDtick%1+1.000001)%1>2e-6)&&(t._minDtick=0)):t._minDtick=0},I.getAutoRange=function(t){var e,r=[],n=t._min[0].val,i=t._max[0].val;for(e=1;e0&&u>0&&f/u>h&&(l=o,c=s,h=f/u);if(n===i){var m=n-1,g=n+1;r=\"tozero\"===t.rangemode?n<0?[m,0]:[0,g]:\"nonnegative\"===t.rangemode?[Math.max(0,m),Math.max(0,g)]:[m,g]}else h&&(\"linear\"!==t.type&&\"-\"!==t.type||(\"tozero\"===t.rangemode?(l.val>=0&&(l={val:0,pad:0}),c.val<=0&&(c={val:0,pad:0})):\"nonnegative\"===t.rangemode&&(l.val-h*l.pad<0&&(l={val:0,pad:0}),c.val<0&&(c={val:1,pad:0})),h=(c.val-l.val)/(t._length-l.pad-c.pad)),r=[l.val-h*l.pad,c.val+h*c.pad]);return r[0]===r[1]&&(\"tozero\"===t.rangemode?r=r[0]<0?[r[0],0]:r[0]>0?[0,r[0]]:[0,1]:(r=[r[0]-1,r[0]+1],\"nonnegative\"===t.rangemode&&(r[0]=Math.max(0,r[0])))),d&&r.reverse(),v.simpleMap(r,t.l2r||Number)},I.doAutoRange=function(t){t._length||t.setScale();var e=t._min&&t._max&&t._min.length&&t._max.length;if(t.autorange&&e){t.range=I.getAutoRange(t),t._r=t.range.slice(),t._rl=v.simpleMap(t._r,t.r2l);var r=t._input;r.range=t.range.slice(),r.autorange=t.autorange}},I.saveRangeInitial=function(t,e){for(var r=I.list(t,\"\",!0),n=!1,i=0;i=h?d=!1:s.val>=c&&s.pad<=h&&(t._min.splice(o,1),o--);d&&t._min.push({val:c,pad:b&&0===c?0:h})}if(n(u)){for(d=!0,o=0;o=u&&s.pad>=f?d=!1:s.val<=u&&s.pad<=f&&(t._max.splice(o,1),o--);d&&t._max.push({val:u,pad:b&&0===u?0:f})}}}if((t.autorange||!!v.nestedProperty(t,\"rangeslider.autorange\").get())&&e){t._min||(t._min=[]),t._max||(t._max=[]),r||(r={}),t._m||t.setScale();var a,o,s,l,c,u,f,h,d,p,g,y=e.length,x=r.padded?.05*t._length:0,b=r.tozero&&(\"linear\"===t.type||\"-\"===t.type);x&&\"domain\"===t.constrain&&t._inputDomain&&(x*=(t._inputDomain[1]-t._inputDomain[0])/(t.domain[1]-t.domain[0]));var _=n((t._m>0?r.ppadplus:r.ppadminus)||r.ppad||0),w=n((t._m>0?r.ppadminus:r.ppadplus)||r.ppad||0),k=n(r.vpadplus||r.vpad),A=n(r.vpadminus||r.vpad);for(a=0;a<6;a++)i(a);for(a=y-1;a>5;a--)i(a)}},I.autoBin=function(t,e,r,n,i){var a=v.aggNums(Math.min,null,t),o=v.aggNums(Math.max,null,t);if(i||(i=e.calendar),\"category\"===e.type)return{start:a-.5,end:o+.5,size:1,_count:o-a+1};var s;if(r)s=(o-a)/r;else{var l=v.distinctVals(t),c=Math.pow(10,Math.floor(Math.log(l.minDiff)/Math.LN10)),u=c*v.roundUp(l.minDiff/c,[.9,1.9,4.9,9.9],!0);s=Math.max(u,2*v.stdev(t)/Math.pow(t.length,n?.25:.4)),m(s)||(s=1)}var f;f=\"log\"===e.type?{type:\"linear\",range:[a,o]}:{type:e.type,range:v.simpleMap([a,o],e.c2r,0,i),calendar:i},I.setConvert(f),I.autoTicks(f,s);var h,d,p=I.tickIncrement(I.tickFirst(f),f.dtick,\"reverse\",i);if(\"number\"==typeof f.dtick)h=(p=function(t,e,r,n,i){function a(e){return(1+100*(e-t)/r.dtick)%100<2}for(var o=0,s=0,l=0,c=0,u=0;u.3*f||a(n)||a(i))){var h=r.dtick/2;t+=t+h.8){var o=Number(r.substr(1));a.exactYears>.8&&o%12==0?t=I.tickIncrement(t,\"M6\",\"reverse\")+1.5*T:a.exactMonths>.8?t=I.tickIncrement(t,\"M1\",\"reverse\")+15.5*T:t-=T/2;var s=I.tickIncrement(t,r);if(s<=n)return s}return t}(p,t,f.dtick,a,i)),h=p,d=0;h<=o;)h=I.tickIncrement(h,f.dtick,!1,i),d++;return{start:e.c2r(p,0,i),end:e.c2r(h,0,i),size:f.dtick,_count:d}},I.calcTicks=function(t){var e=v.simpleMap(t.range,t.r2l);if(\"auto\"===t.tickmode||!t.dtick){var r,n=t.nticks;n||(\"category\"===t.type?(r=t.tickfont?1.2*(t.tickfont.size||12):15,n=t._length/r):(r=\"y\"===t._id.charAt(0)?40:80,n=v.constrain(t._length/r,4,9)+1),\"radialaxis\"===t._name&&(n*=2)),\"array\"===t.tickmode&&(n*=100),I.autoTicks(t,Math.abs(e[1]-e[0])/n),t._minDtick>0&&t.dtick<2*t._minDtick&&(t.dtick=t._minDtick,t.tick0=t.l2r(t._forceTick0))}if(t.tick0||(t.tick0=\"date\"===t.type?\"2000-01-01\":0),o(t),\"array\"===t.tickmode)return function(t){var e,r,n=t.tickvals,i=t.ticktext,a=new Array(n.length),o=v.simpleMap(t.range,t.r2l),l=1.0001*o[0]-1e-4*o[1],c=1.0001*o[1]-1e-4*o[0],u=Math.min(l,c),f=Math.max(l,c),h=0;Array.isArray(i)||(i=[]);var d=\"category\"===t.type?t.d2l_noadd:t.d2l;for(\"log\"===t.type&&\"L\"!==String(t.dtick).charAt(0)&&(t.dtick=\"L\"+Math.pow(10,Math.floor(Math.min(t.range[0],t.range[1]))-1)),r=0;ru&&e=l:f<=l)&&!(a.length>u||f===c);f=I.tickIncrement(f,t.dtick,i,t.calendar))c=f,a.push(f);\"angular\"===t._id&&360===Math.abs(e[1]-e[0])&&a.pop(),t._tmax=a[a.length-1],t._prevDateHead=\"\",t._inCalcTicks=!0;for(var h=new Array(a.length),d=0;dk?(e/=k,n=r(10),t.dtick=\"M\"+12*a(e,n,R)):i>A?(e/=A,t.dtick=\"M\"+a(e,1,N)):i>T?(t.dtick=a(e,T,B),t.tick0=v.dateTick0(t.calendar,!0)):i>S?t.dtick=a(e,S,N):i>E?t.dtick=a(e,E,j):i>L?t.dtick=a(e,L,j):(n=r(10),t.dtick=a(e,n,R))}else if(\"log\"===t.type){t.tick0=0;var o=v.simpleMap(t.range,t.r2l);if(e>.7)t.dtick=Math.ceil(e);else if(Math.abs(o[1]-o[0])<1){var s=1.5*Math.abs((o[1]-o[0])/e);e=Math.abs(Math.pow(10,o[1])-Math.pow(10,o[0]))/s,n=r(10),t.dtick=\"L\"+a(e,n,R)}else t.dtick=e>.3?\"D2\":\"D1\"}else\"category\"===t.type?(t.tick0=0,t.dtick=Math.ceil(Math.max(e,1))):\"angular\"===t._id?(t.tick0=0,n=1,t.dtick=a(e,n,q)):(t.tick0=0,n=r(10),t.dtick=a(e,n,R));if(0===t.dtick&&(t.dtick=1),!m(t.dtick)&&\"string\"!=typeof t.dtick){var l=t.dtick;throw t.dtick=1,\"ax.dtick error: \"+String(l)}},I.tickIncrement=function(t,e,r,n){var i=r?-1:1;if(m(e))return t+i*e;var a=e.charAt(0),o=i*Number(e.substr(1));if(\"M\"===a)return v.incrementMonth(t,o,n);if(\"L\"===a)return Math.log(Math.pow(10,t)+o)/Math.LN10;if(\"D\"===a){var s=\"D2\"===e?V:U,l=t+.01*i,c=v.roundUp(v.mod(l,1),s,r);return Math.floor(l)+Math.log(p.round(Math.pow(10,c),1))/Math.LN10}throw\"unrecognized dtick \"+String(e)},I.tickFirst=function(t){var e=t.r2l||Number,r=v.simpleMap(t.range,e),n=r[1]\"+o,t._prevDateHead=o)),e.text=s}(t,o,r,d):\"log\"===t.type?function(t,e,r,n,i){var a=t.dtick,o=e.x,s=t.tickformat;if(\"never\"===i&&(i=\"\"),!n||\"string\"==typeof a&&\"L\"===a.charAt(0)||(a=\"L3\"),s||\"string\"==typeof a&&\"L\"===a.charAt(0))e.text=f(Math.pow(10,o),t,i,n);else if(m(a)||\"D\"===a.charAt(0)&&v.mod(o+.01,1)<.1){var l=Math.round(o);-1!==[\"e\",\"E\",\"power\"].indexOf(t.exponentformat)||c(t.exponentformat)&&u(l)?(e.text=0===l?1:1===l?\"10\":l>1?\"10\"+l+\"\":\"10\"+C+-l+\"\",e.fontSize*=1.25):(e.text=f(Math.pow(10,o),t,\"\",\"fakehover\"),\"D1\"===a&&\"y\"===t._id.charAt(0)&&(e.dy-=e.fontSize/6))}else{if(\"D\"!==a.charAt(0))throw\"unrecognized dtick \"+String(a);e.text=String(Math.round(Math.pow(10,v.mod(o,1)))),e.fontSize*=.75}if(\"D1\"===t.dtick){var h=String(e.text).charAt(0);\"0\"!==h&&\"1\"!==h||(\"y\"===t._id.charAt(0)?e.dx-=e.fontSize/4:(e.dy+=e.fontSize/2,e.dx+=(t.range[1]>t.range[0]?1:-1)*e.fontSize*(o<0?.5:.25)))}}(t,o,0,d,i):\"category\"===t.type?function(t,e){var r=t._categories[Math.round(e.x)];void 0===r&&(r=\"\"),e.text=String(r)}(t,o):\"angular\"===t._id?l(t,o,r,d,i):function(t,e,r,n,i){\"never\"===i?i=\"\":\"all\"===t.showexponent&&Math.abs(e.x/t.dtick)<1e-6&&(i=\"hide\"),e.text=f(e.x,t,i,n)}(t,o,0,d,i),t.tickprefix&&!n(t.showtickprefix)&&(o.text=t.tickprefix+o.text),t.ticksuffix&&!n(t.showticksuffix)&&(o.text+=t.ticksuffix),o},I.hoverLabelText=function(t,e,r){if(r!==z&&r!==e)return I.hoverLabelText(t,e)+\" - \"+I.hoverLabelText(t,r);var n=\"log\"===t.type&&e<=0,i=I.tickText(t,t.c2l(n?-e:e),\"hover\").text;return n?0===e?\"0\":C+i:i};var H=[\"f\",\"p\",\"n\",\"\\u03bc\",\"m\",\"\",\"k\",\"M\",\"G\",\"T\"];I.getTickFormat=function(t){function e(t){return\"string\"!=typeof t?t:Number(t.replace(\"M\",\"\"))*A}function r(t,e){var r=[\"L\",\"D\"];if(typeof t==typeof e){if(\"number\"==typeof t)return t-e;var n=r.indexOf(t.charAt(0)),i=r.indexOf(e.charAt(0));return n===i?Number(t.replace(/(L|D)/g,\"\"))-Number(e.replace(/(L|D)/g,\"\")):n-i}return\"number\"==typeof t?1:-1}function n(t,e,r){var n=r||function(t){return t},i=e[0],a=e[1];return(!i&&\"number\"!=typeof i||n(i)<=n(t))&&(!a&&\"number\"!=typeof a||n(a)>=n(t))}function i(t,e){var n=null===e[0],i=null===e[1],a=r(t,e[0])>=0,o=r(t,e[1])<=0;return(n||a)&&(i||o)}var a,o;if(t.tickformatstops&&t.tickformatstops.length>0)switch(t.type){case\"date\":case\"linear\":for(a=0;a1&&e1)for(n=1;n2*o}(t,e)?\"date\":function(t){for(var e,r=Math.max(1,(t.length-1)/1e3),n=0,o=0,s=0;s2*n}(t)?\"category\":function(t){if(!t)return!1;for(var e=0;en?1:-1:+(t.substr(1)||1)-+(e.substr(1)||1)}},{\"../../registry\":873,\"./constants\":794}],793:[function(t,e,r){\"use strict\";e.exports=function(t,e,r){if(\"category\"===e.type){var n,i=t.categoryarray,a=Array.isArray(i)&&i.length>0;a&&(n=\"array\");var o=r(\"categoryorder\",n);\"array\"===o&&r(\"categoryarray\"),a||\"array\"!==o||(e.categoryorder=\"trace\")}}},{}],794:[function(t,e,r){\"use strict\";var n=t(\"../../lib\").counterRegex;e.exports={idRegex:{x:n(\"x\"),y:n(\"y\")},attrRegex:n(\"[xy]axis\"),xAxisMatch:n(\"xaxis\"),yAxisMatch:n(\"yaxis\"),AX_ID_PATTERN:/^[xyz][0-9]*$/,AX_NAME_PATTERN:/^[xyz]axis[0-9]*$/,SUBPLOT_PATTERN:/^x([0-9]*)y([0-9]*)$/,MINDRAG:8,MINSELECT:12,MINZOOM:20,DRAGGERSIZE:20,BENDPX:1.5,REDRAWDELAY:50,SELECTDELAY:100,SELECTID:\"-select\",DFLTRANGEX:[-1,6],DFLTRANGEY:[-1,4],traceLayerClasses:[\"imagelayer\",\"maplayer\",\"barlayer\",\"carpetlayer\",\"violinlayer\",\"boxlayer\",\"scatterlayer\"],layerValue2layerClass:{\"above traces\":\"above\",\"below traces\":\"below\"}}},{\"../../lib\":743}],795:[function(t,e,r){\"use strict\";var n=t(\"../../lib\"),i=t(\"./axis_ids\").id2name;e.exports=function(t,e,r,a,o){var s=o._axisConstraintGroups,l=e._id,c=l.charAt(0);if(!e.fixedrange&&(r(\"constrain\"),n.coerce(t,e,{constraintoward:{valType:\"enumerated\",values:\"x\"===c?[\"left\",\"center\",\"right\"]:[\"bottom\",\"middle\",\"top\"],dflt:\"x\"===c?\"center\":\"middle\"}},\"constraintoward\"),t.scaleanchor)){var u=function(t,e,r,n){var a,o,s,l,c=n[i(e)].type,u=[];for(o=0;oo*v)||_)for(r=0;rz&&IL&&(L=I);f/=(L-E)/(2*C),E=l.l2r(E),L=l.l2r(L),l.range=l._input.range=A.2?\"rgba(0,0,0,0)\":\"rgba(255,255,255,0)\",\"stroke-width\":0}).attr(\"transform\",\"translate(\"+r+\", \"+n+\")\").attr(\"d\",i+\"Z\")}function c(t,e,r){return t.append(\"path\").attr(\"class\",\"zoombox-corners\").style({fill:k.background,stroke:k.defaultLine,\"stroke-width\":1,opacity:0}).attr(\"transform\",\"translate(\"+e+\", \"+r+\")\").attr(\"d\",\"M0,0Z\")}function u(t){t.selectAll(\".select-outline\").remove()}function f(t,e,r,n,i,a){t.attr(\"d\",n+\"M\"+r.l+\",\"+r.t+\"v\"+r.h+\"h\"+r.w+\"v-\"+r.h+\"h-\"+r.w+\"Z\"),h(t,e,i,a)}function h(t,e,r,n){r||(t.transition().style(\"fill\",n>.2?\"rgba(0,0,0,0.4)\":\"rgba(255,255,255,0.3)\").duration(200),e.transition().style(\"opacity\",1).duration(200))}function d(t){y.select(t).selectAll(\".zoombox,.js-zoombox-backdrop,.js-zoombox-menu,.zoombox-corners\").remove()}function p(t){j&&t.data&&t._context.showTips&&(w.notifier(w._(t,\"Double-click to zoom back out\"),\"long\"),j=!1)}function m(t){return\"lasso\"===t||\"select\"===t}function g(t){var e=Math.floor(Math.min(t.b-t.t,t.r-t.l,R)/2);return\"M\"+(t.l-3.5)+\",\"+(t.t-.5+e)+\"h3v\"+-e+\"h\"+e+\"v-3h-\"+(e+3)+\"ZM\"+(t.r+3.5)+\",\"+(t.t-.5+e)+\"h-3v\"+-e+\"h\"+-e+\"v-3h\"+(e+3)+\"ZM\"+(t.r+3.5)+\",\"+(t.b+.5-e)+\"h-3v\"+e+\"h\"+-e+\"v3h\"+(e+3)+\"ZM\"+(t.l-3.5)+\",\"+(t.b+.5-e)+\"h3v\"+e+\"h\"+e+\"v3h-\"+(e+3)+\"Z\"}function v(t,e){if(N){var r=void 0!==t.onwheel?\"wheel\":\"mousewheel\";t._onwheel&&t.removeEventListener(r,t._onwheel),t._onwheel=e,t.addEventListener(r,e,{passive:!1})}else void 0!==t.onwheel?t.onwheel=e:void 0!==t.onmousewheel&&(t.onmousewheel=e)}var y=t(\"d3\"),x=t(\"tinycolor2\"),b=t(\"../../plotly\"),_=t(\"../../registry\"),w=t(\"../../lib\"),M=t(\"../../lib/svg_text_utils\"),k=t(\"../../components/color\"),A=t(\"../../components/drawing\"),T=t(\"../../components/fx\"),S=t(\"../../lib/setcursor\"),E=t(\"../../components/dragelement\"),L=t(\"../../constants/alignment\").FROM_TL,C=t(\"../plots\"),z=t(\"./axes\").doTicks,D=t(\"./axis_ids\").getFromId,I=t(\"./select\"),P=t(\"./scale_zoom\"),O=t(\"./constants\"),F=O.MINDRAG,R=O.MINZOOM,N=w.eventListenerOptionsSupported(),j=!0;e.exports={makeDragBox:function(t,e,r,n,h,k,S,N){function j(){X=[e.xaxis],Z=[e.yaxis];var r=X[0],n=Z[0];Q=r._length,$=n._length;var i=ot._axisConstraintGroups,o=[r._id],s=[n._id];W=[e].concat(S&&N?e.overlays:[]);for(var l=1;lR||s>R?(xt=\"xy\",o/Q>s/$?(s=o*$/Q,pt>a?mt.t=pt-s:mt.b=pt+s):(o=s*Q/$,dt>i?mt.l=dt-o:mt.r=dt+o),_t.attr(\"d\",g(mt))):n():!et||s10||n.scrollWidth-n.clientWidth>10)){clearTimeout(kt);var i=-e.deltaY;if(isFinite(i)||(i=e.wheelDelta/10),isFinite(i)){var a,o=Math.exp(-Math.min(Math.max(i,-20),20)/200),s=Tt.draglayer.select(\".nsewdrag\").node().getBoundingClientRect(),l=(e.clientX-s.left)/s.width,c=(s.bottom-e.clientY)/s.height;if(N||nt){for(N||(l=.5),a=0;a=0?Math.min(t,.9):1/(1/Math.max(t,-.3)+3.222))}(r/s._length);var l=s.l2r(i);!1!==l&&void 0!==l&&(s.range[e]=l)}}return n._length*(n._rl[e]-i)/(n._rl[e]-n._rl[a])}if(!t._transitioningWithDuration){if(j(),\"ew\"===tt||\"ns\"===et)return tt&&s(X,e),et&&s(Z,r),Y([tt?-e:0,et?-r:0,Q,$]),void H(et,tt);if(nt&&tt&&et){var i=\"w\"===tt==(\"n\"===et)?1:-1,a=(e/Q+i*r/$)/2;e=a*Q,r=i*a*$}\"w\"===tt?e=n(X,0,e):\"e\"===tt?e=n(X,1,-e):tt||(e=0),\"n\"===et?r=n(Z,1,r):\"s\"===et?r=n(Z,0,-r):et||(r=0);var o=\"w\"===tt?e:0,l=\"n\"===et?r:0;if(nt){var c;if(!tt&&1===et.length){for(c=0;c rect\").call(A.setTranslate,s,l).call(A.setScale,a,o);var T=m.plot.selectAll(\".scatterlayer .trace, .boxlayer .trace, .violinlayer .trace\");m.plot.call(A.setTranslate,M,k).call(A.setScale,1/a,1/o),T.selectAll(\".point\").call(A.setPointGroupScale,a,o),T.selectAll(\".textpoint\").call(A.setTextPointsScale,a,o),T.call(A.hideOutsideRangePoints,m)}}}var W,X,Z,J,K,Q,$,tt,et,rt,nt,it,at,ot=t._fullLayout,st=t._fullLayout._zoomlayer,lt=S+N===\"nsew\",ct=1===(S+N).length;j();var ut=i(e,S+N+\"drag\",rt,r,n,h,k),ft=!et&&!tt;if(ft&&!lt)return ut.onmousedown=null,ut.style.pointerEvents=\"none\",ut;var ht={element:ut,gd:t,plotinfo:e,prepFn:function(e,r,n){var i=t._fullLayout.dragmode;ft||(lt?e.shiftKey?\"pan\"===i?i=\"zoom\":m(i)||(i=\"pan\"):e.ctrlKey&&(i=\"pan\"):i=\"pan\"),ht.minDrag=\"lasso\"===i?1:void 0,m(i)?(ht.xaxes=X,ht.yaxes=Z,I(e,r,n,ht,i)):ft?u(st):\"zoom\"===i?(ht.moveFn=B,ht.doneFn=U,ht.minDrag=1,function(e,r,n){var i=ut.getBoundingClientRect();dt=r-i.left,pt=n-i.top,mt={l:dt,r:dt,w:0,t:pt,b:pt,h:0},gt=t._hmpixcount?t._hmlumcount/t._hmpixcount:x(t._fullLayout.plot_bgcolor).getLuminance(),yt=!1,xt=\"xy\",bt=l(st,gt,J,K,vt=\"M0,0H\"+Q+\"V\"+$+\"H0V0\"),_t=c(st,J,K),u(st)}(0,r,n)):\"pan\"===i&&(ht.moveFn=q,ht.doneFn=G,u(st))},clickFn:function(r,n){if(d(t),2!==r||ct||function(){if(!t._transitioningWithDuration){var e,r,n,i=t._context.doubleClick,a=(tt?X:[]).concat(et?Z:[]),o={};if(\"reset+autosize\"===i)for(i=\"autosize\",r=0;ru[1]-.01&&(e.domain=[0,1]),i.noneOrAll(t.domain,e.domain,[0,1])}return r(\"layer\"),e}},{\"../../lib\":743,\"fast-isnumeric\":140}],806:[function(t,e,r){\"use strict\";var n=t(\"../../constants/alignment\").FROM_BL;e.exports=function(t,e,r){void 0===r&&(r=n[t.constraintoward||\"center\"]);var i=[t.r2l(t.range[0]),t.r2l(t.range[1])],a=i[0]+(i[1]-i[0])*r;t.range=t._input.range=[t.l2r(a+(i[0]-a)*e),t.l2r(a+(i[1]-a)*e)]}},{\"../../constants/alignment\":716}],807:[function(t,e,r){\"use strict\";function n(t){return t._id}function i(t,e,r){var n,i,a;if(r){var o=r.points||[];for(n=0;n0)return Math.log(e)/Math.LN10;if(e<=0&&r&&t.range&&2===t.range.length){var n=t.range[0],i=t.range[1];return.5*(n+i-3*M*Math.abs(n-i))}return d}function f(e,r,n){var i=c(e,n||t.calendar);if(i===d){if(!a(e))return d;i=c(new Date(+e))}return i}function g(e,r,n){return l(e,r,n||t.calendar)}function v(e){return t._categories[Math.round(e)]}function y(e){if(null!==e&&void 0!==e){if(void 0===t._categoriesMap&&(t._categoriesMap={}),void 0!==t._categoriesMap[e])return t._categoriesMap[e];t._categories.push(e);var r=t._categories.length-1;return t._categoriesMap[e]=r,r}return d}function x(e){if(t._categoriesMap){var r=t._categoriesMap[e];if(void 0!==r)return r}if(a(e))return+e}function b(e){return a(e)?i.round(t._b+t._m*e,2):d}function _(e){return(e-t._b)/t._m}e=e||{};var w=(t._id||\"x\").charAt(0),M=10;t.c2l=\"log\"===t.type?r:u,t.l2c=\"log\"===t.type?n:u,t.l2p=b,t.p2l=_,t.c2p=\"log\"===t.type?function(t,e){return b(r(t,e))}:b,t.p2c=\"log\"===t.type?function(t){return n(_(t))}:_,-1!==[\"linear\",\"-\"].indexOf(t.type)?(t.d2r=t.r2d=t.d2c=t.r2c=t.d2l=t.r2l=s,t.c2d=t.c2r=t.l2d=t.l2r=u,t.d2p=t.r2p=function(e){return t.l2p(s(e))},t.p2d=t.p2r=_,t.cleanPos=u):\"log\"===t.type?(t.d2r=t.d2l=function(t,e){return r(s(t),e)},t.r2d=t.r2c=function(t){return n(s(t))},t.d2c=t.r2l=s,t.c2d=t.l2r=u,t.c2r=r,t.l2d=n,t.d2p=function(e,r){return t.l2p(t.d2r(e,r))},t.p2d=function(t){return n(_(t))},t.r2p=function(e){return t.l2p(s(e))},t.p2r=_,t.cleanPos=u):\"date\"===t.type?(t.d2r=t.r2d=o.identity,t.d2c=t.r2c=t.d2l=t.r2l=f,t.c2d=t.c2r=t.l2d=t.l2r=g,t.d2p=t.r2p=function(e,r,n){return t.l2p(f(e,0,n))},t.p2d=t.p2r=function(t,e,r){return g(_(t),e,r)},t.cleanPos=function(e){return o.cleanDate(e,d,t.calendar)}):\"category\"===t.type&&(t.d2c=t.d2l=y,t.r2d=t.c2d=t.l2d=v,t.d2r=t.d2l_noadd=x,t.r2c=function(e){var r=x(e);return void 0!==r?r:t.fraction2r(.5)},t.l2r=t.c2r=u,t.r2l=x,t.d2p=function(e){return t.l2p(t.r2c(e))},t.p2d=function(t){return v(_(t))},t.r2p=t.d2p,t.p2r=_,t.cleanPos=function(t){return\"string\"==typeof t&&\"\"!==t?t:u(t)}),t.fraction2r=function(e){var r=t.r2l(t.range[0]),n=t.r2l(t.range[1]);return t.l2r(r+e*(n-r))},t.r2fraction=function(e){var r=t.r2l(t.range[0]),n=t.r2l(t.range[1]);return(t.r2l(e)-r)/(n-r)},t.cleanRange=function(e,r){r||(r={}),e||(e=\"range\");var n,i,s=o.nestedProperty(t,e).get();if(i=\"date\"===t.type?o.dfltRange(t.calendar):\"y\"===w?p.DFLTRANGEY:r.dfltRange||p.DFLTRANGEX,i=i.slice(),s&&2===s.length)for(\"date\"===t.type&&(s[0]=o.cleanDate(s[0],d,t.calendar),s[1]=o.cleanDate(s[1],d,t.calendar)),n=0;n<2;n++)if(\"date\"===t.type){if(!o.isDateTime(s[n],t.calendar)){t[e]=i;break}if(t.r2l(s[0])===t.r2l(s[1])){var l=o.constrain(t.r2l(s[0]),o.MIN_MS+1e3,o.MAX_MS-1e3);s[0]=t.l2r(l-1e3),s[1]=t.l2r(l+1e3);break}}else{if(!a(s[n])){if(!a(s[1-n])){t[e]=i;break}s[n]=s[1-n]*(n?10:.1)}if(s[n]<-h?s[n]=-h:s[n]>h&&(s[n]=h),s[0]===s[1]){var c=Math.max(1,Math.abs(1e-6*s[0]));s[0]-=c,s[1]+=c}}else o.nestedProperty(t,e).set(i)},t.setScale=function(r){var n=e._size;if(t._categories||(t._categories=[]),t._categoriesMap||(t._categoriesMap={}),t.overlaying){var i=m.getFromId({_fullLayout:e},t.overlaying);t.domain=i.domain}var a=r&&t._r?\"_r\":\"range\",o=t.calendar;t.cleanRange(a);var s=t.r2l(t[a][0],o),l=t.r2l(t[a][1],o);if(\"y\"===w?(t._offset=n.t+(1-t.domain[1])*n.h,t._length=n.h*(t.domain[1]-t.domain[0]),t._m=t._length/(s-l),t._b=-t._m*l):(t._offset=n.l+t.domain[0]*n.w,t._length=n.w*(t.domain[1]-t.domain[0]),t._m=t._length/(l-s),t._b=-t._m*s),!isFinite(t._m)||!isFinite(t._b))throw e._replotting=!1,new Error(\"Something went wrong with axis scaling\")},t.makeCalcdata=function(e,r){var n,i,a,o=\"date\"===t.type&&e[r+\"calendar\"];if(r in e)for(n=e[r],i=new Array(n.length),a=0;a=t.r2l(t.range[0])&&n<=t.r2l(t.range[1])},t._min=[],t._max=[];var k=e._d3locale;\"date\"===t.type&&(t._dateFormat=k?k.timeFormat.utc:i.time.format.utc),t._separators=e.separators,t._numFormat=k?k.numberFormat:i.format,delete t._minDtick,delete t._forceTick0}},{\"../../constants/numerical\":721,\"../../lib\":743,\"./axis_ids\":792,\"./constants\":794,d3:128,\"fast-isnumeric\":140}],809:[function(t,e,r){\"use strict\";var n=t(\"../../lib\"),i=t(\"./layout_attributes\");e.exports=function(t,e,r,a,o){var s=function(t){var e=[\"showexponent\",\"showtickprefix\",\"showticksuffix\"].filter(function(e){return void 0!==t[e]});if(e.every(function(r){return t[r]===t[e[0]]})||1===e.length)return t[e[0]]}(t);r(\"tickprefix\")&&r(\"showtickprefix\",s);r(\"ticksuffix\",o.tickSuffixDflt)&&r(\"showticksuffix\",s);if(r(\"showticklabels\")){var l=o.font||{},c=e.color===t.color?e.color:l.color;if(n.coerceFont(r,\"tickfont\",{family:l.family,size:l.size,color:c}),r(\"tickangle\"),\"category\"!==a){var u=r(\"tickformat\");!function(t,e){function r(t,e){return n.coerce(s,l,i.tickformatstops,t,e)}var a=t.tickformatstops,o=e.tickformatstops=[];if(Array.isArray(a))for(var s,l,c=0;c0?Number(u):c;else if(\"string\"!=typeof u)e.dtick=c;else{var f=u.charAt(0),h=u.substr(1);((h=n(h)?Number(h):0)<=0||!(\"date\"===o&&\"M\"===f&&h===Math.round(h)||\"log\"===o&&\"L\"===f||\"log\"===o&&\"D\"===f&&(1===h||2===h)))&&(e.dtick=c)}var d=\"date\"===o?i.dateTick0(e.calendar):0,p=r(\"tick0\",d);\"date\"===o?e.tick0=i.cleanDate(p,d):n(p)&&\"D1\"!==u&&\"D2\"!==u?e.tick0=Number(p):e.tick0=d}else{void 0===r(\"tickvals\")?e.tickmode=\"auto\":r(\"ticktext\")}}},{\"../../constants/numerical\":721,\"../../lib\":743,\"fast-isnumeric\":140}],812:[function(t,e,r){\"use strict\";var n=t(\"d3\"),i=t(\"../../plotly\"),a=t(\"../../registry\"),o=t(\"../../components/drawing\"),s=t(\"./axes\"),l=t(\"./constants\").attrRegex;e.exports=function(t,e,r,c){function u(t){var e=t.xaxis,r=t.yaxis;d._defs.select(\"#\"+t.clipId+\"> rect\").call(o.setTranslate,0,0).call(o.setScale,1,1),t.plot.call(o.setTranslate,e._offset,r._offset).call(o.setScale,1,1);var n=t.plot.selectAll(\".scatterlayer .trace\");n.selectAll(\".point\").call(o.setPointGroupScale,1,1),n.selectAll(\".textpoint\").call(o.setTextPointsScale,1,1),n.call(o.hideOutsideRangePoints,t)}function f(e,r){var n,i,l,c=m[e.xaxis._id],u=m[e.yaxis._id],f=[];if(c){i=(n=t._fullLayout[c.axisName])._r,l=c.to,f[0]=(i[0]*(1-r)+r*l[0]-i[0])/(i[1]-i[0])*e.xaxis._length;var h=i[1]-i[0],p=l[1]-l[0];n.range[0]=i[0]*(1-r)+r*l[0],n.range[1]=i[1]*(1-r)+r*l[1],f[2]=e.xaxis._length*(1-r+r*p/h)}else f[0]=0,f[2]=e.xaxis._length;if(u){i=(n=t._fullLayout[u.axisName])._r,l=u.to,f[1]=(i[1]*(1-r)+r*l[1]-i[1])/(i[0]-i[1])*e.yaxis._length;var g=i[1]-i[0],v=l[1]-l[0];n.range[0]=i[0]*(1-r)+r*l[0],n.range[1]=i[1]*(1-r)+r*l[1],f[3]=e.yaxis._length*(1-r+r*v/g)}else f[1]=0,f[3]=e.yaxis._length;!function(e,r){function n(e,r,n){for(i=0;i rect\").call(o.setTranslate,k,A).call(o.setScale,1/w,1/M),e.plot.call(o.setTranslate,E,L).call(o.setScale,w,M).selectAll(\".points\").selectAll(\".point\").call(o.setPointGroupScale,1/w,1/M),e.plot.selectAll(\".points\").selectAll(\".textpoint\").call(o.setTextPointsScale,1/w,1/M)}function h(){b=Date.now();for(var e=Math.min(1,(b-x)/r.duration),n=w(e),a=0;ar.duration?(!function(){for(var e={},r=0;r0?\".\":\"\")+i;l.isPlainObject(a)?o(a,e,s,n+1):e(s,i,a)}})}var s=t(\"../plotly\"),l=t(\"../lib\");r.manageCommandObserver=function(t,e,i,a){var o={},s=!0;e&&e._commandObserver&&(o=e._commandObserver),o.cache||(o.cache={}),o.lookupTable={};var c=r.hasSimpleAPICommandBindings(t,i,o.lookupTable);if(e&&e._commandObserver){if(c)return o;if(e._commandObserver.remove)return e._commandObserver.remove(),e._commandObserver=null,o}if(c){n(t,c,o.cache),o.check=function(){if(s){var e=n(t,c,o.cache);return e.changed&&a&&void 0!==o.lookupTable[e.value]&&(o.disable(),Promise.resolve(a({value:e.value,type:c.type,prop:c.prop,traces:c.traces,index:o.lookupTable[e.value]})).then(o.enable,o.enable)),e.changed}};for(var u=[\"plotly_relayout\",\"plotly_redraw\",\"plotly_restyle\",\"plotly_update\",\"plotly_animatingframe\",\"plotly_afterplot\"],f=0;fn*Math.PI/180}return!1},r.getPath=function(){return i.geo.path().projection(r)},r.getBounds=function(t){return r.getPath().bounds(t)},r.fitExtent=function(t,e){var n=t[1][0]-t[0][0],i=t[1][1]-t[0][1],a=r.clipExtent&&r.clipExtent();r.scale(150).translate([0,0]),a&&r.clipExtent(null);var o=r.getBounds(e),s=Math.min(n/(o[1][0]-o[0][0]),i/(o[1][1]-o[0][1])),l=+t[0][0]+(n-s*(o[1][0]+o[0][0]))/2,c=+t[0][1]+(i-s*(o[1][1]+o[0][1]))/2;return a&&r.clipExtent(a),r.scale(150*s).translate([l,c])},r.precision(m.precision),n&&r.clipAngle(n-m.clipPad),r}(e);u.center([c.lon-l.lon,c.lat-l.lat]).rotate([-l.lon,-l.lat,l.roll]).parallels(s.parallels);var f=[[r.l+r.w*n.x[0],r.t+r.h*(1-n.y[1])],[r.l+r.w*n.x[1],r.t+r.h*(1-n.y[0])]],h=e.lonaxis,d=e.lataxis,p=function(t,e){var r=m.clipPad,n=t[0]+r,i=t[1]-r,a=e[0]+r,o=e[1]-r;n>0&&i<0&&(i+=360);var s=(i-n)/4;return{type:\"Polygon\",coordinates:[[[n,a],[n,o],[n+s,o],[n+2*s,o],[n+3*s,o],[i,o],[i,a],[i-s,a],[i-2*s,a],[i-3*s,a],[n,a]]]}}(h.range,d.range);u.fitExtent(f,p);var g=this.bounds=u.getBounds(p),v=this.fitScale=u.scale(),y=u.translate();if(!isFinite(g[0][0])||!isFinite(g[0][1])||!isFinite(g[1][0])||!isFinite(g[1][1])||isNaN(y[0])||isNaN(y[0])){for(var x=this.graphDiv,b=[\"projection.rotation\",\"center\",\"lonaxis.range\",\"lataxis.range\"],_=\"Invalid geo settings, relayout'ing to default view.\",w={},M=0;M0&&w<0&&(w+=360);var M,k=(_+w)/2;if(!c){var A=u?o.projRotate:[k,0,0];M=r(\"projection.rotation.lon\",A[0]),r(\"projection.rotation.lat\",A[1]),r(\"projection.rotation.roll\",A[2]),r(\"showcoastlines\",!u)&&(r(\"coastlinecolor\"),r(\"coastlinewidth\")),r(\"showocean\")&&r(\"oceancolor\")}var T,S;if(c?(T=-96.6,S=38.7):(T=u?k:M,S=(b[0]+b[1])/2),r(\"center.lon\",T),r(\"center.lat\",S),f){r(\"projection.parallels\",o.projParallels||[0,60])}r(\"projection.scale\"),r(\"showland\")&&r(\"landcolor\"),r(\"showlakes\")&&r(\"lakecolor\"),r(\"showrivers\")&&(r(\"rivercolor\"),r(\"riverwidth\")),r(\"showcountries\",u&&\"usa\"!==i)&&(r(\"countrycolor\"),r(\"countrywidth\")),(\"usa\"===i||\"north america\"===i&&50===n)&&(r(\"showsubunits\",!0),r(\"subunitcolor\"),r(\"subunitwidth\")),u||r(\"showframe\",!0)&&(r(\"framecolor\"),r(\"framewidth\")),r(\"bgcolor\")}var i=t(\"../../subplot_defaults\"),a=t(\"../constants\"),o=t(\"./layout_attributes\"),s=a.axesNames;e.exports=function(t,e,r){i(t,e,r,{type:\"geo\",attributes:o,handleDefaults:n,partition:\"y\"})}},{\"../../subplot_defaults\":865,\"../constants\":818,\"./layout_attributes\":823}],823:[function(t,e,r){\"use strict\";var n=t(\"../../../components/color/attributes\"),i=t(\"../../domain_attributes\"),a=t(\"../constants\"),o=t(\"../../../plot_api/edit_types\").overrideAll,s={range:{valType:\"info_array\",items:[{valType:\"number\"},{valType:\"number\"}]},showgrid:{valType:\"boolean\",dflt:!1},tick0:{valType:\"number\"},dtick:{valType:\"number\"},gridcolor:{valType:\"color\",dflt:n.lightLine},gridwidth:{valType:\"number\",min:0,dflt:1}};e.exports=o({domain:i({name:\"geo\"},{}),resolution:{valType:\"enumerated\",values:[110,50],dflt:110,coerceNumber:!0},scope:{valType:\"enumerated\",values:Object.keys(a.scopeDefaults),dflt:\"world\"},projection:{type:{valType:\"enumerated\",values:Object.keys(a.projNames)},rotation:{lon:{valType:\"number\"},lat:{valType:\"number\"},roll:{valType:\"number\"}},parallels:{valType:\"info_array\",items:[{valType:\"number\"},{valType:\"number\"}]},scale:{valType:\"number\",min:0,dflt:1}},center:{lon:{valType:\"number\"},lat:{valType:\"number\"}},showcoastlines:{valType:\"boolean\"},coastlinecolor:{valType:\"color\",dflt:n.defaultLine},coastlinewidth:{valType:\"number\",min:0,dflt:1},showland:{valType:\"boolean\",dflt:!1},landcolor:{valType:\"color\",dflt:a.landColor},showocean:{valType:\"boolean\",dflt:!1},oceancolor:{valType:\"color\",dflt:a.waterColor},showlakes:{valType:\"boolean\",dflt:!1},lakecolor:{valType:\"color\",dflt:a.waterColor},showrivers:{valType:\"boolean\",dflt:!1},rivercolor:{valType:\"color\",dflt:a.waterColor},riverwidth:{valType:\"number\",min:0,dflt:1},showcountries:{valType:\"boolean\"},countrycolor:{valType:\"color\",dflt:n.defaultLine},countrywidth:{valType:\"number\",min:0,dflt:1},showsubunits:{valType:\"boolean\"},subunitcolor:{valType:\"color\",dflt:n.defaultLine},subunitwidth:{valType:\"number\",min:0,dflt:1},showframe:{valType:\"boolean\"},framecolor:{valType:\"color\",dflt:n.defaultLine},framewidth:{valType:\"number\",min:0,dflt:1},bgcolor:{valType:\"color\",dflt:n.background},lonaxis:s,lataxis:s},\"plot\",\"from-root\")},{\"../../../components/color/attributes\":617,\"../../../plot_api/edit_types\":773,\"../../domain_attributes\":815,\"../constants\":818}],824:[function(t,e,r){\"use strict\";e.exports=function(t){function e(t,e){return{type:\"Feature\",id:t.id,properties:t.properties,geometry:r(t.geometry,e)}}function r(e,n){if(!e)return null;if(\"GeometryCollection\"===e.type)return{type:\"GeometryCollection\",geometries:object.geometries.map(function(t){return r(t,n)})};if(!M.hasOwnProperty(e.type))return null;var i=M[e.type];return t.geo.stream(e,n(i)),i.result()}function n(){}function i(t){return t>1?S:t<-1?-S:Math.asin(t)}function a(t){return t>1?0:t<-1?T:Math.acos(t)}function o(t,e){var r=(2+S)*Math.sin(e);e/=2;for(var n=0,i=1/0;n<10&&Math.abs(i)>k;n++){var a=Math.cos(e);e-=i=(e+Math.sin(e)*(a+2)-r)/(2*a*(1+a))}return[2/Math.sqrt(T*(4+T))*t*(1+Math.cos(e)),2*Math.sqrt(T/(4+T))*Math.sin(e)]}function s(t,e){function r(r,n){var i=D(r/e,n);return i[0]*=t,i}return arguments.length<2&&(e=t),1===e?D:e===1/0?l:(r.invert=function(r,n){var i=D.invert(r/t,n);return i[0]*=e,i},r)}function l(t,e){return[t*Math.cos(e)/Math.cos(e/=2),2*Math.sin(e)]}function c(t,e){return[3*t/(2*T)*Math.sqrt(T*T/3-e*e),e]}function u(t,e){return[t,1.25*Math.log(Math.tan(T/4+.4*e))]}function f(t){return function(e){var r,n=t*Math.sin(e),i=30;do{e-=r=(e+Math.sin(e)-n)/(1+Math.cos(e))}while(Math.abs(r)>k&&--i>0);return e/2}}function h(t,e){var r=e*e,n=r*r;return[t*(.8707-.131979*r+n*(n*(.003971*r-.001529*n)-.013791)),e*(1.007226+r*(.015085+n*(.028874*r-.044475-.005916*n)))]}function d(t,e){var r,n=Math.min(18,36*Math.abs(e)/T),i=Math.floor(n),a=n-i,o=(r=P[i])[0],s=r[1],l=(r=P[++i])[0],c=r[1],u=(r=P[Math.min(19,++i)])[0],f=r[1];return[t*(l+a*(u-o)/2+a*a*(u-2*l+o)/2),(e>0?S:-S)*(c+a*(f-s)/2+a*a*(f-2*c+s)/2)]}function p(t,e){return[t*Math.cos(e),e]}function m(t,e){var r=Math.cos(e),n=function(t){return t?t/Math.sin(t):1}(a(r*Math.cos(t/=2)));return[2*r*Math.sin(t)*n,Math.sin(e)*n]}function g(t,e){var r=m(t,e);return[(r[0]+t/S)/2,(r[1]+e)/2]}t.geo.project=function(t,e){var n=e.stream;if(!n)throw new Error(\"not yet supported\");return(t&&v.hasOwnProperty(t.type)?v[t.type]:r)(t,n)};var v={Feature:e,FeatureCollection:function(t,r){return{type:\"FeatureCollection\",features:t.features.map(function(t){return e(t,r)})}}},y=[],x=[],b={point:function(t,e){y.push([t,e])},result:function(){var t=y.length?y.length<2?{type:\"Point\",coordinates:y[0]}:{type:\"MultiPoint\",coordinates:y}:null;return y=[],t}},_={lineStart:n,point:function(t,e){y.push([t,e])},lineEnd:function(){y.length&&(x.push(y),y=[])},result:function(){var t=x.length?x.length<2?{type:\"LineString\",coordinates:x[0]}:{type:\"MultiLineString\",coordinates:x}:null;return x=[],t}},w={polygonStart:n,lineStart:n,point:function(t,e){y.push([t,e])},lineEnd:function(){var t=y.length;if(t){do{y.push(y[0].slice())}while(++t<4);x.push(y),y=[]}},polygonEnd:n,result:function(){if(!x.length)return null;var t=[],e=[];return x.forEach(function(r){!function(t){if((e=t.length)<4)return!1;for(var e,r=0,n=t[e-1][1]*t[0][0]-t[e-1][0]*t[0][1];++rn^d>n&&r<(h-c)*(n-u)/(d-u)+c&&(i=!i)}return i}(t[0],r))return t.push(e),!0})||t.push([e])}),x=[],t.length?t.length>1?{type:\"MultiPolygon\",coordinates:t}:{type:\"Polygon\",coordinates:t[0]}:null}},M={Point:b,MultiPoint:b,LineString:_,MultiLineString:_,Polygon:w,MultiPolygon:w,Sphere:w},k=1e-6,A=k*k,T=Math.PI,S=T/2,E=(Math.sqrt(T),T/180),L=180/T,C=t.geo.projection,z=t.geo.projectionMutator;t.geo.interrupt=function(e){function r(t,r){for(var n=r<0?-1:1,i=a[+(r<0)],o=0,s=i.length-1;oi[o][2][0];++o);var l=e(t-i[o][1][0],r);return l[0]+=e(i[o][1][0],n*r>n*i[o][0][1]?i[o][0][1]:r)[0],l}function n(t,e){for(var r,n,i,a=-1,o=t.length,s=t[0],l=[];++a=0;--r){var f;o=180*(f=a[1][r])[0][0]/T,s=180*f[0][1]/T,l=180*f[1][1]/T,c=180*f[2][0]/T,u=180*f[2][1]/T,e.push(n([[c-1e-6,u-1e-6],[c-1e-6,l+1e-6],[o+1e-6,l+1e-6],[o+1e-6,s-1e-6]],30))}return{type:\"Polygon\",coordinates:[t.merge(e)]}}(),l)},i},o.lobes=function(t){return arguments.length?(a=t.map(function(t){return t.map(function(t){return[[t[0][0]*T/180,t[0][1]*T/180],[t[1][0]*T/180,t[1][1]*T/180],[t[2][0]*T/180,t[2][1]*T/180]]})}),i=a.map(function(t){return t.map(function(t){var r,n=e(t[0][0],t[0][1])[0],i=e(t[2][0],t[2][1])[0],a=e(t[1][0],t[0][1])[1],o=e(t[1][0],t[1][1])[1];return a>o&&(r=a,a=o,o=r),[[n,a],[i,o]]})}),o):a.map(function(t){return t.map(function(t){return[[180*t[0][0]/T,180*t[0][1]/T],[180*t[1][0]/T,180*t[1][1]/T],[180*t[2][0]/T,180*t[2][1]/T]]})})},o},o.invert=function(t,e){var r=.5*e*Math.sqrt((4+T)/T),n=i(r),a=Math.cos(n);return[t/(2/Math.sqrt(T*(4+T))*(1+a)),i((n+r*(a+2))/(2+S))]},(t.geo.eckert4=function(){return C(o)}).raw=o;var D=t.geo.azimuthalEqualArea.raw;l.invert=function(t,e){var r=2*i(e/2);return[t*Math.cos(r/2)/Math.cos(r),r]},(t.geo.hammer=function(){var t=2,e=z(s),r=e(t);return r.coefficient=function(r){return arguments.length?e(t=+r):t},r}).raw=s,c.invert=function(t,e){return[2/3*T*t/Math.sqrt(T*T/3-e*e),e]},(t.geo.kavrayskiy7=function(){return C(c)}).raw=c,u.invert=function(t,e){return[t,2.5*Math.atan(Math.exp(.8*e))-.625*T]},(t.geo.miller=function(){return C(u)}).raw=u,f(T);var I=function(t,e,r){function n(r,n){return[t*r*Math.cos(n=a(n)),e*Math.sin(n)]}var a=f(r);return n.invert=function(n,a){var o=i(a/e);return[n/(t*Math.cos(o)),i((2*o+Math.sin(2*o))/r)]},n}(Math.SQRT2/S,Math.SQRT2,T);(t.geo.mollweide=function(){return C(I)}).raw=I,h.invert=function(t,e){var r,n=e,i=25;do{var a=n*n,o=a*a;n-=r=(n*(1.007226+a*(.015085+o*(.028874*a-.044475-.005916*o)))-e)/(1.007226+a*(.045255+o*(.259866*a-.311325-.005916*11*o)))}while(Math.abs(r)>k&&--i>0);return[t/(.8707+(a=n*n)*(a*(a*a*a*(.003971-.001529*a)-.013791)-.131979)),n]},(t.geo.naturalEarth=function(){return C(h)}).raw=h;var P=[[.9986,-.062],[1,0],[.9986,.062],[.9954,.124],[.99,.186],[.9822,.248],[.973,.31],[.96,.372],[.9427,.434],[.9216,.4958],[.8962,.5571],[.8679,.6176],[.835,.6769],[.7986,.7346],[.7597,.7903],[.7186,.8435],[.6732,.8936],[.6213,.9394],[.5722,.9761],[.5322,1]];P.forEach(function(t){t[1]*=1.0144}),d.invert=function(t,e){var r=e/S,n=90*r,i=Math.min(18,Math.abs(n/5)),a=Math.max(0,Math.floor(i));do{var o=P[a][1],s=P[a+1][1],l=P[Math.min(19,a+2)][1],c=l-o,u=l-2*s+o,f=2*(Math.abs(r)-s)/c,h=u/c,d=f*(1-h*f*(1-2*h*f));if(d>=0||1===a){n=(e>=0?5:-5)*(d+i);var p,m=50;do{d=(i=Math.min(18,Math.abs(n)/5))-(a=Math.floor(i)),o=P[a][1],s=P[a+1][1],l=P[Math.min(19,a+2)][1],n-=(p=(e>=0?S:-S)*(s+d*(l-o)/2+d*d*(l-2*s+o)/2)-e)*L}while(Math.abs(p)>A&&--m>0);break}}while(--a>=0);var g=P[a][0],v=P[a+1][0],y=P[Math.min(19,a+2)][0];return[t/(v+d*(y-g)/2+d*d*(y-2*v+g)/2),n*E]},(t.geo.robinson=function(){return C(d)}).raw=d,p.invert=function(t,e){return[t/Math.cos(e),e]},(t.geo.sinusoidal=function(){return C(p)}).raw=p,m.invert=function(t,e){if(!(t*t+4*e*e>T*T+k)){var r=t,n=e,i=25;do{var o,s=Math.sin(r),l=Math.sin(r/2),c=Math.cos(r/2),u=Math.sin(n),f=Math.cos(n),h=Math.sin(2*n),d=u*u,p=f*f,m=l*l,g=1-p*c*c,v=g?a(f*c)*Math.sqrt(o=1/g):o=0,y=2*v*f*l-t,x=v*u-e,b=o*(p*m+v*f*c*d),_=o*(.5*s*h-2*v*u*l),w=.25*o*(h*l-v*u*p*s),M=o*(d*c+v*m*f),A=_*w-M*b;if(!A)break;var S=(x*_-y*M)/A,E=(y*w-x*b)/A;r-=S,n-=E}while((Math.abs(S)>k||Math.abs(E)>k)&&--i>0);return[r,n]}},(t.geo.aitoff=function(){return C(m)}).raw=m,g.invert=function(t,e){var r=t,n=e,i=25;do{var o,s=Math.cos(n),l=Math.sin(n),c=Math.sin(2*n),u=l*l,f=s*s,h=Math.sin(r),d=Math.cos(r/2),p=Math.sin(r/2),m=p*p,g=1-f*d*d,v=g?a(s*d)*Math.sqrt(o=1/g):o=0,y=.5*(2*v*s*p+r/S)-t,x=.5*(v*l+n)-e,b=.5*o*(f*m+v*s*d*u)+.5/S,_=o*(h*c/4-v*l*p),w=.125*o*(c*p-v*l*f*h),M=.5*o*(u*d+v*m*s)+.5,A=_*w-M*b,T=(x*_-y*M)/A,E=(y*w-x*b)/A;r-=T,n-=E}while((Math.abs(T)>k||Math.abs(E)>k)&&--i>0);return[r,n]},(t.geo.winkel3=function(){return C(g)}).raw=g}},{}],825:[function(t,e,r){\"use strict\";function n(t,e){return d.behavior.zoom().translate(e.translate()).scale(e.scale())}function i(t,e,r){function n(t,e){var r=p.nestedProperty(s,t);r.get()!==e&&(r.set(e),p.nestedProperty(o,t).set(e),l[i+\".\"+t]=e)}var i=t.id,a=t.graphDiv,o=a.layout[i],s=a._fullLayout[i],l={};r(n),n(\"projection.scale\",e.scale()/t.fitScale),a.emit(\"plotly_relayout\",l)}function a(t,e){function r(r){var n=e.invert(t.midPt);r(\"center.lon\",n[0]),r(\"center.lat\",n[1])}var a=n(0,e);return a.on(\"zoomstart\",function(){d.select(this).style(v)}).on(\"zoom\",function(){e.scale(d.event.scale).translate(d.event.translate),t.render()}).on(\"zoomend\",function(){d.select(this).style(y),i(t,e,r)}),a}function o(t,e){function r(t){return e.invert(t)}function a(r){var n=e.rotate(),i=e.invert(t.midPt);r(\"projection.rotation.lon\",-n[0]),r(\"center.lon\",i[0]),r(\"center.lat\",i[1])}var o,s,l,c,u,f,h,p,m=n(0,e),g=2;return m.on(\"zoomstart\",function(){d.select(this).style(v),o=d.mouse(this),s=e.rotate(),l=e.translate(),c=s,u=r(o)}).on(\"zoom\",function(){if(f=d.mouse(this),function(t){var n=e(r(t));return Math.abs(n[0]-t[0])>g||Math.abs(n[1]-t[1])>g}(o))return m.scale(e.scale()),void m.translate(e.translate());e.scale(d.event.scale),e.translate([l[0],d.event.translate[1]]),u?r(f)&&(p=r(f),h=[c[0]+(p[0]-u[0]),s[1],s[2]],e.rotate(h),c=h):u=r(o=f),t.render()}).on(\"zoomend\",function(){d.select(this).style(y),i(t,e,a)}),m}function s(t,e){function r(t){var r=e.rotate();t(\"projection.rotation.lon\",-r[0]),t(\"projection.rotation.lat\",-r[1])}var a,o={r:e.rotate(),k:e.scale()},s=n(0,e),u=function(t){var e=0,r=arguments.length,n=[];for(;++em?(a=(h>0?90:-90)-p,i=0):(a=Math.asin(h/m)*g-p,i=Math.sqrt(m*m-h*h));var v=180-a-2*p,y=(Math.atan2(d,u)-Math.atan2(l,i))*g,x=(Math.atan2(d,u)-Math.atan2(l,-i))*g,b=c(r[0],r[1],a,y),_=c(r[0],r[1],v,x);return b<=_?[a,y,r[2]]:[v,x,r[2]]}(v,a,n);isFinite(x[0])&&isFinite(x[1])&&isFinite(x[2])||(x=n),e.rotate(x),n=x}}else a=l(e,t=s);!function(t){t({type:\"zoom\"})}(u.of(this,arguments))}),function(t){p++||t({type:\"zoomstart\"})}(u.of(this,arguments))}).on(\"zoomend\",function(){d.select(this).style(y),x.call(s,\"zoom\",null),function(t){--p||t({type:\"zoomend\"})}(u.of(this,arguments)),i(t,e,r)}).on(\"zoom.redraw\",function(){t.render()}),d.rebind(s,u,\"on\")}function l(t,e){var r=t.invert(e);return r&&isFinite(r[0])&&isFinite(r[1])&&function(t){var e=t[0]*m,r=t[1]*m,n=Math.cos(r);return[n*Math.cos(e),n*Math.sin(e),Math.sin(r)]}(r)}function c(t,e,r,n){var i=u(r-t),a=u(n-e);return Math.sqrt(i*i+a*a)}function u(t){return(t%360+540)%360-180}function f(t,e,r){var n=r*m,i=t.slice(),a=0===e?1:0,o=2===e?1:2,s=Math.cos(n),l=Math.sin(n);return i[a]=t[a]*s-t[o]*l,i[o]=t[o]*s+t[a]*l,i}function h(t,e){for(var r=0,n=0,i=t.length;nMath.abs(u)?(c.boxEnd[1]=c.boxStart[1]+Math.abs(s)*_*(u>=0?1:-1),c.boxEnd[1]f[3]&&(c.boxEnd[1]=f[3],c.boxEnd[0]=c.boxStart[0]+(f[3]-c.boxStart[1])/Math.abs(_))):(c.boxEnd[0]=c.boxStart[0]+Math.abs(u)/_*(s>=0?1:-1),c.boxEnd[0]f[2]&&(c.boxEnd[0]=f[2],c.boxEnd[1]=c.boxStart[1]+(f[2]-c.boxStart[0])*Math.abs(_)))}}else c.boxEnabled?(s=c.boxStart[0]!==c.boxEnd[0],u=c.boxStart[1]!==c.boxEnd[1],s||u?(s&&(a(0,c.boxStart[0],c.boxEnd[0]),t.xaxis.autorange=!1),u&&(a(1,c.boxStart[1],c.boxEnd[1]),t.yaxis.autorange=!1),t.relayoutCallback()):t.glplot.setDirty(),c.boxEnabled=!1,c.boxInited=!1):c.boxInited&&(c.boxInited=!1);break;case\"pan\":c.boxEnabled=!1,c.boxInited=!1,r?(c.panning||(c.dragStart[0]=n,c.dragStart[1]=i),Math.abs(c.dragStart[0]-n)h[p+2]&&(h[p]=-1,h[p+2]=1),(d=this[b[p]])._length=o.viewBox[p+2]-o.viewBox[p],s.doAutoRange(d),d.setScale();y(l),o.ticks=this.computeTickMarks(),o.dataBox=this.calcDataBox(),o.merge(r),n.update(o),this.glplot.draw()},w.calcDataBox=function(){var t=this.xaxis,e=this.yaxis,r=t.range,n=e.range,i=t.r2l,a=e.r2l;return[i(r[0]),a(n[0]),i(r[1]),a(n[1])]},w.setRanges=function(t){var e=this.xaxis,r=this.yaxis,n=e.l2r,i=r.l2r;e.range=[n(t[0]),n(t[2])],r.range=[i(t[1]),i(t[3])]},w.updateTraces=function(t,e){var r,n,i,a=Object.keys(this.traces);this.fullData=t;t:for(r=0;rMath.abs(e))c.rotate(a,0,0,-t*r*Math.PI*p.rotateSpeed/window.innerWidth);else{var o=-p.zoomSpeed*i*e/window.innerHeight*(a-c.lastT())/20;c.pan(a,0,0,f*(Math.exp(o)-1))}}},!0),p};var n=t(\"right-now\"),i=t(\"3d-view\"),a=t(\"mouse-change\"),o=t(\"mouse-wheel\"),s=t(\"mouse-event-offset\")},{\"3d-view\":40,\"mouse-change\":443,\"mouse-event-offset\":444,\"mouse-wheel\":446,\"right-now\":509}],832:[function(t,e,r){\"use strict\";var n=t(\"../../plot_api/edit_types\").overrideAll,i=t(\"../../components/fx/layout_attributes\"),a=t(\"./scene\"),o=t(\"../get_data\").getSubplotData,s=t(\"../../lib\"),l=t(\"../../constants/xmlns_namespaces\");r.name=\"gl3d\",r.attr=\"scene\",r.idRoot=\"scene\",r.idRegex=r.attrRegex=s.counterRegex(\"scene\"),r.attributes=t(\"./layout/attributes\"),r.layoutAttributes=t(\"./layout/layout_attributes\"),r.baseLayoutAttrOverrides=n({hoverlabel:i.hoverlabel},\"plot\",\"nested\"),r.supplyLayoutDefaults=t(\"./layout/defaults\"),r.plot=function(t){for(var e=t._fullLayout,r=t._fullData,n=e._subplots.gl3d,i=0;i1;s(t,e,r,{type:\"gl3d\",attributes:c,handleDefaults:n,fullLayout:e,font:e.font,fullData:r,getDfltFromLayout:function(e){if(!a)return i.validate(t[e],c[e])?t[e]:void 0},paper_bgcolor:e.paper_bgcolor,calendar:e.calendar})}},{\"../../../components/color\":618,\"../../../lib\":743,\"../../../registry\":873,\"../../subplot_defaults\":865,\"./axis_defaults\":835,\"./layout_attributes\":838}],838:[function(t,e,r){\"use strict\";function n(t,e,r){return{x:{valType:\"number\",dflt:t,editType:\"camera\"},y:{valType:\"number\",dflt:e,editType:\"camera\"},z:{valType:\"number\",dflt:r,editType:\"camera\"},editType:\"camera\"}}var i=t(\"./axis_attributes\"),a=t(\"../../domain_attributes\"),o=t(\"../../../lib/extend\").extendFlat,s=t(\"../../../lib\").counterRegex;e.exports={_arrayAttrRegexps:[s(\"scene\",\".annotations\",!0)],bgcolor:{valType:\"color\",dflt:\"rgba(0,0,0,0)\",editType:\"plot\"},camera:{up:o(n(0,0,1),{}),center:o(n(0,0,0),{}),eye:o(n(1.25,1.25,1.25),{}),editType:\"camera\"},domain:a({name:\"scene\",editType:\"plot\"}),aspectmode:{valType:\"enumerated\",values:[\"auto\",\"cube\",\"data\",\"manual\"],dflt:\"auto\",editType:\"plot\",impliedEdits:{\"aspectratio.x\":void 0,\"aspectratio.y\":void 0,\"aspectratio.z\":void 0}},aspectratio:{x:{valType:\"number\",min:0,editType:\"plot\",impliedEdits:{\"^aspectmode\":\"manual\"}},y:{valType:\"number\",min:0,editType:\"plot\",impliedEdits:{\"^aspectmode\":\"manual\"}},z:{valType:\"number\",min:0,editType:\"plot\",impliedEdits:{\"^aspectmode\":\"manual\"}},editType:\"plot\",impliedEdits:{aspectmode:\"manual\"}},xaxis:i,yaxis:i,zaxis:i,dragmode:{valType:\"enumerated\",values:[\"orbit\",\"turntable\",\"zoom\",\"pan\",!1],dflt:\"turntable\",editType:\"plot\"},hovermode:{valType:\"enumerated\",values:[\"closest\",!1],dflt:\"closest\",editType:\"modebar\"},editType:\"plot\",_deprecated:{cameraposition:{valType:\"info_array\",editType:\"camera\"}}}},{\"../../../lib\":743,\"../../../lib/extend\":732,\"../../domain_attributes\":815,\"./axis_attributes\":834}],839:[function(t,e,r){\"use strict\";function n(){this.enabled=[!0,!0,!0],this.colors=[[0,0,0,1],[0,0,0,1],[0,0,0,1]],this.drawSides=[!0,!0,!0],this.lineWidth=[1,1,1]}var i=t(\"../../../lib/str2rgbarray\"),a=[\"xaxis\",\"yaxis\",\"zaxis\"];n.prototype.merge=function(t){for(var e=0;e<3;++e){var r=t[a[e]];r.visible?(this.enabled[e]=r.showspikes,this.colors[e]=i(r.spikecolor),this.drawSides[e]=r.spikesides,this.lineWidth[e]=r.spikethickness):(this.enabled[e]=!1,this.drawSides[e]=!1)}},e.exports=function(t){var e=new n;return e.merge(t),e}},{\"../../../lib/str2rgbarray\":765}],840:[function(t,e,r){\"use strict\";e.exports=function(t){for(var e=t.axesOptions,r=t.glplot.axesPixels,l=t.fullSceneLayout,c=[[],[],[]],u=0;u<3;++u){var f=l[o[u]];if(f._length=(r[u].hi-r[u].lo)*r[u].pixelsPerDataUnit/t.dataScale[u],Math.abs(f._length)===1/0)c[u]=[];else{f.range[0]=r[u].lo/t.dataScale[u],f.range[1]=r[u].hi/t.dataScale[u],f._m=1/(t.dataScale[u]*r[u].pixelsPerDataUnit),f.range[0]===f.range[1]&&(f.range[0]-=1,f.range[1]+=1);var h=f.tickmode;if(\"auto\"===f.tickmode){f.tickmode=\"linear\";var d=f.nticks||i.constrain(f._length/40,4,9);n.autoTicks(f,Math.abs(f.range[1]-f.range[0])/d)}for(var p=n.calcTicks(f),m=0;mh[1][s]?d[s]=1:h[1][s]===h[0][s]?d[s]=1:d[s]=1/(h[1][s]-h[0][s]);for(this.dataScale=d,this.convertAnnotations(this),a=0;am[1][a])m[0][a]=-1,m[1][a]=1;else{var T=m[1][a]-m[0][a];m[0][a]-=T/32,m[1][a]+=T/32}}else{var S=l.range;m[0][a]=l.r2l(S[0]),m[1][a]=l.r2l(S[1])}m[0][a]===m[1][a]&&(m[0][a]-=1,m[1][a]+=1),v[a]=m[1][a]-m[0][a],this.glplot.bounds[0][a]=m[0][a]*d[a],this.glplot.bounds[1][a]=m[1][a]*d[a]}var E=[1,1,1];for(a=0;a<3;++a){var L=y[c=(l=u[k[a]]).type];E[a]=Math.pow(L.acc,1/L.count)/d[a]}var C;if(\"auto\"===u.aspectmode)C=Math.max.apply(null,E)/Math.min.apply(null,E)<=4?E:[1,1,1];else if(\"cube\"===u.aspectmode)C=[1,1,1];else if(\"data\"===u.aspectmode)C=E;else{if(\"manual\"!==u.aspectmode)throw new Error(\"scene.js aspectRatio was not one of the enumerated types\");var z=u.aspectratio;C=[z.x,z.y,z.z]}u.aspectratio.x=f.aspectratio.x=C[0],u.aspectratio.y=f.aspectratio.y=C[1],u.aspectratio.z=f.aspectratio.z=C[2],this.glplot.aspect=C;var D=u.domain||null,I=e._size||null;if(D&&I){var P=this.container.style;P.position=\"absolute\",P.left=I.l+D.x[0]*I.w+\"px\",P.top=I.t+(1-D.y[1])*I.h+\"px\",P.width=I.w*(D.x[1]-D.x[0])+\"px\",P.height=I.h*(D.y[1]-D.y[0])+\"px\"}this.glplot.redraw()}},M.destroy=function(){this.glplot&&(this.camera.mouseListener.enabled=!1,this.container.removeEventListener(\"wheel\",this.camera.wheelListener),this.camera=this.glplot.camera=null,this.glplot.dispose(),this.container.parentNode.removeChild(this.container),this.glplot=null)},M.getCamera=function(){return this.glplot.camera.view.recalcMatrix(this.camera.view.lastT()),s(this.glplot.camera)},M.setCamera=function(t){this.glplot.camera.lookAt.apply(this,function(t){return[[t.eye.x,t.eye.y,t.eye.z],[t.center.x,t.center.y,t.center.z],[t.up.x,t.up.y,t.up.z]]}(t))},M.saveCamera=function(t){function e(t,e,r,n){var i=[\"up\",\"center\",\"eye\"],a=[\"x\",\"y\",\"z\"];return e[i[r]]&&t[i[r]][a[n]]===e[i[r]][a[n]]}var r=this.getCamera(),n=d.nestedProperty(t,this.id+\".camera\"),i=n.get(),a=!1;if(void 0===i)a=!0;else for(var o=0;o<3;o++)for(var s=0;s<3;s++)if(!e(r,i,o,s)){a=!0;break}return a&&n.set(r),a},M.updateFx=function(t,e){var r=this.camera;r&&(\"orbit\"===t?(r.mode=\"orbit\",r.keyBindingMode=\"rotate\"):\"turntable\"===t?(r.up=[0,0,1],r.mode=\"turntable\",r.keyBindingMode=\"rotate\"):r.keyBindingMode=t),this.fullSceneLayout.hovermode=e},M.toImage=function(t){t||(t=\"png\"),this.staticMode&&this.container.appendChild(l),this.glplot.redraw();var e=this.glplot.gl,r=e.drawingBufferWidth,n=e.drawingBufferHeight;e.bindFramebuffer(e.FRAMEBUFFER,null);var i=new Uint8Array(r*n*4);e.readPixels(0,0,r,n,e.RGBA,e.UNSIGNED_BYTE,i);for(var a=0,o=n-1;a0}var a=t(\"../../lib\"),o=t(\"./convert_text_opts\"),s=n.prototype;s.update=function(t){this.visible?this.needsNewSource(t)?(this.updateLayer(t),this.updateSource(t)):this.needsNewLayer(t)&&this.updateLayer(t):(this.updateSource(t),this.updateLayer(t)),this.updateStyle(t),this.visible=i(t)},s.needsNewSource=function(t){return this.sourceType!==t.sourcetype||this.source!==t.source||this.layerType!==t.type},s.needsNewLayer=function(t){return this.layerType!==t.type||this.below!==t.below},s.updateSource=function(t){var e=this.map;if(e.getSource(this.idSource)&&e.removeSource(this.idSource),this.sourceType=t.sourcetype,this.source=t.source,i(t)){var r=function(t){var e,r=t.sourcetype,n=t.source,i={type:r};return\"geojson\"===r?e=\"data\":\"vector\"===r&&(e=\"string\"==typeof n?\"url\":\"tiles\"),i[e]=n,i}(t);e.addSource(this.idSource,r)}},s.updateLayer=function(t){var e=this.map;if(e.getLayer(this.idLayer)&&e.removeLayer(this.idLayer),this.layerType=t.type,i(t)){e.addLayer({id:this.idLayer,source:this.idSource,\"source-layer\":t.sourcelayer||\"\",type:t.type},t.below);this.mapbox.setOptions(this.idLayer,\"setLayoutProperty\",{visibility:\"visible\"})}},s.updateStyle=function(t){var e=function(t){var e={},r={};switch(t.type){case\"circle\":a.extendFlat(r,{\"circle-radius\":t.circle.radius,\"circle-color\":t.color,\"circle-opacity\":t.opacity});break;case\"line\":a.extendFlat(r,{\"line-width\":t.line.width,\"line-color\":t.color,\"line-opacity\":t.opacity});break;case\"fill\":a.extendFlat(r,{\"fill-color\":t.color,\"fill-outline-color\":t.fill.outlinecolor,\"fill-opacity\":t.opacity});break;case\"symbol\":var n=t.symbol,i=o(n.textposition,n.iconsize);a.extendFlat(e,{\"icon-image\":n.icon+\"-15\",\"icon-size\":n.iconsize/10,\"text-field\":n.text,\"text-size\":n.textfont.size,\"text-anchor\":i.anchor,\"text-offset\":i.offset}),a.extendFlat(r,{\"icon-color\":t.color,\"text-color\":n.textfont.color,\"text-opacity\":t.opacity})}return{layout:e,paint:r}}(t);i(t)&&(this.mapbox.setOptions(this.idLayer,\"setLayoutProperty\",e.layout),this.mapbox.setOptions(this.idLayer,\"setPaintProperty\",e.paint))},s.dispose=function(){var t=this.map;t.removeLayer(this.idLayer),t.removeSource(this.idSource)},e.exports=function(t,e,r){var i=new n(t,e);return i.update(r),i}},{\"../../lib\":743,\"./convert_text_opts\":845}],848:[function(t,e,r){\"use strict\";var n=t(\"../../lib\"),i=t(\"../../components/color\").defaultLine,a=t(\"../domain_attributes\"),o=t(\"../font_attributes\"),s=t(\"../../traces/scatter/attributes\").textposition,l=t(\"../../plot_api/edit_types\").overrideAll,c=o({});c.family.dflt=\"Open Sans Regular, Arial Unicode MS Regular\",e.exports=l({_arrayAttrRegexps:[n.counterRegex(\"mapbox\",\".layers\",!0)],domain:a({name:\"mapbox\"}),accesstoken:{valType:\"string\",noBlank:!0,strict:!0},style:{valType:\"any\",values:[\"basic\",\"streets\",\"outdoors\",\"light\",\"dark\",\"satellite\",\"satellite-streets\"],dflt:\"basic\"},center:{lon:{valType:\"number\",dflt:0},lat:{valType:\"number\",dflt:0}},zoom:{valType:\"number\",dflt:1},bearing:{valType:\"number\",dflt:0},pitch:{valType:\"number\",dflt:0},layers:{_isLinkedToArray:\"layer\",sourcetype:{valType:\"enumerated\",values:[\"geojson\",\"vector\"],dflt:\"geojson\"},source:{valType:\"any\"},sourcelayer:{valType:\"string\",dflt:\"\"},type:{valType:\"enumerated\",values:[\"circle\",\"line\",\"fill\",\"symbol\"],dflt:\"circle\"},below:{valType:\"string\",dflt:\"\"},color:{valType:\"color\",dflt:i},opacity:{valType:\"number\",min:0,max:1,dflt:1},circle:{radius:{valType:\"number\",dflt:15}},line:{width:{valType:\"number\",dflt:2}},fill:{outlinecolor:{valType:\"color\",dflt:i}},symbol:{icon:{valType:\"string\",dflt:\"marker\"},iconsize:{valType:\"number\",dflt:10},text:{valType:\"string\",dflt:\"\"},textfont:c,textposition:n.extendFlat({},s,{arrayOk:!1})}}},\"plot\",\"from-root\")},{\"../../components/color\":618,\"../../lib\":743,\"../../plot_api/edit_types\":773,\"../../traces/scatter/attributes\":1066,\"../domain_attributes\":815,\"../font_attributes\":816}],849:[function(t,e,r){\"use strict\";function n(t,e,r){r(\"accesstoken\"),r(\"style\"),r(\"center.lon\"),r(\"center.lat\"),r(\"zoom\"),r(\"bearing\"),r(\"pitch\"),function(t,e){function r(t,e){return i.coerce(n,a,o.layers,t,e)}var n,a,s=t.layers||[],l=e.layers=[];for(var c=0;c=e.width-20?(a[\"text-anchor\"]=\"start\",a.x=5):(a[\"text-anchor\"]=\"end\",a.x=e._paper.attr(\"width\")-7),r.attr(a);var o=r.select(\".js-link-to-tool\"),s=r.select(\".js-link-spacer\"),l=r.select(\".js-sourcelinks\");t._context.showSources&&t._context.showSources(t),t._context.showLink&&function(t,e){e.text(\"\");var r=e.append(\"a\").attr({\"xlink:xlink:href\":\"#\",class:\"link--impt link--embedview\",\"font-weight\":\"bold\"}).text(t._context.linkText+\" \"+String.fromCharCode(187));if(t._context.sendData)r.on(\"click\",function(){p.sendDataToCloud(t)});else{var n=window.location.pathname.split(\"/\"),i=window.location.search;r.attr({\"xlink:xlink:show\":\"new\",\"xlink:xlink:href\":\"/\"+n[2].split(\".\")[0]+\"/\"+n[1]+i})}}(t,o),s.text(o.text()&&l.text()?\" - \":\"\")}},p.sendDataToCloud=function(t){t.emit(\"plotly_beforeexport\");var e=window.PLOTLYENV&&window.PLOTLYENV.BASE_URL||\"https://plot.ly\",r=i.select(t).append(\"div\").attr(\"id\",\"hiddenform\").style(\"display\",\"none\"),n=r.append(\"form\").attr({action:e+\"/external\",method:\"post\",target:\"_blank\"});return n.append(\"input\").attr({type:\"text\",name:\"data\"}).node().value=p.graphJson(t,!1,\"keepdata\"),n.node().submit(),r.remove(),t.emit(\"plotly_afterexport\"),!1},p.supplyDefaults=function(t){var e,r=t._fullLayout||{},n=t._fullLayout={},a=t.layout||{},o=t._fullData||[],s=t._fullData=[],h=t.data||[];t._transitionData||p.createTransitionData(t),n._dfltTitle={plot:f(t,\"Click to enter Plot title\"),x:f(t,\"Click to enter X axis title\"),y:f(t,\"Click to enter Y axis title\"),colorbar:f(t,\"Click to enter Colorscale title\"),annotation:f(t,\"new text\")},n._traceWord=f(t,\"trace\");var d=function(t){function e(t){for(var e=!0,r=0;r=0)return!0}return!1},p.cleanPlot=function(t,e,r,n){var i,a,o=n._basePlotModules||[];for(i=0;i0){var c=function(t){var e,r={left:0,right:0,bottom:0,top:0};if(t)for(e in t)t.hasOwnProperty(e)&&(r.left+=t[e].left||0,r.right+=t[e].right||0,r.bottom+=t[e].bottom||0,r.top+=t[e].top||0);return r}(t._boundingBoxMargins),f=c.left+c.right,h=c.bottom+c.top,d=1-2*s,m=r._container&&r._container.node?r._container.node().getBoundingClientRect():{width:r.width,height:r.height};n=Math.round(d*(m.width-f)),i=Math.round(d*(m.height-h))}else{var g=l?window.getComputedStyle(t):{};n=parseFloat(g.width)||r.width,i=parseFloat(g.height)||r.height}var v=p.layoutAttributes.width.min,y=p.layoutAttributes.height.min;n1,b=!e.height&&Math.abs(r.height-i)>1;(b||x)&&(x&&(r.width=n),b&&(r.height=i)),t._initialAutoSize||(t._initialAutoSize={width:n,height:i}),p.sanitizeMargins(r)},p.supplyLayoutModuleDefaults=function(t,e,r,n){var i,a,o,s=l.componentsRegistry,c=e._basePlotModules,u=l.subplotsRegistry.cartesian;for(i in s)(o=s[i]).includeBasePlot&&o.includeBasePlot(t,e);for(c.length||c.push(u),e._has(\"cartesian\")&&u.finalizeSubplots(t,e),a=0;a.5*n.width&&(r.l=r.r=0),r.b+r.t>.5*n.height&&(r.b=r.t=0),n._pushmargin[e]={l:{val:r.x,size:r.l+i},r:{val:r.x,size:r.r+i},b:{val:r.y,size:r.b+i},t:{val:r.y,size:r.t+i}}}else delete n._pushmargin[e];n._replotting||p.doAutoMargin(t)}},p.doAutoMargin=function(t){var e=t._fullLayout;e._size||(e._size={}),e._pushmargin||(e._pushmargin={});var r=e._size,n=JSON.stringify(r),i=Math.max(e.margin.l||0,0),s=Math.max(e.margin.r||0,0),l=Math.max(e.margin.t||0,0),c=Math.max(e.margin.b||0,0),u=e._pushmargin;if(!1!==e.margin.autoexpand){u.base={l:{val:0,size:i},r:{val:1,size:s},t:{val:1,size:l},b:{val:0,size:c}};for(var f in u){var h=u[f].l||{},d=u[f].b||{},p=h.val,m=h.size,g=d.val,v=d.size;for(var y in u){if(a(m)&&u[y].r){var x=u[y].r.val,b=u[y].r.size;if(x>p){var _=(m*x+(b-e.width)*p)/(x-p),w=(b*(1-p)+(m-e.width)*(1-x))/(x-p);_>=0&&w>=0&&_+w>i+s&&(i=_,s=w)}}if(a(v)&&u[y].t){var M=u[y].t.val,k=u[y].t.size;if(M>g){var A=(v*M+(k-e.height)*g)/(M-g),T=(k*(1-g)+(v-e.height)*(1-M))/(M-g);A>=0&&T>=0&&A+T>c+l&&(c=A,l=T)}}}}}if(r.l=Math.round(i),r.r=Math.round(s),r.t=Math.round(l),r.b=Math.round(c),r.p=Math.round(e.margin.pad),r.w=Math.round(e.width)-r.l-r.r,r.h=Math.round(e.height)-r.t-r.b,!e._replotting&&\"{}\"!==n&&n!==JSON.stringify(e._size))return o.plot(t)},p.graphJson=function(t,e,r,n,i){function a(t){if(\"function\"==typeof t)return null;if(u.isPlainObject(t)){var e,n,i={};for(e in t)if(\"function\"!=typeof t[e]&&-1===[\"_\",\"[\"].indexOf(e.charAt(0))){if(\"keepdata\"===r){if(\"src\"===e.substr(e.length-3))continue}else if(\"keepstream\"===r){if(\"string\"==typeof(n=t[e+\"src\"])&&n.indexOf(\":\")>0&&!u.isPlainObject(t.stream))continue}else if(\"keepall\"!==r&&\"string\"==typeof(n=t[e+\"src\"])&&n.indexOf(\":\")>0)continue;i[e]=a(t[e])}return i}return Array.isArray(t)?t.map(a):u.isJSDate(t)?u.ms2DateTimeLocal(+t):t}(i&&e&&!t._fullData||i&&!e&&!t._fullLayout)&&p.supplyDefaults(t);var o=i?t._fullData:t.data,s=i?t._fullLayout:t.layout,l=(t._transitionData||{})._frames,c={data:(o||[]).map(function(t){var r=a(t);return e&&delete r.fit,r})};return e||(c.layout=a(s)),t.framework&&t.framework.isPolar&&(c=t.framework.getConfig()),l&&(c.frames=a(l)),\"object\"===n?c:JSON.stringify(c)},p.modifyFrames=function(t,e){var r,n,i,a=t._transitionData._frames,o=t._transitionData._frameHash;for(r=0;r0&&(t._transitioningWithDuration=!0),t._transitionData._interruptCallbacks.push(function(){d=!0}),i.redraw&&t._transitionData._interruptCallbacks.push(function(){return o.redraw(t)}),t._transitionData._interruptCallbacks.push(function(){t.emit(\"plotly_transitioninterrupted\",[])});var s,l,c=0,f=0,p=t._fullLayout._basePlotModules,m=!1;if(r)for(l=0;l=0;o--)if(_[o].enabled){r._indexToPoints=_[o]._indexToPoints;break}i&&i.calc&&(b=i.calc(t,r))}Array.isArray(b)&&b[0]||(b=[{x:d,y:d}]),b[0].t||(b[0].t={}),b[0].trace=r,p[a]=b}l.getComponentMethod(\"fx\",\"calc\")(t)},p.rehover=function(t){t._fullLayout._rehover&&t._fullLayout._rehover()},p.generalUpdatePerTraceModule=function(t,e,r,n){var i,a=e.traceHash,o={};for(i=0;i=0?h.angularAxis.domain:n.extent(M),E=Math.abs(M[1]-M[0]);A&&!k&&(E=0);var L=S.slice();T&&k&&(L[1]+=E);var C=h.angularAxis.ticksCount||4;C>8&&(C=C/(C/8)+C%8),h.angularAxis.ticksStep&&(C=(L[1]-L[0])/C);var z=h.angularAxis.ticksStep||(L[1]-L[0])/(C*(h.minorTicks+1));w&&(z=Math.max(Math.round(z),1)),L[2]||(L[2]=z);var D=n.range.apply(this,L);if(D=D.map(function(t,e){return parseFloat(t.toPrecision(12))}),s=n.scale.linear().domain(L.slice(0,2)).range(\"clockwise\"===h.direction?[0,360]:[360,0]),u.layout.angularAxis.domain=s.domain(),u.layout.angularAxis.endPadding=T?E:0,void 0===(t=n.select(this).select(\"svg.chart-root\"))||t.empty()){var I=(new DOMParser).parseFromString(\"' + '' + '' + '' + '' + '' + '' + '' + '' + '' + '' + '' + '' + '' + '' + '\",\"application/xml\"),P=this.appendChild(this.ownerDocument.importNode(I.documentElement,!0));t=n.select(P)}t.select(\".guides-group\").style({\"pointer-events\":\"none\"}),t.select(\".angular.axis-group\").style({\"pointer-events\":\"none\"}),t.select(\".radial.axis-group\").style({\"pointer-events\":\"none\"});var O,F=t.select(\".chart-group\"),R={fill:\"none\",stroke:h.tickColor},N={\"font-size\":h.font.size,\"font-family\":h.font.family,fill:h.font.color,\"text-shadow\":[\"-1px 0px\",\"1px -1px\",\"-1px 1px\",\"1px 1px\"].map(function(t,e){return\" \"+t+\" 0 \"+h.font.outlineColor}).join(\",\")};if(h.showLegend){O=t.select(\".legend-group\").attr({transform:\"translate(\"+[x,h.margin.top]+\")\"}).style({display:\"block\"});var j=p.map(function(t,e){var r=o.util.cloneJson(t);return r.symbol=\"DotPlot\"===t.geometry?t.dotType||\"circle\":\"LinePlot\"!=t.geometry?\"square\":\"line\",r.visibleInLegend=void 0===t.visibleInLegend||t.visibleInLegend,r.color=\"LinePlot\"===t.geometry?t.strokeColor:t.color,r});o.Legend().config({data:p.map(function(t,e){return t.name||\"Element\"+e}),legendConfig:i({},o.Legend.defaultConfig().legendConfig,{container:O,elements:j,reverseOrder:h.legend.reverseOrder})})();var B=O.node().getBBox();x=Math.min(h.width-B.width-h.margin.left-h.margin.right,h.height-h.margin.top-h.margin.bottom)/2,x=Math.max(10,x),_=[h.margin.left+x,h.margin.top+x],r.range([0,x]),u.layout.radialAxis.domain=r.domain(),O.attr(\"transform\",\"translate(\"+[_[0]+x,_[1]-x]+\")\")}else O=t.select(\".legend-group\").style({display:\"none\"});t.attr({width:h.width,height:h.height}).style({opacity:h.opacity}),F.attr(\"transform\",\"translate(\"+_+\")\").style({cursor:\"crosshair\"});var U=[(h.width-(h.margin.left+h.margin.right+2*x+(B?B.width:0)))/2,(h.height-(h.margin.top+h.margin.bottom+2*x))/2];if(U[0]=Math.max(0,U[0]),U[1]=Math.max(0,U[1]),t.select(\".outer-group\").attr(\"transform\",\"translate(\"+U+\")\"),h.title){var V=t.select(\"g.title-group text\").style(N).text(h.title),q=V.node().getBBox();V.attr({x:_[0]-q.width/2,y:_[1]-x-20})}var H=t.select(\".radial.axis-group\");if(h.radialAxis.gridLinesVisible){var G=H.selectAll(\"circle.grid-circle\").data(r.ticks(5));G.enter().append(\"circle\").attr({class:\"grid-circle\"}).style(R),G.attr(\"r\",r),G.exit().remove()}H.select(\"circle.outside-circle\").attr({r:x}).style(R);var Y=t.select(\"circle.background-circle\").attr({r:x}).style({fill:h.backgroundColor,stroke:h.stroke});if(h.radialAxis.visible){var W=n.svg.axis().scale(r).ticks(5).tickSize(5);H.call(W).attr({transform:\"rotate(\"+h.radialAxis.orientation+\")\"}),H.selectAll(\".domain\").style(R),H.selectAll(\"g>text\").text(function(t,e){return this.textContent+h.radialAxis.ticksSuffix}).style(N).style({\"text-anchor\":\"start\"}).attr({x:0,y:0,dx:0,dy:0,transform:function(t,e){return\"horizontal\"===h.radialAxis.tickOrientation?\"rotate(\"+-h.radialAxis.orientation+\") translate(\"+[0,N[\"font-size\"]]+\")\":\"translate(\"+[0,N[\"font-size\"]]+\")\"}}),H.selectAll(\"g>line\").style({stroke:\"black\"})}var X=t.select(\".angular.axis-group\").selectAll(\"g.angular-tick\").data(D),Z=X.enter().append(\"g\").classed(\"angular-tick\",!0);X.attr({transform:function(t,e){return\"rotate(\"+c(t)+\")\"}}).style({display:h.angularAxis.visible?\"block\":\"none\"}),X.exit().remove(),Z.append(\"line\").classed(\"grid-line\",!0).classed(\"major\",function(t,e){return e%(h.minorTicks+1)==0}).classed(\"minor\",function(t,e){return!(e%(h.minorTicks+1)==0)}).style(R),Z.selectAll(\".minor\").style({stroke:h.minorTickColor}),X.select(\"line.grid-line\").attr({x1:h.tickLength?x-h.tickLength:0,x2:x}).style({display:h.angularAxis.gridLinesVisible?\"block\":\"none\"}),Z.append(\"text\").classed(\"axis-text\",!0).style(N);var J=X.select(\"text.axis-text\").attr({x:x+h.labelOffset,dy:a+\"em\",transform:function(t,e){var r=c(t),n=x+h.labelOffset,i=h.angularAxis.tickOrientation;return\"horizontal\"==i?\"rotate(\"+-r+\" \"+n+\" 0)\":\"radial\"==i?r<270&&r>90?\"rotate(180 \"+n+\" 0)\":null:\"rotate(\"+(r<=180&&r>0?-90:90)+\" \"+n+\" 0)\"}}).style({\"text-anchor\":\"middle\",display:h.angularAxis.labelsVisible?\"block\":\"none\"}).text(function(t,e){return e%(h.minorTicks+1)!=0?\"\":w?w[t]+h.angularAxis.ticksSuffix:t+h.angularAxis.ticksSuffix}).style(N);h.angularAxis.rewriteTicks&&J.text(function(t,e){return e%(h.minorTicks+1)!=0?\"\":h.angularAxis.rewriteTicks(this.textContent,e)});var K=n.max(F.selectAll(\".angular-tick text\")[0].map(function(t,e){return t.getCTM().e+t.getBBox().width}));O.attr({transform:\"translate(\"+[x+K,h.margin.top]+\")\"});var Q=t.select(\"g.geometry-group\").selectAll(\"g\").size()>0,$=t.select(\"g.geometry-group\").selectAll(\"g.geometry\").data(p);if($.enter().append(\"g\").attr({class:function(t,e){return\"geometry geometry\"+e}}),$.exit().remove(),p[0]||Q){var tt=[];p.forEach(function(t,e){var n={};n.radialScale=r,n.angularScale=s,n.container=$.filter(function(t,r){return r==e}),n.geometry=t.geometry,n.orientation=h.orientation,n.direction=h.direction,n.index=e,tt.push({data:t,geometryConfig:n})});var et=[];n.nest().key(function(t,e){return void 0!==t.data.groupId||\"unstacked\"}).entries(tt).forEach(function(t,e){\"unstacked\"===t.key?et=et.concat(t.values.map(function(t,e){return[t]})):et.push(t.values)}),et.forEach(function(t,e){var r;r=Array.isArray(t)?t[0].geometryConfig.geometry:t.geometryConfig.geometry;var n=t.map(function(t,e){return i(o[r].defaultConfig(),t)});o[r]().config(n)()})}var rt,nt,it=t.select(\".guides-group\"),at=t.select(\".tooltips-group\"),ot=o.tooltipPanel().config({container:at,fontSize:8})(),st=o.tooltipPanel().config({container:at,fontSize:8})(),lt=o.tooltipPanel().config({container:at,hasTick:!0})();if(!k){var ct=it.select(\"line\").attr({x1:0,y1:0,y2:0}).style({stroke:\"grey\",\"pointer-events\":\"none\"});F.on(\"mousemove.angular-guide\",function(t,e){var r=o.util.getMousePos(Y).angle;ct.attr({x2:-x,transform:\"rotate(\"+r+\")\"}).style({opacity:.5});var n=(r+180+360-h.orientation)%360;rt=s.invert(n);var i=o.util.convertToCartesian(x+12,r+180);ot.text(o.util.round(rt)).move([i[0]+_[0],i[1]+_[1]])}).on(\"mouseout.angular-guide\",function(t,e){it.select(\"line\").style({opacity:0})})}var ut=it.select(\"circle\").style({stroke:\"grey\",fill:\"none\"});F.on(\"mousemove.radial-guide\",function(t,e){var n=o.util.getMousePos(Y).radius;ut.attr({r:n}).style({opacity:.5}),nt=r.invert(o.util.getMousePos(Y).radius);var i=o.util.convertToCartesian(n,h.radialAxis.orientation);st.text(o.util.round(nt)).move([i[0]+_[0],i[1]+_[1]])}).on(\"mouseout.radial-guide\",function(t,e){ut.style({opacity:0}),lt.hide(),ot.hide(),st.hide()}),t.selectAll(\".geometry-group .mark\").on(\"mouseover.tooltip\",function(e,r){var i=n.select(this),a=this.style.fill,s=\"black\",l=this.style.opacity||1;if(i.attr({\"data-opacity\":l}),a&&\"none\"!==a){i.attr({\"data-fill\":a}),s=n.hsl(a).darker().toString(),i.style({fill:s,opacity:1});var c={t:o.util.round(e[0]),r:o.util.round(e[1])};k&&(c.t=w[e[0]]);var u=\"t: \"+c.t+\", r: \"+c.r,f=this.getBoundingClientRect(),h=t.node().getBoundingClientRect(),d=[f.left+f.width/2-U[0]-h.left,f.top+f.height/2-U[1]-h.top];lt.config({color:s}).text(u),lt.move(d)}else a=this.style.stroke||\"black\",i.attr({\"data-stroke\":a}),s=n.hsl(a).darker().toString(),i.style({stroke:s,opacity:1})}).on(\"mousemove.tooltip\",function(t,e){if(0!=n.event.which)return!1;n.select(this).attr(\"data-fill\")&<.show()}).on(\"mouseout.tooltip\",function(t,e){lt.hide();var r=n.select(this),i=r.attr(\"data-fill\");i?r.style({fill:i,opacity:r.attr(\"data-opacity\")}):r.style({stroke:r.attr(\"data-stroke\"),opacity:r.attr(\"data-opacity\")})})})}(c),this},h.config=function(t){if(!arguments.length)return l;var e=o.util.cloneJson(t);return e.data.forEach(function(t,e){l.data[e]||(l.data[e]={}),i(l.data[e],o.Axis.defaultConfig().data[0]),i(l.data[e],t)}),i(l.layout,o.Axis.defaultConfig().layout),i(l.layout,e.layout),this},h.getLiveConfig=function(){return u},h.getinputConfig=function(){return c},h.radialScale=function(t){return r},h.angularScale=function(t){return s},h.svg=function(){return t},n.rebind(h,f,\"on\"),h},o.Axis.defaultConfig=function(t,e){return{data:[{t:[1,2,3,4],r:[10,11,12,13],name:\"Line1\",geometry:\"LinePlot\",color:null,strokeDash:\"solid\",strokeColor:null,strokeSize:\"1\",visibleInLegend:!0,opacity:1}],layout:{defaultColorRange:n.scale.category10().range(),title:null,height:450,width:500,margin:{top:40,right:40,bottom:40,left:40},font:{size:12,color:\"gray\",outlineColor:\"white\",family:\"Tahoma, sans-serif\"},direction:\"clockwise\",orientation:0,labelOffset:10,radialAxis:{domain:null,orientation:-45,ticksSuffix:\"\",visible:!0,gridLinesVisible:!0,tickOrientation:\"horizontal\",rewriteTicks:null},angularAxis:{domain:[0,360],ticksSuffix:\"\",visible:!0,gridLinesVisible:!0,labelsVisible:!0,tickOrientation:\"horizontal\",rewriteTicks:null,ticksCount:null,ticksStep:null},minorTicks:0,tickLength:null,tickColor:\"silver\",minorTickColor:\"#eee\",backgroundColor:\"none\",needsEndSpacing:null,showLegend:!0,legend:{reverseOrder:!1},opacity:1}}},o.util={},o.DATAEXTENT=\"dataExtent\",o.AREA=\"AreaChart\",o.LINE=\"LinePlot\",o.DOT=\"DotPlot\",o.BAR=\"BarChart\",o.util._override=function(t,e){for(var r in t)r in e&&(e[r]=t[r])},o.util._extend=function(t,e){for(var r in t)e[r]=t[r]},o.util._rndSnd=function(){return 2*Math.random()-1+(2*Math.random()-1)+(2*Math.random()-1)},o.util.dataFromEquation2=function(t,e){var r=e||6;return n.range(0,360+r,r).map(function(e,r){var n=e*Math.PI/180;return[e,t(n)]})},o.util.dataFromEquation=function(t,e,r){var i=e||6,a=[],o=[];n.range(0,360+i,i).forEach(function(e,r){var n=e*Math.PI/180,i=t(n);a.push(e),o.push(i)});var s={t:a,r:o};return r&&(s.name=r),s},o.util.ensureArray=function(t,e){if(void 0===t)return null;var r=[].concat(t);return n.range(e).map(function(t,e){return r[e]||r[0]})},o.util.fillArrays=function(t,e,r){return e.forEach(function(e,n){t[e]=o.util.ensureArray(t[e],r)}),t},o.util.cloneJson=function(t){return JSON.parse(JSON.stringify(t))},o.util.validateKeys=function(t,e){\"string\"==typeof e&&(e=e.split(\".\"));var r=e.shift();return t[r]&&(!e.length||objHasKeys(t[r],e))},o.util.sumArrays=function(t,e){return n.zip(t,e).map(function(t,e){return n.sum(t)})},o.util.arrayLast=function(t){return t[t.length-1]},o.util.arrayEqual=function(t,e){for(var r=Math.max(t.length,e.length,1);r-- >=0&&t[r]===e[r];);return-2===r},o.util.flattenArray=function(t){for(var e=[];!o.util.arrayEqual(e,t);)e=t,t=[].concat.apply([],t);return t},o.util.deduplicate=function(t){return t.filter(function(t,e,r){return r.indexOf(t)==e})},o.util.convertToCartesian=function(t,e){var r=e*Math.PI/180;return[t*Math.cos(r),t*Math.sin(r)]},o.util.round=function(t,e){var r=e||2,n=Math.pow(10,r);return Math.round(t*n)/n},o.util.getMousePos=function(t){var e=n.mouse(t.node()),r=e[0],i=e[1],a={};return a.x=r,a.y=i,a.pos=e,a.angle=180*(Math.atan2(i,r)+Math.PI)/Math.PI,a.radius=Math.sqrt(r*r+i*i),a},o.util.duplicatesCount=function(t){for(var e,r={},n={},i=0,a=t.length;i0)){var l=n.select(this.parentNode).selectAll(\"path.line\").data([0]);l.enter().insert(\"path\"),l.attr({class:\"line\",d:u(s),transform:function(e,r){return\"rotate(\"+(t.orientation+90)+\")\"},\"pointer-events\":\"none\"}).style({fill:function(t,e){return p.fill(r,i,a)},\"fill-opacity\":0,stroke:function(t,e){return p.stroke(r,i,a)},\"stroke-width\":function(t,e){return p[\"stroke-width\"](r,i,a)},\"stroke-dasharray\":function(t,e){return p[\"stroke-dasharray\"](r,i,a)},opacity:function(t,e){return p.opacity(r,i,a)},display:function(t,e){return p.display(r,i,a)}})}};var f=t.angularScale.range(),h=Math.abs(f[1]-f[0])/o[0].length*Math.PI/180,d=n.svg.arc().startAngle(function(t){return-h/2}).endAngle(function(t){return h/2}).innerRadius(function(e){return t.radialScale(l+(e[2]||0))}).outerRadius(function(e){return t.radialScale(l+(e[2]||0))+t.radialScale(e[1])});c.arc=function(e,r,i){n.select(this).attr({class:\"mark arc\",d:d,transform:function(e,r){return\"rotate(\"+(t.orientation+s(e[0])+90)+\")\"}})};var p={fill:function(t,r,n){return e[n].data.color},stroke:function(t,r,n){return e[n].data.strokeColor},\"stroke-width\":function(t,r,n){return e[n].data.strokeSize+\"px\"},\"stroke-dasharray\":function(t,r,n){return a[e[n].data.strokeDash]},opacity:function(t,r,n){return e[n].data.opacity},display:function(t,r,n){return void 0===e[n].data.visible||e[n].data.visible?\"block\":\"none\"}},m=n.select(this).selectAll(\"g.layer\").data(o);m.enter().append(\"g\").attr({class:\"layer\"});var g=m.selectAll(\"path.mark\").data(function(t,e){return t});g.enter().append(\"path\").attr({class:\"mark\"}),g.style(p).each(c[t.geometryType]),g.exit().remove(),m.exit().remove()})}var e=[o.PolyChart.defaultConfig()],r=n.dispatch(\"hover\"),a={solid:\"none\",dash:[5,2],dot:[2,5]};return t.config=function(t){return arguments.length?(t.forEach(function(t,r){e[r]||(e[r]={}),i(e[r],o.PolyChart.defaultConfig()),i(e[r],t)}),this):e},t.getColorScale=function(){},n.rebind(t,r,\"on\"),t},o.PolyChart.defaultConfig=function(){return{data:{name:\"geom1\",t:[[1,2,3,4]],r:[[1,2,3,4]],dotType:\"circle\",dotSize:64,dotVisible:!1,barWidth:20,color:\"#ffa500\",strokeSize:1,strokeColor:\"silver\",strokeDash:\"solid\",opacity:1,index:0,visible:!0,visibleInLegend:!0},geometryConfig:{geometry:\"LinePlot\",geometryType:\"arc\",direction:\"clockwise\",orientation:0,container:\"body\",radialScale:null,angularScale:null,colorScale:n.scale.category20()}}},o.BarChart=function(){return o.PolyChart()},o.BarChart.defaultConfig=function(){return{geometryConfig:{geometryType:\"bar\"}}},o.AreaChart=function(){return o.PolyChart()},o.AreaChart.defaultConfig=function(){return{geometryConfig:{geometryType:\"arc\"}}},o.DotPlot=function(){return o.PolyChart()},o.DotPlot.defaultConfig=function(){return{geometryConfig:{geometryType:\"dot\",dotType:\"circle\"}}},o.LinePlot=function(){return o.PolyChart()},o.LinePlot.defaultConfig=function(){return{geometryConfig:{geometryType:\"line\"}}},o.Legend=function(){function t(){var r=e.legendConfig,a=e.data.map(function(t,e){return[].concat(t).map(function(t,n){var a=i({},r.elements[e]);return a.name=t,a.color=[].concat(r.elements[e].color)[n],a})}),o=n.merge(a);o=o.filter(function(t,e){return r.elements[e]&&(r.elements[e].visibleInLegend||void 0===r.elements[e].visibleInLegend)}),r.reverseOrder&&(o=o.reverse());var s=r.container;(\"string\"==typeof s||s.nodeName)&&(s=n.select(s));var l=o.map(function(t,e){return t.color}),c=r.fontSize,u=null==r.isContinuous?\"number\"==typeof o[0]:r.isContinuous,f=u?r.height:c*o.length,h=s.classed(\"legend-group\",!0).selectAll(\"svg\").data([0]),d=h.enter().append(\"svg\").attr({width:300,height:f+c,xmlns:\"http://www.w3.org/2000/svg\",\"xmlns:xlink\":\"http://www.w3.org/1999/xlink\",version:\"1.1\"});d.append(\"g\").classed(\"legend-axis\",!0),d.append(\"g\").classed(\"legend-marks\",!0);var p=n.range(o.length),m=n.scale[u?\"linear\":\"ordinal\"]().domain(p).range(l),g=n.scale[u?\"linear\":\"ordinal\"]().domain(p)[u?\"range\":\"rangePoints\"]([0,f]);if(u){var v=h.select(\".legend-marks\").append(\"defs\").append(\"linearGradient\").attr({id:\"grad1\",x1:\"0%\",y1:\"0%\",x2:\"0%\",y2:\"100%\"}).selectAll(\"stop\").data(l);v.enter().append(\"stop\"),v.attr({offset:function(t,e){return e/(l.length-1)*100+\"%\"}}).style({\"stop-color\":function(t,e){return t}}),h.append(\"rect\").classed(\"legend-mark\",!0).attr({height:r.height,width:r.colorBandWidth,fill:\"url(#grad1)\"})}else{var y=h.select(\".legend-marks\").selectAll(\"path.legend-mark\").data(o);y.enter().append(\"path\").classed(\"legend-mark\",!0),y.attr({transform:function(t,e){return\"translate(\"+[c/2,g(e)+c/2]+\")\"},d:function(t,e){return function(t,e){var r=3*e;return\"line\"===t?\"M\"+[[-e/2,-e/12],[e/2,-e/12],[e/2,e/12],[-e/2,e/12]]+\"Z\":-1!=n.svg.symbolTypes.indexOf(t)?n.svg.symbol().type(t).size(r)():n.svg.symbol().type(\"square\").size(r)()}(t.symbol,c)},fill:function(t,e){return m(e)}}),y.exit().remove()}var x=n.svg.axis().scale(g).orient(\"right\"),b=h.select(\"g.legend-axis\").attr({transform:\"translate(\"+[u?r.colorBandWidth:c,c/2]+\")\"}).call(x);return b.selectAll(\".domain\").style({fill:\"none\",stroke:\"none\"}),b.selectAll(\"line\").style({fill:\"none\",stroke:u?r.textColor:\"none\"}),b.selectAll(\"text\").style({fill:r.textColor,\"font-size\":r.fontSize}).text(function(t,e){return o[e].name}),t}var e=o.Legend.defaultConfig(),r=n.dispatch(\"hover\");return t.config=function(t){return arguments.length?(i(e,t),this):e},n.rebind(t,r,\"on\"),t},o.Legend.defaultConfig=function(t,e){return{data:[\"a\",\"b\",\"c\"],legendConfig:{elements:[{symbol:\"line\",color:\"red\"},{symbol:\"square\",color:\"yellow\"},{symbol:\"diamond\",color:\"limegreen\"}],height:150,colorBandWidth:30,fontSize:12,container:\"body\",isContinuous:null,textColor:\"grey\",reverseOrder:!1}}},o.tooltipPanel=function(){var t,e,r,a={container:null,hasTick:!1,fontSize:12,color:\"white\",padding:5},s=\"tooltip-\"+o.tooltipPanel.uid++,l=10,c=function(){var n=(t=a.container.selectAll(\"g.\"+s).data([0])).enter().append(\"g\").classed(s,!0).style({\"pointer-events\":\"none\",display:\"none\"});return r=n.append(\"path\").style({fill:\"white\",\"fill-opacity\":.9}).attr({d:\"M0 0\"}),e=n.append(\"text\").attr({dx:a.padding+l,dy:.3*+a.fontSize}),c};return c.text=function(i){var o=n.hsl(a.color).l,s=o>=.5?\"#aaa\":\"white\",u=o>=.5?\"black\":\"white\",f=i||\"\";e.style({fill:u,\"font-size\":a.fontSize+\"px\"}).text(f);var h=a.padding,d=e.node().getBBox(),p={fill:a.color,stroke:s,\"stroke-width\":\"2px\"},m=d.width+2*h+l,g=d.height+2*h;return r.attr({d:\"M\"+[[l,-g/2],[l,-g/4],[a.hasTick?0:l,0],[l,g/4],[l,g/2],[m,g/2],[m,-g/2]].join(\"L\")+\"Z\"}).style(p),t.attr({transform:\"translate(\"+[l,-g/2+2*h]+\")\"}),t.style({display:\"block\"}),c},c.move=function(e){if(t)return t.attr({transform:\"translate(\"+[e[0],e[1]]+\")\"}).style({display:\"block\"}),c},c.hide=function(){if(t)return t.style({display:\"none\"}),c},c.show=function(){if(t)return t.style({display:\"block\"}),c},c.config=function(t){return i(a,t),c},c},o.tooltipPanel.uid=1,o.adapter={},o.adapter.plotly=function(){var t={};return t.convert=function(t,e){var r={};if(t.data&&(r.data=t.data.map(function(t,r){var n=i({},t);return[[n,[\"marker\",\"color\"],[\"color\"]],[n,[\"marker\",\"opacity\"],[\"opacity\"]],[n,[\"marker\",\"line\",\"color\"],[\"strokeColor\"]],[n,[\"marker\",\"line\",\"dash\"],[\"strokeDash\"]],[n,[\"marker\",\"line\",\"width\"],[\"strokeSize\"]],[n,[\"marker\",\"symbol\"],[\"dotType\"]],[n,[\"marker\",\"size\"],[\"dotSize\"]],[n,[\"marker\",\"barWidth\"],[\"barWidth\"]],[n,[\"line\",\"interpolation\"],[\"lineInterpolation\"]],[n,[\"showlegend\"],[\"visibleInLegend\"]]].forEach(function(t,r){o.util.translator.apply(null,t.concat(e))}),e||delete n.marker,e&&delete n.groupId,e?(\"LinePlot\"===n.geometry?(n.type=\"scatter\",!0===n.dotVisible?(delete n.dotVisible,n.mode=\"lines+markers\"):n.mode=\"lines\"):\"DotPlot\"===n.geometry?(n.type=\"scatter\",n.mode=\"markers\"):\"AreaChart\"===n.geometry?n.type=\"area\":\"BarChart\"===n.geometry&&(n.type=\"bar\"),delete n.geometry):(\"scatter\"===n.type?\"lines\"===n.mode?n.geometry=\"LinePlot\":\"markers\"===n.mode?n.geometry=\"DotPlot\":\"lines+markers\"===n.mode&&(n.geometry=\"LinePlot\",n.dotVisible=!0):\"area\"===n.type?n.geometry=\"AreaChart\":\"bar\"===n.type&&(n.geometry=\"BarChart\"),delete n.mode,delete n.type),n}),!e&&t.layout&&\"stack\"===t.layout.barmode)){var a=o.util.duplicates(r.data.map(function(t,e){return t.geometry}));r.data.forEach(function(t,e){var n=a.indexOf(t.geometry);-1!=n&&(r.data[e].groupId=n)})}if(t.layout){var s=i({},t.layout);if([[s,[\"plot_bgcolor\"],[\"backgroundColor\"]],[s,[\"showlegend\"],[\"showLegend\"]],[s,[\"radialaxis\"],[\"radialAxis\"]],[s,[\"angularaxis\"],[\"angularAxis\"]],[s.angularaxis,[\"showline\"],[\"gridLinesVisible\"]],[s.angularaxis,[\"showticklabels\"],[\"labelsVisible\"]],[s.angularaxis,[\"nticks\"],[\"ticksCount\"]],[s.angularaxis,[\"tickorientation\"],[\"tickOrientation\"]],[s.angularaxis,[\"ticksuffix\"],[\"ticksSuffix\"]],[s.angularaxis,[\"range\"],[\"domain\"]],[s.angularaxis,[\"endpadding\"],[\"endPadding\"]],[s.radialaxis,[\"showline\"],[\"gridLinesVisible\"]],[s.radialaxis,[\"tickorientation\"],[\"tickOrientation\"]],[s.radialaxis,[\"ticksuffix\"],[\"ticksSuffix\"]],[s.radialaxis,[\"range\"],[\"domain\"]],[s.angularAxis,[\"showline\"],[\"gridLinesVisible\"]],[s.angularAxis,[\"showticklabels\"],[\"labelsVisible\"]],[s.angularAxis,[\"nticks\"],[\"ticksCount\"]],[s.angularAxis,[\"tickorientation\"],[\"tickOrientation\"]],[s.angularAxis,[\"ticksuffix\"],[\"ticksSuffix\"]],[s.angularAxis,[\"range\"],[\"domain\"]],[s.angularAxis,[\"endpadding\"],[\"endPadding\"]],[s.radialAxis,[\"showline\"],[\"gridLinesVisible\"]],[s.radialAxis,[\"tickorientation\"],[\"tickOrientation\"]],[s.radialAxis,[\"ticksuffix\"],[\"ticksSuffix\"]],[s.radialAxis,[\"range\"],[\"domain\"]],[s.font,[\"outlinecolor\"],[\"outlineColor\"]],[s.legend,[\"traceorder\"],[\"reverseOrder\"]],[s,[\"labeloffset\"],[\"labelOffset\"]],[s,[\"defaultcolorrange\"],[\"defaultColorRange\"]]].forEach(function(t,r){o.util.translator.apply(null,t.concat(e))}),e?(void 0!==s.tickLength&&(s.angularaxis.ticklen=s.tickLength,delete s.tickLength),s.tickColor&&(s.angularaxis.tickcolor=s.tickColor,delete s.tickColor)):(s.angularAxis&&void 0!==s.angularAxis.ticklen&&(s.tickLength=s.angularAxis.ticklen),s.angularAxis&&void 0!==s.angularAxis.tickcolor&&(s.tickColor=s.angularAxis.tickcolor)),s.legend&&\"boolean\"!=typeof s.legend.reverseOrder&&(s.legend.reverseOrder=\"normal\"!=s.legend.reverseOrder),s.legend&&\"boolean\"==typeof s.legend.traceorder&&(s.legend.traceorder=s.legend.traceorder?\"reversed\":\"normal\",delete s.legend.reverseOrder),s.margin&&void 0!==s.margin.t){var l=[\"t\",\"r\",\"b\",\"l\",\"pad\"],c=[\"top\",\"right\",\"bottom\",\"left\",\"pad\"],u={};n.entries(s.margin).forEach(function(t,e){u[c[l.indexOf(t.key)]]=t.value}),s.margin=u}e&&(delete s.needsEndSpacing,delete s.minorTickColor,delete s.minorTicks,delete s.angularaxis.ticksCount,delete s.angularaxis.ticksCount,delete s.angularaxis.ticksStep,delete s.angularaxis.rewriteTicks,delete s.angularaxis.nticks,delete s.radialaxis.ticksCount,delete s.radialaxis.ticksCount,delete s.radialaxis.ticksStep,delete s.radialaxis.rewriteTicks,delete s.radialaxis.nticks),r.layout=s}return r},t}},{\"../../../constants/alignment\":716,\"../../../lib\":743,d3:128}],862:[function(t,e,r){\"use strict\";var n=t(\"d3\"),i=t(\"../../../lib\"),a=t(\"../../../components/color\"),o=t(\"./micropolar\"),s=t(\"./undo_manager\"),l=i.extendDeepAll,c=e.exports={};c.framework=function(t){function e(e,i){return i&&(f=i),n.select(n.select(f).node().parentNode).selectAll(\".svg-container>*:not(.chart-root)\").remove(),r=r?l(r,e):e,a||(a=o.Axis()),u=o.adapter.plotly().convert(r),a.config(u).render(f),t.data=r.data,t.layout=r.layout,c.fillLayout(t),r}var r,i,a,u,f,h=new s;return e.isPolar=!0,e.svg=function(){return a.svg()},e.getConfig=function(){return r},e.getLiveConfig=function(){return o.adapter.plotly().convert(a.getLiveConfig(),!0)},e.getLiveScales=function(){return{t:a.angularScale(),r:a.radialScale()}},e.setUndoPoint=function(){var t=this,e=o.util.cloneJson(r);!function(e,r){h.add({undo:function(){r&&t(r)},redo:function(){t(e)}})}(e,i),i=o.util.cloneJson(e)},e.undo=function(){h.undo()},e.redo=function(){h.redo()},e},c.fillLayout=function(t){var e=n.select(t).selectAll(\".plot-container\"),r=e.selectAll(\".svg-container\"),i=t.framework&&t.framework.svg&&t.framework.svg(),o={width:800,height:600,paper_bgcolor:a.background,_container:e,_paperdiv:r,_paper:i};t._fullLayout=l(o,t.layout)}},{\"../../../components/color\":618,\"../../../lib\":743,\"./micropolar\":861,\"./undo_manager\":863,d3:128}],863:[function(t,e,r){\"use strict\";e.exports=function(){function t(t,e){return t?(i=!0,t[e](),i=!1,this):this}var e,r=[],n=-1,i=!1;return{add:function(t){return i?this:(r.splice(n+1,r.length-n),r.push(t),n=r.length-1,this)},setCallback:function(t){e=t},undo:function(){var i=r[n];return i?(t(i,\"undo\"),n-=1,e&&e(i.undo),this):this},redo:function(){var i=r[n+1];return i?(t(i,\"redo\"),n+=1,e&&e(i.redo),this):this},clear:function(){r=[],n=-1},hasUndo:function(){return-1!==n},hasRedo:function(){return n0?1:-1}function d(t){return h(Math.cos(t))}function p(t){return h(Math.sin(t))}var m=t(\"d3\"),g=t(\"tinycolor2\"),v=t(\"../../plotly\"),y=t(\"../../registry\"),x=t(\"../../lib\"),b=t(\"../../components/color\"),_=t(\"../../components/drawing\"),w=t(\"../plots\"),M=t(\"../cartesian/axes\"),k=t(\"../../components/dragelement\"),A=t(\"../cartesian/dragbox\"),T=t(\"../../components/fx\"),S=t(\"../../components/titles\"),E=t(\"../cartesian/select\"),L=t(\"../../lib/setcursor\"),C=t(\"../../constants/alignment\").MID_SHIFT,z=x._,D=x.deg2rad,I=x.rad2deg,P=x.wrap360,O=x.wrap180,F=t(\"./helpers\").setConvertAngular,R=t(\"./constants\"),N=n.prototype;e.exports=function(t,e){return new n(t,e)},N.plot=function(t,e){var r=e[this.id];this._hasClipOnAxisFalse=!1;for(var n=0;n=90||s>90&&l>=450?1:u<=0&&h<=0?0:Math.max(u,h),e=s<=180&&l>=180||s>180&&l>=540?-1:c>=0&&f>=0?0:Math.min(c,f),r=s<=270&&l>=270||s>270&&l>=630?-1:u>=0&&h>=0?0:Math.min(u,h),n=l>=360?1:c<=0&&f<=0?0:Math.max(c,f),[e,r,n,i]}(g),y=v[2]-v[0],x=v[3]-v[1],w=m/p,k=Math.abs(x/y);w>k?(l=p,d=(m-(c=p*k))/i.h/2,f=[a[0],a[1]],h=[o[0]+d,o[1]-d]):(c=m,d=(p-(l=m/k))/i.w/2,f=[a[0]+d,a[1]-d],h=[o[0],o[1]]),r.xLength2=l,r.yLength2=c,r.xDomain2=f,r.yDomain2=h;var A=r.xOffset2=i.l+i.w*f[0],T=r.yOffset2=i.t+i.h*(1-h[1]),S=r.radius=l/y,E=r.cx=A-S*v[0],L=r.cy=T+S*v[3],C=r.cxx=E-A,z=r.cyy=L-T;r.updateRadialAxis(t,e),r.updateRadialAxisTitle(t,e),r.updateAngularAxis(t,e);var I=r.radialAxis.range,O=I[1]-I[0],F=r.xaxis={type:\"linear\",_id:\"x\",range:[v[0]*O,v[2]*O],domain:f};M.setConvert(F,t),F.setScale();var R=r.yaxis={type:\"linear\",_id:\"y\",range:[v[1]*O,v[3]*O],domain:h};M.setConvert(R,t),R.setScale(),F.isPtWithinRange=function(t){return r.isPtWithinSector(t)},R.isPtWithinRange=function(){return!0},n.frontplot.attr(\"transform\",u(A,T)).call(_.setClipUrl,r._hasClipOnAxisFalse?null:r.clipIds.circle),n.bgcircle.attr({d:s(S,g),transform:u(E,L)}).call(b.fill,e.bgcolor),r.clipPaths.circle.select(\"path\").attr(\"d\",s(S,g)).attr(\"transform\",u(C,z)),r.framework.selectAll(\".crisp\").classed(\"crisp\",0)},N.updateRadialAxis=function(t,e){var r=this.gd,n=this.layers,s=this.radius,l=this.cx,h=this.cy,d=t._size,p=e.radialaxis,m=e.sector,g=P(m[0]);this.fillViewInitialKey(\"radialaxis.angle\",p.angle);var v=this.radialAxis=x.extendFlat({},p,{_axislayer:n[\"radial-axis\"],_gridlayer:n[\"radial-grid\"],_id:\"x\",_pos:0,side:{counterclockwise:\"top\",clockwise:\"bottom\"}[p.side],domain:[0,s/d.w],anchor:\"free\",position:0,_counteraxis:!0});i(v,p,t),M.doAutoRange(v),p.range=v.range.slice(),p._input.range=v.range.slice(),this.fillViewInitialKey(\"radialaxis.range\",v.range.slice()),\"auto\"===v.tickangle&&g>90&&g<=270&&(v.tickangle=180),v._transfn=function(t){return\"translate(\"+v.l2p(t.x)+\",0)\"},v._gridpath=function(t){return o(v.r2p(t.x),m)};var y=a(p);this.radialTickLayout!==y&&(n[\"radial-axis\"].selectAll(\".xtick\").remove(),this.radialTickLayout=y),M.doTicks(r,v,!0),c(n[\"radial-axis\"],p.showticklabels||p.ticks,{transform:u(l,h)+f(-p.angle)}),c(n[\"radial-grid\"],p.showgrid,{transform:u(l,h)}).selectAll(\"path\").attr(\"transform\",null),c(n[\"radial-line\"].select(\"line\"),p.showline,{x1:0,y1:0,x2:s,y2:0,transform:u(l,h)+f(-p.angle)}).attr(\"stroke-width\",p.linewidth).call(b.stroke,p.linecolor)},N.updateRadialAxisTitle=function(t,e,r){var n=this.gd,i=this.radius,a=this.cx,o=this.cy,s=e.radialaxis,l=this.id+\"title\",c=void 0!==r?r:s.angle,u=D(c),f=Math.cos(u),h=Math.sin(u),d=0;if(s.title){var p=_.bBox(this.layers[\"radial-axis\"].node()).height,m=s.titlefont.size;d=\"counterclockwise\"===s.side?-p-.4*m:p+.8*m}this.layers[\"radial-axis-title\"]=S.draw(n,l,{propContainer:s,propName:this.id+\".radialaxis.title\",placeholder:z(n,\"Click to enter radial axis title\"),attributes:{x:a+i/2*f+d*h,y:o-i/2*h+d*f,\"text-anchor\":\"middle\"},transform:{rotate:-c}})},N.updateAngularAxis=function(t,e){function r(t){return T.c2rad(t.x,\"degrees\")}function n(t){return[v*Math.cos(t),v*Math.sin(t)]}var o=this,h=o.gd,g=o.layers,v=o.radius,y=o.cx,_=o.cy,w=e.angularaxis,k=e.sector,A=k.map(D);o.fillViewInitialKey(\"angularaxis.rotation\",w.rotation);var T=o.angularAxis=x.extendFlat({},w,{_axislayer:g[\"angular-axis\"],_gridlayer:g[\"angular-grid\"],_id:\"angular\",_pos:0,side:\"right\",domain:[0,Math.PI],anchor:\"free\",position:0,_counteraxis:!0});\"linear\"===T.type?(T.autorange=!1,l(k)?T.range=k.slice():T.range=A.map(T.unTransformRad).map(I),\"radians\"===T.thetaunit&&(T.tick0=I(T.tick0),T.dtick=I(T.dtick))):\"category\"===T.type&&(T._tickFilter=function(t){return o.isPtWithinSector({r:o.radialAxis.range[1],rad:T.c2rad(t.x)})}),i(T,w,t),M.doAutoRange(T),T._transfn=function(t){var e=r(t),i=n(e),a=u(y+i[0],_-i[1]),o=m.select(this);return o&&o.node()&&o.classed(\"ticks\")&&(a+=f(-I(e))),a},T._gridpath=function(t){var e=n(r(t));return\"M0,0L\"+-e[0]+\",\"+e[1]};var S=\"outside\"!==w.ticks?.7:.5;T._labelx=function(t){var e=r(t),n=T._labelStandoff,i=T._pad;return(0===p(e)?0:Math.cos(e)*(n+i+S*t.fontSize))+d(e)*(t.dx+n+i)},T._labely=function(t){var e=r(t),n=T._labelStandoff,i=T._labelShift,a=T._pad;return t.dy+t.fontSize*C-i+-Math.sin(e)*(n+a+S*t.fontSize)},T._labelanchor=function(t,e){var n=r(e);return 0===p(n)?d(n)>0?\"start\":\"end\":\"middle\"};var E=a(w);o.angularTickLayout!==E&&(g[\"angular-axis\"].selectAll(\".angulartick\").remove(),o.angularTickLayout=E),M.doTicks(h,T,!0),c(g[\"angular-line\"].select(\"path\"),w.showline,{d:s(v,k),transform:u(y,_)}).attr(\"stroke-width\",w.linewidth).call(b.stroke,w.linecolor)},N.updateFx=function(t,e){this.gd._context.staticPlot||(this.updateAngularDrag(t,e),this.updateRadialDrag(t,e),this.updateMainDrag(t,e))},N.updateMainDrag=function(t,e){function r(t,e){var r=t-w,n=e-M;return Math.sqrt(r*r+n*n)}function n(t,e){return Math.atan2(M-e,t-w)}function i(t,e){return[t*Math.cos(e),t*Math.sin(-e)]}function a(t,e){var r=R.cornerLen,n=R.cornerHalfWidth;if(0===t)return s(2*n,S);var a=r/t/2,o=e-a,l=e+a,c=Math.max(0,Math.min(t,x)),u=c-n,f=c+n;return\"M\"+i(u,o)+\"A\"+[u,u]+\" 0,0,0 \"+i(u,l)+\"L\"+i(f,l)+\"A\"+[f,f]+\" 0,0,1 \"+i(f,o)+\"Z\"}function o(t,e){var i=C+t,o=z+e,l=r(C,z),c=Math.min(r(i,o),x),u=n(C,z),f=n(i,o);lp?(l0!=n>g[0])return;P=h.range[1]=n,M.doTicks(a,i.radialAxis,!0),o[\"radial-grid\"].attr(\"transform\",u(l,c)).selectAll(\"path\").attr(\"transform\",null);var f=P-g[0],d=i.sectorBBox;i.xaxis.range=[d[0]*f,d[2]*f],i.yaxis.range=[d[1]*f,d[3]*f],i.xaxis.setScale(),i.yaxis.setScale();for(var m in i.traceHash){var v=i.traceHash[m],_=x.filterVisible(v),w=v[0][0].trace._module,k=a._fullLayout[i.id];if(w.plot(a,i,_,k),!y.traceIs(m,\"gl\"))for(var A=0;A<_.length;A++)w.style(a,_[A])}})}}function n(){null!==z?v.relayout(a,i.id+\".radialaxis.angle\",z):null!==P&&v.relayout(a,i.id+\".radialaxis.range[1]\",P)}var i=this,a=i.gd,o=i.layers,s=i.radius,l=i.cx,c=i.cy,h=i.radialAxis,d=e.radialaxis,p=D(d.angle),g=h.range.slice(),b=g[1]-g[0],_=R.radialDragBoxSize,w=_/2;if(d.visible){var T=A.makeRectDragger(o,\"radialdrag\",\"crosshair\",-w,-w,_,_),S={element:T,gd:a},E=l+(s+w)*Math.cos(p),L=c-(s+w)*Math.sin(p);m.select(T).attr(\"transform\",u(E,L));var C,z,P;S.prepFn=function(){C=null,z=null,P=null,S.moveFn=r,S.doneFn=n,A.clearSelect(t._zoomlayer)},S.clampFn=function(t,e){return Math.sqrt(t*t+e*e)o&&(o+=360);var s,c,u=P(I(t.rad)),f=u+360;return n[1]>=n[0]?(s=n[0],c=n[1]):(s=n[1],c=n[0]),i>=s&&i<=c&&(l(e)||u>=a&&u<=o||f>=a&&f<=o)},N.fillViewInitialKey=function(t,e){t in this.viewInitial||(this.viewInitial[t]=e)}},{\"../../components/color\":618,\"../../components/dragelement\":640,\"../../components/drawing\":643,\"../../components/fx\":660,\"../../components/titles\":709,\"../../constants/alignment\":716,\"../../lib\":743,\"../../lib/setcursor\":762,\"../../plotly\":784,\"../../registry\":873,\"../cartesian/axes\":789,\"../cartesian/dragbox\":797,\"../cartesian/select\":807,\"../plots\":852,\"./constants\":853,\"./helpers\":854,d3:128,tinycolor2:546}],865:[function(t,e,r){\"use strict\";var n=t(\"../lib\");e.exports=function(t,e,r,i){function a(t,e){return n.coerce(o,s,c,t,e)}for(var o,s,l=i.type,c=i.attributes,u=i.handleDefaults,f=i.partition||\"x\",h=e._subplots[l],d=h.length,p=0;p=o&&(d.min=0,p.min=0,m.min=0,t.aaxis&&delete t.aaxis.min,t.baxis&&delete t.baxis.min,t.caxis&&delete t.caxis.min)}var i=t(\"../../../components/color\"),a=t(\"../../subplot_defaults\"),o=t(\"./layout_attributes\"),s=t(\"./axis_defaults\"),l=[\"aaxis\",\"baxis\",\"caxis\"];e.exports=function(t,e,r){a(t,e,r,{type:\"ternary\",attributes:o,handleDefaults:n,font:e.font,paper_bgcolor:e.paper_bgcolor})}},{\"../../../components/color\":618,\"../../subplot_defaults\":865,\"./axis_defaults\":869,\"./layout_attributes\":871}],871:[function(t,e,r){\"use strict\";var n=t(\"../../../components/color/attributes\"),i=t(\"../../domain_attributes\"),a=t(\"./axis_attributes\"),o=t(\"../../../plot_api/edit_types\").overrideAll;e.exports=o({domain:i({name:\"ternary\"}),bgcolor:{valType:\"color\",dflt:n.background},sum:{valType:\"number\",dflt:1,min:0},aaxis:a,baxis:a,caxis:a},\"plot\",\"from-root\")},{\"../../../components/color/attributes\":617,\"../../../plot_api/edit_types\":773,\"../../domain_attributes\":815,\"./axis_attributes\":868}],872:[function(t,e,r){\"use strict\";function n(t,e){this.id=t.id,this.graphDiv=t.graphDiv,this.init(e),this.makeFramework(e)}function i(t){a.select(t).selectAll(\".zoombox,.js-zoombox-backdrop,.js-zoombox-menu,.zoombox-corners\").remove()}var a=t(\"d3\"),o=t(\"tinycolor2\"),s=t(\"../../plotly\"),l=t(\"../../lib\"),c=l._,u=t(\"../../components/color\"),f=t(\"../../components/drawing\"),h=t(\"../cartesian/set_convert\"),d=t(\"../../lib/extend\").extendFlat,p=t(\"../plots\"),m=t(\"../cartesian/axes\"),g=t(\"../../components/dragelement\"),v=t(\"../../components/fx\"),y=t(\"../../components/titles\"),x=t(\"../cartesian/select\"),b=t(\"../cartesian/constants\");e.exports=n;var _=n.prototype;_.init=function(t){this.container=t._ternarylayer,this.defs=t._defs,this.layoutId=t._uid,this.traceHash={},this.layers={}},_.plot=function(t,e){var r=e[this.id],n=e._size;this._hasClipOnAxisFalse=!1;for(var i=0;iw*x?i=(a=x)*w:a=(i=y)/w,o=g*i/y,s=v*a/x,r=e.l+e.w*p-i/2,n=e.t+e.h*(1-m)-a/2,l.x0=r,l.y0=n,l.w=i,l.h=a,l.sum=b,l.xaxis={type:\"linear\",range:[_+2*k-b,b-_-2*M],domain:[p-o/2,p+o/2],_id:\"x\"},h(l.xaxis,l.graphDiv._fullLayout),l.xaxis.setScale(),l.xaxis.isPtWithinRange=function(t){return t.a>=l.aaxis.range[0]&&t.a<=l.aaxis.range[1]&&t.b>=l.baxis.range[1]&&t.b<=l.baxis.range[0]&&t.c>=l.caxis.range[1]&&t.c<=l.caxis.range[0]},l.yaxis={type:\"linear\",range:[_,b-M-k],domain:[m-s/2,m+s/2],_id:\"y\"},h(l.yaxis,l.graphDiv._fullLayout),l.yaxis.setScale(),l.yaxis.isPtWithinRange=function(){return!0};var A=l.yaxis.domain[0],T=l.aaxis=d({},t.aaxis,{visible:!0,range:[_,b-M-k],side:\"left\",_counterangle:30,tickangle:(+t.aaxis.tickangle||0)-30,domain:[A,A+s*w],_axislayer:l.layers.aaxis,_gridlayer:l.layers.agrid,_pos:0,_id:\"y\",_length:i,_gridpath:\"M0,0l\"+a+\",-\"+i/2});h(T,l.graphDiv._fullLayout),T.setScale();var S=l.baxis=d({},t.baxis,{visible:!0,range:[b-_-k,M],side:\"bottom\",_counterangle:30,domain:l.xaxis.domain,_axislayer:l.layers.baxis,_gridlayer:l.layers.bgrid,_counteraxis:l.aaxis,_pos:0,_id:\"x\",_length:i,_gridpath:\"M0,0l-\"+i/2+\",-\"+a});h(S,l.graphDiv._fullLayout),S.setScale(),T._counteraxis=S;var E=l.caxis=d({},t.caxis,{visible:!0,range:[b-_-M,k],side:\"right\",_counterangle:30,tickangle:(+t.caxis.tickangle||0)+30,domain:[A,A+s*w],_axislayer:l.layers.caxis,_gridlayer:l.layers.cgrid,_counteraxis:l.baxis,_pos:0,_id:\"y\",_length:i,_gridpath:\"M0,0l-\"+a+\",\"+i/2});h(E,l.graphDiv._fullLayout),E.setScale();var L=\"M\"+r+\",\"+(n+a)+\"h\"+i+\"l-\"+i/2+\",-\"+a+\"Z\";l.clipDef.select(\"path\").attr(\"d\",L),l.layers.plotbg.select(\"path\").attr(\"d\",L);var C=\"M0,\"+a+\"h\"+i+\"l-\"+i/2+\",-\"+a+\"Z\";l.clipDefRelative.select(\"path\").attr(\"d\",C);var z=\"translate(\"+r+\",\"+n+\")\";l.plotContainer.selectAll(\".scatterlayer,.maplayer\").attr(\"transform\",z),l.clipDefRelative.select(\"path\").attr(\"transform\",null);var D=\"translate(\"+(r-S._offset)+\",\"+(n+a)+\")\";l.layers.baxis.attr(\"transform\",D),l.layers.bgrid.attr(\"transform\",D);var I=\"translate(\"+(r+i/2)+\",\"+n+\")rotate(30)translate(0,-\"+T._offset+\")\";l.layers.aaxis.attr(\"transform\",I),l.layers.agrid.attr(\"transform\",I);var P=\"translate(\"+(r+i/2)+\",\"+n+\")rotate(-30)translate(0,-\"+E._offset+\")\";l.layers.caxis.attr(\"transform\",P),l.layers.cgrid.attr(\"transform\",P),l.drawAxes(!0),l.plotContainer.selectAll(\".crisp\").classed(\"crisp\",!1),l.layers.aline.select(\"path\").attr(\"d\",T.showline?\"M\"+r+\",\"+(n+a)+\"l\"+i/2+\",-\"+a:\"M0,0\").call(u.stroke,T.linecolor||\"#000\").style(\"stroke-width\",(T.linewidth||0)+\"px\"),l.layers.bline.select(\"path\").attr(\"d\",S.showline?\"M\"+r+\",\"+(n+a)+\"h\"+i:\"M0,0\").call(u.stroke,S.linecolor||\"#000\").style(\"stroke-width\",(S.linewidth||0)+\"px\"),l.layers.cline.select(\"path\").attr(\"d\",E.showline?\"M\"+(r+i/2)+\",\"+n+\"l\"+i/2+\",\"+a:\"M0,0\").call(u.stroke,E.linecolor||\"#000\").style(\"stroke-width\",(E.linewidth||0)+\"px\"),l.graphDiv._context.staticPlot||l.initInteractions(),f.setClipUrl(l.layers.frontplot,l._hasClipOnAxisFalse?null:l.clipId)},_.drawAxes=function(t){var e=this.graphDiv,r=this.id.substr(7)+\"title\",n=this.aaxis,i=this.baxis,a=this.caxis;if(m.doTicks(e,n,!0),m.doTicks(e,i,!0),m.doTicks(e,a,!0),t){var o=Math.max(n.showticklabels?n.tickfont.size/2:0,(a.showticklabels?.75*a.tickfont.size:0)+(\"outside\"===a.ticks?.87*a.ticklen:0));this.layers[\"a-title\"]=y.draw(e,\"a\"+r,{propContainer:n,propName:this.id+\".aaxis.title\",placeholder:c(e,\"Click to enter Component A title\"),attributes:{x:this.x0+this.w/2,y:this.y0-n.titlefont.size/3-o,\"text-anchor\":\"middle\"}});var s=(i.showticklabels?i.tickfont.size:0)+(\"outside\"===i.ticks?i.ticklen:0)+3;this.layers[\"b-title\"]=y.draw(e,\"b\"+r,{propContainer:i,propName:this.id+\".baxis.title\",placeholder:c(e,\"Click to enter Component B title\"),attributes:{x:this.x0-s,y:this.y0+this.h+.83*i.titlefont.size+s,\"text-anchor\":\"middle\"}}),this.layers[\"c-title\"]=y.draw(e,\"c\"+r,{propContainer:a,propName:this.id+\".caxis.title\",placeholder:c(e,\"Click to enter Component C title\"),attributes:{x:this.x0+this.w+s,y:this.y0+this.h+.83*a.titlefont.size+s,\"text-anchor\":\"middle\"}})}};var M=b.MINZOOM/2+.87,k=\"m-0.87,.5h\"+M+\"v3h-\"+(M+5.2)+\"l\"+(M/2+2.6)+\",-\"+(.87*M+4.5)+\"l2.6,1.5l-\"+M/2+\",\"+.87*M+\"Z\",A=\"m0.87,.5h-\"+M+\"v3h\"+(M+5.2)+\"l-\"+(M/2+2.6)+\",-\"+(.87*M+4.5)+\"l-2.6,1.5l\"+M/2+\",\"+.87*M+\"Z\",T=\"m0,1l\"+M/2+\",\"+.87*M+\"l2.6,-1.5l-\"+(M/2+2.6)+\",-\"+(.87*M+4.5)+\"l-\"+(M/2+2.6)+\",\"+(.87*M+4.5)+\"l2.6,1.5l\"+M/2+\",-\"+.87*M+\"Z\",S=\"m0.5,0.5h5v-2h-5v-5h-2v5h-5v2h5v5h2Z\",E=!0;_.initInteractions=function(){function t(t,e){return 1-e/O.h}function e(t,e){return 1-(t+(O.h-e)/Math.sqrt(3))/O.w}function r(t,e){return(t-(O.h-e)/Math.sqrt(3))/O.w}function n(n,i){var a=m+n,o=y+i,s=Math.max(0,Math.min(1,t(0,y),t(0,o))),l=Math.max(0,Math.min(1,e(m,y),e(a,o))),c=Math.max(0,Math.min(1,r(m,y),r(a,o))),u=(s/2+c)*O.w,f=(1-s/2-l)*O.w,h=(u+f)/2,d=f-u,p=(1-s)*O.h,g=p-d/w;d.2?\"rgba(0,0,0,0.4)\":\"rgba(255,255,255,0.3)\").duration(200),P.transition().style(\"opacity\",1).duration(200),D=!0)}function a(){if(i(R),L!==_){var t={};t[O.id+\".aaxis.min\"]=L.a,t[O.id+\".baxis.min\"]=L.b,t[O.id+\".caxis.min\"]=L.c,s.relayout(R,t),E&&R.data&&R._context.showTips&&(l.notifier(c(R,\"Double-click to zoom back out\"),\"long\"),E=!1)}}function h(t,e){var r=t/O.xaxis._m,n=e/O.yaxis._m,i=[(L={a:_.a-n,b:_.b+(r+n)/2,c:_.c-(r-n)/2}).a,L.b,L.c].sort(),a=i.indexOf(L.a),o=i.indexOf(L.b),s=i.indexOf(L.c);i[0]<0&&(i[1]+i[0]/2<0?(i[2]+=i[0]+i[1],i[0]=i[1]=0):(i[2]+=i[0]/2,i[1]+=i[0]/2,i[0]=0),L={a:i[a],b:i[o],c:i[s]},e=(_.a-L.a)*O.yaxis._m,t=(_.c-L.c-_.b+L.b)*O.xaxis._m);var l=\"translate(\"+(O.x0+t)+\",\"+(O.y0+e)+\")\";O.plotContainer.selectAll(\".scatterlayer,.maplayer\").attr(\"transform\",l);var c=\"translate(\"+-t+\",\"+-e+\")\";O.clipDefRelative.select(\"path\").attr(\"transform\",c),O.aaxis.range=[L.a,O.sum-L.b-L.c],O.baxis.range=[O.sum-L.a-L.c,L.b],O.caxis.range=[O.sum-L.a-L.b,L.c],O.drawAxes(!1),O.plotContainer.selectAll(\".crisp\").classed(\"crisp\",!1),O._hasClipOnAxisFalse&&O.plotContainer.select(\".scatterlayer\").selectAll(\".trace\").call(f.hideOutsideRangePoints,O)}function d(){var t={};t[O.id+\".aaxis.min\"]=L.a,t[O.id+\".baxis.min\"]=L.b,t[O.id+\".caxis.min\"]=L.c,s.relayout(R,t)}function p(){N.selectAll(\".select-outline\").remove()}var m,y,_,M,L,C,z,D,I,P,O=this,F=O.layers.plotbg.select(\"path\").node(),R=O.graphDiv,N=R._fullLayout._zoomlayer,j={element:F,gd:R,plotinfo:{xaxis:O.xaxis,yaxis:O.yaxis},subplot:O.id,prepFn:function(t,e,r){j.xaxes=[O.xaxis],j.yaxes=[O.yaxis];var i=R._fullLayout.dragmode;t.shiftKey&&(i=\"pan\"===i?\"zoom\":\"pan\"),j.minDrag=\"lasso\"===i?1:void 0,\"zoom\"===i?(j.moveFn=n,j.doneFn=a,function(t,e,r){var n=F.getBoundingClientRect();m=e-n.left,y=r-n.top,_={a:O.aaxis.range[0],b:O.baxis.range[1],c:O.caxis.range[1]},L=_,M=O.aaxis.range[1]-_.a,C=o(O.graphDiv._fullLayout[O.id].bgcolor).getLuminance(),z=\"M0,\"+O.h+\"L\"+O.w/2+\", 0L\"+O.w+\",\"+O.h+\"Z\",D=!1,I=N.append(\"path\").attr(\"class\",\"zoombox\").attr(\"transform\",\"translate(\"+O.x0+\", \"+O.y0+\")\").style({fill:C>.2?\"rgba(0,0,0,0)\":\"rgba(255,255,255,0)\",\"stroke-width\":0}).attr(\"d\",z),P=N.append(\"path\").attr(\"class\",\"zoombox-corners\").attr(\"transform\",\"translate(\"+O.x0+\", \"+O.y0+\")\").style({fill:u.background,stroke:u.defaultLine,\"stroke-width\":1,opacity:0}).attr(\"d\",\"M0,0Z\"),p()}(0,e,r)):\"pan\"===i?(j.moveFn=h,j.doneFn=d,_={a:O.aaxis.range[0],b:O.baxis.range[1],c:O.caxis.range[1]},L=_,p()):\"select\"!==i&&\"lasso\"!==i||x(t,e,r,j,i)},clickFn:function(t,e){if(i(R),2===t){var r={};r[O.id+\".aaxis.min\"]=0,r[O.id+\".baxis.min\"]=0,r[O.id+\".caxis.min\"]=0,R.emit(\"plotly_doubleclick\",null),s.relayout(R,r)}v.click(R,e,O.id)}};F.onmousemove=function(t){v.hover(R,t,O.id),R._fullLayout._lasthover=F,R._fullLayout._hoversubplot=O.id},F.onmouseout=function(t){R._dragging||g.unhover(R,t)},g.init(j)}},{\"../../components/color\":618,\"../../components/dragelement\":640,\"../../components/drawing\":643,\"../../components/fx\":660,\"../../components/titles\":709,\"../../lib\":743,\"../../lib/extend\":732,\"../../plotly\":784,\"../cartesian/axes\":789,\"../cartesian/constants\":794,\"../cartesian/select\":807,\"../cartesian/set_convert\":808,\"../plots\":852,d3:128,tinycolor2:546}],873:[function(t,e,r){\"use strict\";function n(t){if(t.layoutAttributes){var e=t.layoutAttributes._arrayAttrRegexps;if(e)for(var n=0;n-1}var a=t(\"../lib\"),o=a.extendFlat,s=a.extendDeep;e.exports=function(t,e){t.framework&&t.framework.isPolar&&(t=t.framework.getConfig());var r,a=t.data,l=t.layout,c=s([],a),u=s({},l,n(e.tileClass)),f=t._context||{};if(e.width&&(u.width=e.width),e.height&&(u.height=e.height),\"thumbnail\"===e.tileClass||\"themes__thumb\"===e.tileClass){u.annotations=[];var h=Object.keys(u);for(r=0;r\")?\"\":e.html(t).text()});return e.remove(),r}(w),w=function(t){return t.replace(/&(?!\\w+;|\\#[0-9]+;| \\#x[0-9A-F]+;)/g,\"&\")}(w),w=w.replace(u,\"'\"),i.isIE()&&(w=(w=(w=w.replace(/\"/gi,\"'\")).replace(/(\\('#)([^']*)('\\))/gi,'(\"#$2\")')).replace(/(\\\\')/gi,'\"')),w}},{\"../components/color\":618,\"../components/drawing\":643,\"../constants/xmlns_namespaces\":723,\"../lib\":743,d3:128}],882:[function(t,e,r){\"use strict\";var n=t(\"../../lib\").mergeArray;e.exports=function(t,e){for(var r=0;r0&&E>0&&(S<=F&&E<=R||S<=R&&E<=F||(\"h\"===M?F>=S*(R/E):R>=E*(F/S)))?m=\"inside\":(m=\"outside\",A.remove(),A=null)}else m=\"inside\";if(!A&&(A=d(e,k,\"outside\"===m?z:C),T=p.bBox(A.node()),S=T.width,E=T.height,S<=0||E<=0))A.remove();else{var N;N=\"outside\"===m?function(t,e,r,n,a,o,s){var l,c=\"h\"===o?Math.abs(n-r):Math.abs(e-t);c>2*w&&(l=w);var u=1;s&&(u=\"h\"===o?Math.min(1,c/a.height):Math.min(1,c/a.width));var f,h,d,p,m=(a.left+a.right)/2,g=(a.top+a.bottom)/2;f=u*a.width,h=u*a.height,\"h\"===o?er?(d=(t+e)/2,p=n+l+h/2):(d=(t+e)/2,p=n-l-h/2);return i(m,g,d,p,u,!1)}(l,c,u,f,T,M,\"both\"===g.constraintext||\"outside\"===g.constraintext):function(t,e,r,n,a,o,s){var l,c,u,f,h,d=a.width,p=a.height,m=(a.left+a.right)/2,g=(a.top+a.bottom)/2,v=Math.abs(e-t),y=Math.abs(n-r);v>2*w&&y>2*w?(v-=2*(h=w),y-=2*h):h=0;var x,b;d<=v&&p<=y?(x=!1,b=1):d<=y&&p<=v?(x=!0,b=1):dr?(u=(t+e)/2,f=n-h-c/2):(u=(t+e)/2,f=n+h+c/2);return i(m,g,u,f,b,x)}(l,c,u,f,T,M,\"both\"===g.constraintext||\"inside\"===g.constraintext),A.attr(\"transform\",N)}}}function i(t,e,r,n,i,a){var o;i<1?o=\"scale(\"+i+\") \":(i=1,o=\"\");return\"translate(\"+(r-i*t)+\" \"+(n-i*e)+\")\"+o+(a?\"rotate(\"+a+\" \"+t+\" \"+e+\") \":\"\")}function a(t,e,r,n){var i=o((e=e||{}).family,r),a=o(e.size,r),l=o(e.color,r);return{family:s(t.family,i,n.family),size:function(t,e,r){if(c(e)){e=+e;var n=t.min,i=t.max,a=void 0!==n&&ei;if(!a)return e}return void 0!==r?r:t.dflt}(t.size,a,n.size),color:function(t,e,r){return u(e).isValid()?e:void 0!==r?r:t.dflt}(t.color,l,n.color)}}function o(t,e){var r;return Array.isArray(t)?e.01?f:function(t,e){return Math.abs(t-e)>=2?f(t):t>e?Math.ceil(t):Math.floor(t)};g=A(g,m=A(m,g)),y=A(y,v=A(v,y))}var T=l.select(this);T.append(\"path\").style(\"vector-effect\",\"non-scaling-stroke\").attr(\"d\",\"M\"+m+\",\"+v+\"V\"+y+\"H\"+g+\"V\"+v+\"Z\"),n(t,T,e,s,m,g,v,y)}else l.select(this).remove()})}),s.call(m.plot,e)}},{\"../../components/color\":618,\"../../components/drawing\":643,\"../../components/errorbars\":649,\"../../lib\":743,\"../../lib/svg_text_utils\":766,\"./attributes\":883,d3:128,\"fast-isnumeric\":140,tinycolor2:546}],891:[function(t,e,r){\"use strict\";e.exports=function(t,e){var r,n=t.cd,i=t.xaxis,a=t.yaxis,o=[];if(!1===e)for(r=0;ru+s||!p(l))&&(h=!0,c(f,t))}for(var i=r.traces,a=d(e),o=\"fraction\"===t._fullLayout.barnorm?1:100,s=o/1e9,l=e.l2c(e.c2l(0)),u=\"stack\"===t._fullLayout.barmode?o:l,f=[l,u],h=!1,g=0;g1||0===s.bargap&&0===s.bargroupgap&&!t[0].trace.marker.line.width)&&n.select(this).attr(\"shape-rendering\",\"crispEdges\")}),r.selectAll(\"g.points\").each(function(e){var r=n.select(this),a=r.selectAll(\"path\"),o=r.selectAll(\"text\"),s=e[0].trace;i.pointStyle(a,s,t),i.selectedPointStyle(a,s),o.each(function(t){function e(e){var n=r[e];return Array.isArray(n)?n[t.i]:n}var r,a=n.select(this);a.classed(\"bartext-inside\")?r=s.insidetextfont:a.classed(\"bartext-outside\")&&(r=s.outsidetextfont),r||(r=s.textfont),i.font(a,e(\"family\"),e(\"size\"),e(\"color\"))}),i.selectedTextStyle(o,s)}),a.style(r)}},{\"../../components/drawing\":643,\"../../components/errorbars\":649,d3:128}],895:[function(t,e,r){\"use strict\";var n=t(\"../../components/color\"),i=t(\"../../components/colorscale/has_colorscale\"),a=t(\"../../components/colorscale/defaults\");e.exports=function(t,e,r,o,s){r(\"marker.color\",o),i(t,\"marker\")&&a(t,e,s,r,{prefix:\"marker.\",cLetter:\"c\"}),r(\"marker.line.color\",n.defaultLine),i(t,\"marker.line\")&&a(t,e,s,r,{prefix:\"marker.line.\",cLetter:\"c\"}),r(\"marker.line.width\"),r(\"marker.opacity\"),r(\"selected.marker.color\"),r(\"unselected.marker.color\")}},{\"../../components/color\":618,\"../../components/colorscale/defaults\":628,\"../../components/colorscale/has_colorscale\":632}],896:[function(t,e,r){\"use strict\";var n=t(\"../scatter/attributes\"),i=t(\"../../components/color/attributes\"),a=t(\"../../lib/extend\").extendFlat,o=n.marker,s=o.line;e.exports={y:{valType:\"data_array\",editType:\"calc+clearAxisTypes\"},x:{valType:\"data_array\",editType:\"calc+clearAxisTypes\"},x0:{valType:\"any\",editType:\"calc+clearAxisTypes\"},y0:{valType:\"any\",editType:\"calc+clearAxisTypes\"},name:{valType:\"string\",editType:\"calc+clearAxisTypes\"},text:a({},n.text,{}),whiskerwidth:{valType:\"number\",min:0,max:1,dflt:.5,editType:\"calcIfAutorange\"},boxpoints:{valType:\"enumerated\",values:[\"all\",\"outliers\",\"suspectedoutliers\",!1],dflt:\"outliers\",editType:\"calcIfAutorange\"},boxmean:{valType:\"enumerated\",values:[!0,\"sd\",!1],dflt:!1,editType:\"calcIfAutorange\"},jitter:{valType:\"number\",min:0,max:1,editType:\"calcIfAutorange\"},pointpos:{valType:\"number\",min:-2,max:2,editType:\"calcIfAutorange\"},orientation:{valType:\"enumerated\",values:[\"v\",\"h\"],editType:\"calc+clearAxisTypes\"},marker:{outliercolor:{valType:\"color\",dflt:\"rgba(0, 0, 0, 0)\",editType:\"style\"},symbol:a({},o.symbol,{arrayOk:!1,editType:\"plot\"}),opacity:a({},o.opacity,{arrayOk:!1,dflt:1,editType:\"style\"}),size:a({},o.size,{arrayOk:!1,editType:\"calcIfAutorange\"}),color:a({},o.color,{arrayOk:!1,editType:\"style\"}),line:{color:a({},s.color,{arrayOk:!1,dflt:i.defaultLine,editType:\"style\"}),width:a({},s.width,{arrayOk:!1,dflt:0,editType:\"style\"}),outliercolor:{valType:\"color\",editType:\"style\"},outlierwidth:{valType:\"number\",min:0,dflt:1,editType:\"style\"},editType:\"style\"},editType:\"plot\"},line:{color:{valType:\"color\",editType:\"style\"},width:{valType:\"number\",min:0,dflt:2,editType:\"style\"},editType:\"plot\"},fillcolor:n.fillcolor,selected:{marker:n.selected.marker,editType:\"style\"},unselected:{marker:n.unselected.marker,editType:\"style\"},hoveron:{valType:\"flaglist\",flags:[\"boxes\",\"points\"],dflt:\"boxes+points\",editType:\"style\"}}},{\"../../components/color/attributes\":617,\"../../lib/extend\":732,\"../scatter/attributes\":1066}],897:[function(t,e,r){\"use strict\";function n(t,e){return t.v-e.v}function i(t){return t.v}var a=t(\"fast-isnumeric\"),o=t(\"../../lib\"),s=o._,l=t(\"../../plots/cartesian/axes\");e.exports=function(t,e){var r,c,u,f,h,d=t._fullLayout,p=l.getFromId(t,e.xaxis||\"x\"),m=l.getFromId(t,e.yaxis||\"y\"),g=[],v=\"violin\"===e.type?\"_numViolins\":\"_numBoxes\";\"h\"===e.orientation?(c=p,u=\"x\",f=m,h=\"y\"):(c=m,u=\"y\",f=p,h=\"x\");var y=c.makeCalcdata(e,u),x=function(t,e,r,n,i){if(e in t)return r.makeCalcdata(t,e);var s;s=e+\"0\"in t?t[e+\"0\"]:\"name\"in t&&(\"category\"===r.type||a(t.name)&&-1!==[\"linear\",\"log\"].indexOf(r.type)||o.isDateTime(t.name)&&\"date\"===r.type)?t.name:i;var l=r.d2c(s,0,t[e+\"calendar\"]);return n.map(function(){return l})}(e,h,f,y,d[v]),b=o.distinctVals(x),_=b.vals,w=b.minDiff/2,M=function(t,e){for(var r=t.length,n=new Array(r+1),i=0;i=0&&E0){var C=T[r].sort(n),z=C.map(i),D=z.length,I={pos:_[r],pts:C};I.min=z[0],I.max=z[D-1],I.mean=o.mean(z,D),I.sd=o.stdev(z,D,I.mean),I.q1=o.interp(z,.25),I.med=o.interp(z,.5),I.q3=o.interp(z,.75),I.lf=Math.min(I.q1,z[Math.min(o.findBin(2.5*I.q1-1.5*I.q3,z,!0)+1,D-1)]),I.uf=Math.max(I.q3,z[Math.max(o.findBin(2.5*I.q3-1.5*I.q1,z),0)]),I.lo=4*I.q1-3*I.q3,I.uo=4*I.q3-3*I.q1,g.push(I)}return function(t,e){if(Array.isArray(e.selectedpoints))for(var r=0;r0?(g[0].t={num:d[v],dPos:w,posLetter:h,valLetter:u,labels:{med:s(t,\"median:\"),min:s(t,\"min:\"),q1:s(t,\"q1:\"),q3:s(t,\"q3:\"),max:s(t,\"max:\"),mean:\"sd\"===e.boxmean?s(t,\"mean \\xb1 \\u03c3:\"):s(t,\"mean:\"),lf:s(t,\"lower fence:\"),uf:s(t,\"upper fence:\")}},e._fullInput&&\"candlestick\"===e._fullInput.type&&delete g[0].t.labels,d[v]++,g):[{t:{empty:!0}}]}},{\"../../lib\":743,\"../../plots/cartesian/axes\":789,\"fast-isnumeric\":140}],898:[function(t,e,r){\"use strict\";function n(t,e,r,n){var i,a=r(\"y\"),s=r(\"x\");if(a&&a.length)i=\"v\",s||r(\"x0\");else{if(!s||!s.length)return void(e.visible=!1);i=\"h\",r(\"y0\")}o.getComponentMethod(\"calendars\",\"handleTraceDefaults\")(t,e,[\"x\",\"y\"],n),r(\"orientation\",i)}function i(t,e,r,n){var i=n.prefix,o=a.coerce2(t,e,l,\"marker.outliercolor\"),s=r(\"marker.line.outliercolor\"),c=r(i+\"points\",o||s?\"suspectedoutliers\":void 0);c?(r(\"jitter\",\"all\"===c?.3:0),r(\"pointpos\",\"all\"===c?-1.5:0),r(\"marker.symbol\"),r(\"marker.opacity\"),r(\"marker.size\"),r(\"marker.color\",e.line.color),r(\"marker.line.color\"),r(\"marker.line.width\"),\"suspectedoutliers\"===c&&(r(\"marker.line.outliercolor\",e.marker.color),r(\"marker.line.outlierwidth\")),r(\"selected.marker.color\"),r(\"unselected.marker.color\"),r(\"selected.marker.size\"),r(\"unselected.marker.size\"),r(\"text\")):delete e.marker,r(\"hoveron\"),a.coerceSelectionMarkerOpacity(e,r)}var a=t(\"../../lib\"),o=t(\"../../registry\"),s=t(\"../../components/color\"),l=t(\"./attributes\");e.exports={supplyDefaults:function(t,e,r,o){function c(r,n){return a.coerce(t,e,l,r,n)}n(t,e,c,o),!1!==e.visible&&(c(\"line.color\",(t.marker||{}).color||r),c(\"line.width\"),c(\"fillcolor\",s.addOpacity(e.line.color,.5)),c(\"whiskerwidth\"),c(\"boxmean\"),i(t,e,c,{prefix:\"box\"}))},handleSampleDefaults:n,handlePointsDefaults:i}},{\"../../components/color\":618,\"../../lib\":743,\"../../registry\":873,\"./attributes\":896}],899:[function(t,e,r){\"use strict\";function n(t,e,r,n){var i,c,u,f,h,d,p,m,g,v=t.cd,y=t.xa,x=t.ya,b=v[0].trace,_=v[0].t,w=\"violin\"===b.type,M=[],k=\"closest\"!==n||w?_.bdPos:2.5*_.bdPos,A=function(t){return t.pos+_.bPos-d};w&&\"both\"!==b.side?(\"positive\"===b.side&&(g=function(t){var e=A(t);return s.inbox(e,e+k)}),\"negative\"===b.side&&(g=function(t){var e=A(t);return s.inbox(e-k,e)})):g=function(t){var e=A(t);return s.inbox(e-k,e+k)};var T;T=w?function(t){return s.inbox(t.span[0]-h,t.span[1]-h)}:function(t){return s.inbox(t.min-h,t.max-h)},\"h\"===b.orientation?(h=e,d=r,p=T,m=g,i=\"y\",u=x,c=\"x\",f=y):(h=r,d=e,p=g,m=T,i=\"x\",u=y,c=\"y\",f=x);var S=s.getDistanceFunction(n,p,m);if(s.getClosest(v,S,t),!1===t.index)return[];var E=v[t.index],L=b.line.color,C=(b.marker||{}).color;l.opacity(L)&&b.line.width?t.color=L:l.opacity(C)&&b.boxpoints?t.color=C:t.color=b.fillcolor,t[i+\"0\"]=u.c2p(E.pos+_.bPos-_.bdPos,!0),t[i+\"1\"]=u.c2p(E.pos+_.bPos+_.bdPos,!0),a.tickText(u,u.c2l(E.pos),\"hover\").text,t[i+\"LabelVal\"]=E.pos;var z={},D=[\"med\",\"min\",\"q1\",\"q3\",\"max\"];(b.boxmean||(b.meanline||{}).visible)&&D.push(\"mean\"),(b.boxpoints||b.points)&&D.push(\"lf\",\"uf\");for(var I=0;It.uf}),o=Math.max((t.max-t.min)/10,t.q3-t.q1),c=1e-9*o,u=o*h,m=[],g=0;if(r.jitter){if(0===o)for(g=1,m=new Array(a.length),e=0;et.lo&&(w.so=!0)}return a}).enter().append(\"path\").classed(\"point\",!0).call(c.translatePoints,a,o)}function o(t,e,r,n){var i,a,o=e.pos,c=e.val,u=n.bPos,f=n.bPosPxOffset||0;Array.isArray(n.bdPos)?(i=n.bdPos[0],a=n.bdPos[1]):(i=n.bdPos,a=n.bdPos),t.selectAll(\"path.mean\").data(l.identity).enter().append(\"path\").attr(\"class\",\"mean\").style({fill:\"none\",\"vector-effect\":\"non-scaling-stroke\"}).each(function(t){var e=o.c2p(t.pos+u,!0)+f,n=o.c2p(t.pos+u-i,!0)+f,l=o.c2p(t.pos+u+a,!0)+f,h=c.c2p(t.mean,!0),d=c.c2p(t.mean-t.sd,!0),p=c.c2p(t.mean+t.sd,!0);\"h\"===r.orientation?s.select(this).attr(\"d\",\"M\"+h+\",\"+n+\"V\"+l+(\"sd\"===r.boxmean?\"m0,0L\"+d+\",\"+e+\"L\"+h+\",\"+n+\"L\"+p+\",\"+e+\"Z\":\"\")):s.select(this).attr(\"d\",\"M\"+n+\",\"+h+\"H\"+l+(\"sd\"===r.boxmean?\"m0,0L\"+e+\",\"+d+\"L\"+n+\",\"+h+\"L\"+e+\",\"+p+\"Z\":\"\"))})}var s=t(\"d3\"),l=t(\"../../lib\"),c=t(\"../../components/drawing\"),u=2e9,f=5,h=.01;e.exports={plot:function(t,e,r){var n=t._fullLayout,l=e.xaxis,c=e.yaxis;e.plot.select(\".boxlayer\").selectAll(\"g.trace.boxes\").data(r).enter().append(\"g\").attr(\"class\",\"trace boxes\").each(function(t){var e=t[0],r=e.t,u=e.trace,f=e.node3=s.select(this),h=n._numBoxes,d=\"group\"===n.boxmode&&h>1,p=r.dPos*(1-n.boxgap)*(1-n.boxgroupgap)/(d?h:1),m=d?2*r.dPos*((r.num+.5)/h-.5)*(1-n.boxgap):0,g=p*u.whiskerwidth;if(!0!==u.visible||r.empty)s.select(this).remove();else{var v,y;\"h\"===u.orientation?(v=c,y=l):(v=l,y=c),r.bPos=m,r.bdPos=p,r.wdPos=g,i(f,{pos:v,val:y},u,r),u.boxpoints&&a(f,{x:l,y:c},u,r),u.boxmean&&o(f,{pos:v,val:y},u,r)}})},plotBoxAndWhiskers:i,plotPoints:a,plotBoxMean:o}},{\"../../components/drawing\":643,\"../../lib\":743,d3:128}],904:[function(t,e,r){\"use strict\";e.exports=function(t,e){var r,n,i=t.cd,a=t.xaxis,o=t.yaxis,s=[];if(!1===e)for(r=0;r=10)return null;for(var r=1/0,i=-1/0,a=t.length,o=0;o0?Math.floor:Math.ceil,z=E>0?Math.ceil:Math.floor,D=E>0?Math.min:Math.max,I=E>0?Math.max:Math.min,P=C(T+L),O=z(S-L),F=[[u=A(T)]];for(i=P;i*E=0;i--)a[u-i]=t[f][i],o[u-i]=e[f][i];for(s.push({x:a,y:o,bicubic:l}),i=f,a=[],o=[];i>=0;i--)a[f-i]=t[i][0],o[f-i]=e[i][0];return s.push({x:a,y:o,bicubic:c}),s}},{}],919:[function(t,e,r){\"use strict\";var n=t(\"../../plots/cartesian/axes\"),i=t(\"../../lib/extend\").extendFlat;e.exports=function(t,e,r,a){function o(e){var n,i,o,s,l,c,u,f,h,d,p,g,v=[],y=[],x={};if(\"b\"===r)for(i=t.b2j(e),o=Math.floor(Math.max(0,Math.min(P-2,i))),s=i-o,x.length=P,x.crossLength=I,x.xy=function(e){return t.evalxy([],e,i)},x.dxy=function(e,r){return t.dxydi([],e,o,r,s)},n=0;n0&&(h=t.dxydi([],n-1,o,0,s),v.push(l[0]+h[0]/3),y.push(l[1]+h[1]/3),d=t.dxydi([],n-1,o,1,s),v.push(f[0]-d[0]/3),y.push(f[1]-d[1]/3)),v.push(f[0]),y.push(f[1]),l=f;else for(n=t.a2i(e),c=Math.floor(Math.max(0,Math.min(I-2,n))),u=n-c,x.length=I,x.crossLength=P,x.xy=function(e){return t.evalxy([],n,e)},x.dxy=function(e,r){return t.dxydj([],c,e,u,r)},i=0;i0&&(p=t.dxydj([],c,i-1,u,0),v.push(l[0]+p[0]/3),y.push(l[1]+p[1]/3),g=t.dxydj([],c,i-1,u,1),v.push(f[0]-g[0]/3),y.push(f[1]-g[1]/3)),v.push(f[0]),y.push(f[1]),l=f;return x.axisLetter=r,x.axis=M,x.crossAxis=E,x.value=e,x.constvar=a,x.index=m,x.x=v,x.y=y,x.smoothing=E.smoothing,x}function s(e){var n,i,o,s,l,c=[],u=[],f={};if(f.length=w.length,f.crossLength=S.length,\"b\"===r)for(o=Math.max(0,Math.min(P-2,e)),l=Math.min(1,Math.max(0,e-o)),f.xy=function(r){return t.evalxy([],r,e)},f.dxy=function(e,r){return t.dxydi([],e,o,r,l)},n=0;nw.length-1||k.push(i(s(c),{color:M.gridcolor,width:M.gridwidth}));for(m=d;mw.length-1||y<0||y>w.length-1))for(x=w[u],b=w[y],l=0;lw[w.length-1]||A.push(i(o(v),{color:M.minorgridcolor,width:M.minorgridwidth}));M.startline&&T.push(i(s(0),{color:M.startlinecolor,width:M.startlinewidth})),M.endline&&T.push(i(s(w.length-1),{color:M.endlinecolor,width:M.endlinewidth}))}else{for(f=5e-15,d=(h=[Math.floor((w[w.length-1]-M.tick0)/M.dtick*(1+f)),Math.ceil((w[0]-M.tick0)/M.dtick/(1+f))].sort(function(t,e){return t-e}))[0],p=h[1],m=d;m<=p;m++)g=M.tick0+M.dtick*m,k.push(i(o(g),{color:M.gridcolor,width:M.gridwidth}));for(m=d-1;mw[w.length-1]||A.push(i(o(v),{color:M.minorgridcolor,width:M.minorgridwidth}));M.startline&&T.push(i(o(w[0]),{color:M.startlinecolor,width:M.startlinewidth})),M.endline&&T.push(i(o(w[w.length-1]),{color:M.endlinecolor,width:M.endlinewidth}))}}},{\"../../lib/extend\":732,\"../../plots/cartesian/axes\":789}],920:[function(t,e,r){\"use strict\";var n=t(\"../../plots/cartesian/axes\"),i=t(\"../../lib/extend\").extendFlat;e.exports=function(t,e){var r,a,o,s=e._labels=[],l=e._gridlines;for(r=0;re.length&&(t=t.slice(0,e.length)):t=[],n=0;ne.length&&(t=t.slice(0,e.length)):t=[],n=0;ne.length&&(t[n]=t[n].slice(0,e.length)):t[n]=[],i=0;i90&&(d-=180,l=-l),{angle:d,flip:l,p:t.c2p(n,e,r),offsetMultplier:c}}},{}],936:[function(t,e,r){\"use strict\";function n(t,e,r){var n=t.selectAll(e+\".\"+r).data([0]);return n.enter().append(e).classed(r,!0),n}function i(t,e,r){var i=r[0],l=r[0].trace,c=e.xaxis,d=e.yaxis,m=l.aaxis,g=l.baxis,v=t._fullLayout,y=e.plot.selectAll(\".carpetlayer\"),x=v._clips,b=n(y,\"g\",\"carpet\"+l.uid).classed(\"trace\",!0),_=n(b,\"g\",\"minorlayer\"),w=n(b,\"g\",\"majorlayer\"),M=n(b,\"g\",\"boundarylayer\"),k=n(b,\"g\",\"labellayer\");b.style(\"opacity\",l.opacity),a(c,d,w,m,\"a\",m._gridlines),a(c,d,w,g,\"b\",g._gridlines),a(c,d,_,m,\"a\",m._minorgridlines),a(c,d,_,g,\"b\",g._minorgridlines),a(c,d,M,m,\"a-boundary\",m._boundarylines),a(c,d,M,g,\"b-boundary\",g._boundarylines);!function(t,e,r,n,i,a,o,l){var c,u,f,d;c=.5*(r.a[0]+r.a[r.a.length-1]),u=r.b[0],f=r.ab2xy(c,u,!0),d=r.dxyda_rough(c,u),void 0===o.angle&&p.extendFlat(o,h(r,i,a,f,r.dxydb_rough(c,u)));s(t,e,r,n,f,d,r.aaxis,i,a,o,\"a-title\"),c=r.a[0],u=.5*(r.b[0]+r.b[r.b.length-1]),f=r.ab2xy(c,u,!0),d=r.dxydb_rough(c,u),void 0===l.angle&&p.extendFlat(l,h(r,i,a,f,r.dxyda_rough(c,u)));s(t,e,r,n,f,d,r.baxis,i,a,l,\"b-title\")}(t,k,l,i,c,d,o(t,c,d,l,i,k,m._labels,\"a-label\"),o(t,c,d,l,i,k,g._labels,\"b-label\")),function(t,e,r,i,a){var o,s,l,c,h=r.select(\"#\"+t._clipPathId);h.size()||(h=r.append(\"clipPath\").classed(\"carpetclip\",!0));var d=n(h,\"path\",\"carpetboundary\"),p=e.clipsegments,m=[];for(c=0;c0?\"start\":\"end\",\"data-notex\":1}).call(c.font,i.font).text(i.text).call(d.convertToTspans,t),g=c.bBox(this);m.attr(\"transform\",\"translate(\"+o.p[0]+\",\"+o.p[1]+\") rotate(\"+o.angle+\")translate(\"+i.axis.labelpadding*u+\",\"+.3*g.height+\")\"),f=Math.max(f,g.width+i.axis.labelpadding)}),u.exit().remove(),p.maxExtent=f,p}function s(t,e,r,n,i,a,o,s,u,f,p){var m=[];o.title&&m.push(o.title);var y=e.selectAll(\"text.\"+p).data(m),x=f.maxExtent;y.enter().append(\"text\").classed(p,!0),y.each(function(){var e=h(r,s,u,i,a);-1===[\"start\",\"both\"].indexOf(o.showticklabels)&&(x=0);var n=o.titlefont.size;x+=n+o.titleoffset;var p=(f.angle+(f.flip<0?180:0)-e.angle+450)%360,m=p>90&&p<270,y=l.select(this);y.text(o.title||\"\").call(d.convertToTspans,t),m&&(x=(-d.lineCount(y)+v)*g*n-x),y.attr(\"transform\",\"translate(\"+e.p[0]+\",\"+e.p[1]+\") rotate(\"+e.angle+\") translate(0,\"+x+\")\").classed(\"user-select-none\",!0).attr(\"text-anchor\",\"middle\").call(c.font,o.titlefont)}),y.exit().remove()}var l=t(\"d3\"),c=t(\"../../components/drawing\"),u=t(\"./map_1d_array\"),f=t(\"./makepath\"),h=t(\"./orient_text\"),d=t(\"../../lib/svg_text_utils\"),p=t(\"../../lib\"),m=t(\"../../constants/alignment\");e.exports=function(t,e,r){for(var n=0;nd&&tm&&ep||eg},f.c2p=function(t){return t},h.c2p=function(t){return t},t.setScale=function(){var e=t.x,r=t.y,n=a(t.xctrl,t.yctrl,e,r,f.smoothing,h.smoothing);t.xctrl=n[0],t.yctrl=n[1],t.evalxy=o([t.xctrl,t.yctrl],c,u,f.smoothing,h.smoothing),t.dxydi=s([t.xctrl,t.yctrl],f.smoothing,h.smoothing),t.dxydj=l([t.xctrl,t.yctrl],f.smoothing,h.smoothing)},t.i2a=function(t){var r=Math.max(0,Math.floor(t[0]),c-2),n=t[0]-r;return(1-n)*e[r]+n*e[r+1]},t.j2b=function(t){var e=Math.max(0,Math.floor(t[1]),c-2),n=t[1]-e;return(1-n)*r[e]+n*r[e+1]},t.ij2ab=function(e){return[t.i2a(e[0]),t.j2b(e[1])]},t.a2i=function(t){var r=Math.max(0,Math.min(i(t,e),c-2)),n=e[r],a=e[r+1];return Math.max(0,Math.min(c-1,r+(t-n)/(a-n)))},t.b2j=function(t){var e=Math.max(0,Math.min(i(t,r),u-2)),n=r[e],a=r[e+1];return Math.max(0,Math.min(u-1,e+(t-n)/(a-n)))},t.ab2ij=function(e){return[t.a2i(e[0]),t.b2j(e[1])]},t.i2c=function(e,r){return t.evalxy([],e,r)},t.ab2xy=function(n,i,a){if(!a&&(ne[c-1]|ir[u-1]))return[!1,!1];var o=t.a2i(n),s=t.b2j(i),l=t.evalxy([],o,s);if(a){var f,h,d,p,m=0,g=0,v=[];ne[c-1]?(f=c-2,h=1,m=(n-e[c-1])/(e[c-1]-e[c-2])):h=o-(f=Math.max(0,Math.min(c-2,Math.floor(o)))),ir[u-1]?(d=u-2,p=1,g=(i-r[u-1])/(r[u-1]-r[u-2])):p=s-(d=Math.max(0,Math.min(u-2,Math.floor(s)))),m&&(t.dxydi(v,f,d,h,p),l[0]+=v[0]*m,l[1]+=v[1]*m),g&&(t.dxydj(v,f,d,h,p),l[0]+=v[0]*g,l[1]+=v[1]*g)}return l},t.c2p=function(t,e,r){return[e.c2p(t[0]),r.c2p(t[1])]},t.p2x=function(t,e,r){return[e.p2c(t[0]),r.p2c(t[1])]},t.dadi=function(t){var r=Math.max(0,Math.min(e.length-2,t));return e[r+1]-e[r]},t.dbdj=function(t){var e=Math.max(0,Math.min(r.length-2,t));return r[e+1]-r[e]},t.dxyda=function(e,r,n,i){var a=t.dxydi(null,e,r,n,i),o=t.dadi(e,n);return[a[0]/o,a[1]/o]},t.dxydb=function(e,r,n,i){var a=t.dxydj(null,e,r,n,i),o=t.dbdj(r,i);return[a[0]/o,a[1]/o]},t.dxyda_rough=function(e,r,n){var i=v*(n||.1),a=t.ab2xy(e+i,r,!0),o=t.ab2xy(e-i,r,!0);return[.5*(a[0]-o[0])/i,.5*(a[1]-o[1])/i]},t.dxydb_rough=function(e,r,n){var i=y*(n||.1),a=t.ab2xy(e,r+i,!0),o=t.ab2xy(e,r-i,!0);return[.5*(a[0]-o[0])/i,.5*(a[1]-o[1])/i]},t.dpdx=function(t){return t._m},t.dpdy=function(t){return t._m}}},{\"../../lib/search\":761,\"./compute_control_points\":923,\"./constants\":924,\"./create_i_derivative_evaluator\":925,\"./create_j_derivative_evaluator\":926,\"./create_spline_evaluator\":927}],938:[function(t,e,r){\"use strict\";var n=t(\"../../lib\");e.exports=function(t,e,r){function i(e,r){var n,i=0,a=0;return e>0&&void 0!==(n=t[r][e-1])&&(a++,i+=n),e0&&void 0!==(n=t[r-1][e])&&(a++,i+=n),r0&&o0&&a1e-5);return n.log(\"Smoother converged to\",k,\"after\",A,\"iterations\"),t}},{\"../../lib\":743}],939:[function(t,e,r){\"use strict\";var n=t(\"./has_columns\"),i=t(\"../heatmap/convert_column_xyz\");e.exports=function(t,e,r){var a=[],o=r(\"x\");o&&!n(o)&&a.push(\"x\"),e._cheater=!o;var s=r(\"y\");if(s&&!n(s)&&a.push(\"y\"),o||s)return a.length&&i(e,e.aaxis,e.baxis,\"a\",\"b\",a),!0}},{\"../heatmap/convert_column_xyz\":981,\"./has_columns\":929}],940:[function(t,e,r){\"use strict\";var n=t(\"../scattergeo/attributes\"),i=t(\"../../components/colorscale/attributes\"),a=t(\"../../components/colorbar/attributes\"),o=t(\"../../plots/attributes\"),s=t(\"../../lib/extend\"),l=s.extendFlat,c=s.extendDeepAll,u=n.marker.line;e.exports=l({locations:{valType:\"data_array\",editType:\"calc\"},locationmode:n.locationmode,z:{valType:\"data_array\",editType:\"calc\"},text:l({},n.text,{}),marker:{line:{color:u.color,width:l({},u.width,{dflt:1}),editType:\"calc\"},opacity:{valType:\"number\",arrayOk:!0,min:0,max:1,dflt:1,editType:\"style\"},editType:\"calc\"},selected:{marker:{opacity:n.selected.marker.opacity,editType:\"plot\"},editType:\"plot\"},unselected:{marker:{opacity:n.unselected.marker.opacity,editType:\"plot\"},editType:\"plot\"},hoverinfo:l({},o.hoverinfo,{editType:\"calc\",flags:[\"location\",\"z\",\"text\",\"name\"]})},c({},i,{zmax:{editType:\"calc\"},zmin:{editType:\"calc\"}}),{colorbar:a})},{\"../../components/colorbar/attributes\":619,\"../../components/colorscale/attributes\":624,\"../../lib/extend\":732,\"../../plots/attributes\":787,\"../scattergeo/attributes\":1104}],941:[function(t,e,r){\"use strict\";var n=t(\"fast-isnumeric\"),i=t(\"../../constants/numerical\").BADNUM,a=t(\"../../components/colorscale/calc\"),o=t(\"../scatter/arrays_to_calcdata\"),s=t(\"../scatter/calc_selection\");e.exports=function(t,e){for(var r=e.locations.length,l=new Array(r),c=0;cl&&(e.z=u.slice(0,l)),s(\"locationmode\"),s(\"text\"),s(\"marker.line.color\"),s(\"marker.line.width\"),s(\"marker.opacity\"),i(t,e,o,s,{prefix:\"\",cLetter:\"z\"}),n.coerceSelectionMarkerOpacity(e,s)):e.visible=!1}else e.visible=!1}},{\"../../components/colorscale/defaults\":628,\"../../lib\":743,\"./attributes\":940}],943:[function(t,e,r){\"use strict\";e.exports=function(t,e){return t.location=e.location,t.z=e.z,t}},{}],944:[function(t,e,r){\"use strict\";var n=t(\"../../plots/cartesian/axes\"),i=t(\"./attributes\"),a=t(\"../scatter/fill_hover_text\");e.exports=function(t,e,r){var o,s,l,c,u=t.cd,f=u[0].trace,h=t.subplot;for(s=0;s\")}(t,f,o,h.mockAxis),[t]}},{\"../../plots/cartesian/axes\":789,\"../scatter/fill_hover_text\":1074,\"./attributes\":940}],945:[function(t,e,r){\"use strict\";var n={};n.attributes=t(\"./attributes\"),n.supplyDefaults=t(\"./defaults\"),n.colorbar=t(\"../heatmap/colorbar\"),n.calc=t(\"./calc\"),n.plot=t(\"./plot\"),n.style=t(\"./style\"),n.hoverPoints=t(\"./hover\"),n.eventData=t(\"./event_data\"),n.selectPoints=t(\"./select\"),n.moduleType=\"trace\",n.name=\"choropleth\",n.basePlotModule=t(\"../../plots/geo\"),n.categories=[\"geo\",\"noOpacity\"],n.meta={},e.exports=n},{\"../../plots/geo\":820,\"../heatmap/colorbar\":980,\"./attributes\":940,\"./calc\":941,\"./defaults\":942,\"./event_data\":943,\"./hover\":944,\"./plot\":946,\"./select\":947,\"./style\":948}],946:[function(t,e,r){\"use strict\";function n(t,e){for(var r=t[0].trace,n=t.length,i=s(r,e),a=0;a0&&t[e+1][0]<0)return e;return null}var r,n,i,a,s=t.geometry,l=s.coordinates,c=t.id,u=[];r=\"RUS\"===c||\"FJI\"===c?function(t){var r;if(null===e(t))r=t;else for(r=new Array(t.length),a=0;ar?n[i++]=[t[a][0]+360,t[a][1]]:a===r?(n[i++]=t[a],n[i++]=[t[a][0],-90]):n[i++]=t[a];var s=o.tester(n);s.pts.pop(),u.push(s)}:function(t){u.push(o.tester(t))};switch(s.type){case\"MultiPolygon\":for(n=0;ns.end&&(s.start=s.end=(s.start+s.end)/2),e._input.contours||(e._input.contours={}),a(e._input.contours,{start:s.start,end:s.end,size:s.size}),e._input.autocontour=!0}else{var c=s.start,u=s.end,f=e._input.contours;if(c>u&&(s.start=f.start=u,u=s.end=f.end=c,c=s.start),!(s.size>0)){var h;h=c===u?1:n(c,u,e.ncontours).dtick,f.size=s.size=h}}return r}},{\"../../lib\":743,\"../../plots/cartesian/axes\":789,\"../heatmap/calc\":978}],951:[function(t,e,r){\"use strict\";var n=t(\"../../plots/plots\"),i=t(\"../../components/colorbar/draw\"),a=t(\"./make_color_map\"),o=t(\"./end_plus\");e.exports=function(t,e){var r=e[0].trace,s=\"cb\"+r.uid;if(t._fullLayout._infolayer.selectAll(\".\"+s).remove(),r.showscale){var l=i(t,s);e[0].t.cb=l;var c=r.contours,u=r.line,f=c.size||1,h=c.coloring,d=a(r,{isColorbar:!0});\"heatmap\"===h&&l.filllevels({start:r.zmin,end:r.zmax,size:(r.zmax-r.zmin)/254}),l.fillcolor(\"fill\"===h||\"heatmap\"===h?d:\"\").line({color:\"lines\"===h?d:u.color,width:!1!==c.showlines?u.width:0,dash:u.dash}).levels({start:c.start,end:o(c),size:f}).options(r.colorbar)()}else n.autoMargin(t,s)}},{\"../../components/colorbar/draw\":622,\"../../plots/plots\":852,\"./end_plus\":955,\"./make_color_map\":959}],952:[function(t,e,r){\"use strict\";e.exports={BOTTOMSTART:[1,9,13,104,713],TOPSTART:[4,6,7,104,713],LEFTSTART:[8,12,14,208,1114],RIGHTSTART:[2,3,11,208,1114],NEWDELTA:[null,[-1,0],[0,-1],[-1,0],[1,0],null,[0,-1],[-1,0],[0,1],[0,1],null,[0,1],[1,0],[1,0],[0,-1]],CHOOSESADDLE:{104:[4,1],208:[2,8],713:[7,13],1114:[11,14]},SADDLEREMAINDER:{1:4,2:8,4:1,7:13,8:2,11:14,13:7,14:11},LABELDISTANCE:2,LABELINCREASE:10,LABELMIN:3,LABELMAX:10,LABELOPTIMIZER:{EDGECOST:1,ANGLECOST:1,NEIGHBORCOST:5,SAMELEVELFACTOR:10,SAMELEVELDISTANCE:5,MAXCOST:100,INITIALSEARCHPOINTS:10,ITERATIONS:5}}},{}],953:[function(t,e,r){\"use strict\";var n=t(\"../../lib\"),i=t(\"./attributes\");e.exports=function(t,e,r){var a=n.coerce2(t,e,i,\"contours.start\"),o=n.coerce2(t,e,i,\"contours.end\"),s=!1===a||!1===o,l=r(\"contours.size\");!(s?e.autocontour=!0:r(\"autocontour\",!1))&&l||r(\"ncontours\")}},{\"../../lib\":743,\"./attributes\":949}],954:[function(t,e,r){\"use strict\";var n=t(\"../../lib\"),i=t(\"../heatmap/has_columns\"),a=t(\"../heatmap/xyz_defaults\"),o=t(\"./contours_defaults\"),s=t(\"./style_defaults\"),l=t(\"./attributes\");e.exports=function(t,e,r,c){function u(r,i){return n.coerce(t,e,l,r,i)}a(t,e,u,c)?(u(\"text\"),u(\"connectgaps\",i(e)),o(t,e,u),s(t,e,u,c)):e.visible=!1}},{\"../../lib\":743,\"../heatmap/has_columns\":984,\"../heatmap/xyz_defaults\":993,\"./attributes\":949,\"./contours_defaults\":953,\"./style_defaults\":963}],955:[function(t,e,r){\"use strict\";e.exports=function(t){return t.end+t.size/1e6}},{}],956:[function(t,e,r){\"use strict\";function n(t,e,r,n){return Math.abs(t[0]-e[0])20&&e?208===t||1114===t?n=0===r[0]?1:-1:i=0===r[1]?1:-1:-1!==l.BOTTOMSTART.indexOf(t)?i=1:-1!==l.LEFTSTART.indexOf(t)?n=1:-1!==l.TOPSTART.indexOf(t)?i=-1:n=-1;return[n,i]}(p,r,e),g=[o(t,e,[-m[0],-m[1]])],v=m.join(\",\"),y=t.z.length,x=t.z[0].length;for(f=0;f<1e4;f++){if(p>20?(p=l.CHOOSESADDLE[p][(m[0]||m[1])<0?0:1],t.crossings[d]=l.SADDLEREMAINDER[p]):delete t.crossings[d],!(m=l.NEWDELTA[p])){s.log(\"Found bad marching index:\",p,e,t.level);break}g.push(o(t,e,m)),e[0]+=m[0],e[1]+=m[1],n(g[g.length-1],g[g.length-2],a,c)&&g.pop(),d=e.join(\",\");var b=m[0]&&(e[0]<0||e[0]>x-2)||m[1]&&(e[1]<0||e[1]>y-2);if(d===h&&m.join(\",\")===v||r&&b)break;p=t.crossings[d]}1e4===f&&s.log(\"Infinite loop in contour?\");var _,w,M,k,A,T,S,E,L,C,z,D=n(g[0],g[g.length-1],a,c),I=0,P=.2*t.smoothing,O=[],F=0;for(f=1;f=F;f--)if((_=O[f])=F&&_+O[w]E&&L--,t.edgepaths[L]=z.concat(g,C));break}j||(t.edgepaths[E]=g.concat(C))}for(E=0;Et?0:1)+(e[0][1]>t?0:2)+(e[1][1]>t?0:4)+(e[1][0]>t?0:8);if(5===r||10===r)return t>(e[0][0]+e[0][1]+e[1][0]+e[1][1])/4?5===r?713:1114:5===r?104:208;return 15===r?0:r}((c=t[u]).level,s))&&(c.crossings[o]=l,-1!==i.indexOf(l)&&(c.starts.push([e,r]),p&&-1!==i.indexOf(l,i.indexOf(l)+1)&&c.starts.push([e,r])))}},{\"./constants\":952}],961:[function(t,e,r){\"use strict\";function n(t,e,n){var l=n[0].trace,c=n[0].x,u=n[0].y,g=l.contours,v=l.uid,y=e.xaxis,x=e.yaxis,b=t._fullLayout,_=\"contour\"+v,w=function(t,e,r){for(var n=t.size,i=[],a=p(t),s=t.start;s1e3){o.warn(\"Too many contours, clipping at 1000\",t);break}return i}(g,e,n[0]);if(!0!==l.visible)return b._paper.selectAll(\".\"+_+\",.hm\"+v).remove(),void b._infolayer.selectAll(\".cb\"+v).remove();\"heatmap\"===g.coloring?(l.zauto&&!1===l.autocontour&&(l._input.zmin=l.zmin=g.start-g.size/2,l._input.zmax=l.zmax=l.zmin+w.length*g.size),f(t,e,[n])):(b._paper.selectAll(\".hm\"+v).remove(),b._infolayer.selectAll(\"g.rangeslider-container\").selectAll(\".hm\"+v).remove()),h(w),d(w);var M=y.c2p(c[0],!0),k=y.c2p(c[c.length-1],!0),A=x.c2p(u[0],!0),T=x.c2p(u[u.length-1],!0),S=[[M,T],[k,T],[k,A],[M,A]],E=r.makeContourGroup(e,n,_);!function(t,e,r){var n=t.selectAll(\"g.contourbg\").data([0]);n.enter().append(\"g\").classed(\"contourbg\",!0);var i=n.selectAll(\"path\").data(\"fill\"===r.coloring?[0]:[]);i.enter().append(\"path\"),i.exit().remove(),i.attr(\"d\",\"M\"+e.join(\"L\")+\"Z\").style(\"stroke\",\"none\")}(E,S,g),function(t,e,r,n){var o=t.selectAll(\"g.contourfill\").data([0]);o.enter().append(\"g\").classed(\"contourfill\",!0);var s=o.selectAll(\"path\").data(\"fill\"===n.coloring?e:[]);s.enter().append(\"path\"),s.exit().remove(),s.each(function(t){var e=i(t,r);e?a.select(this).attr(\"d\",e).style(\"stroke\",\"none\"):a.select(this).remove()})}(E,w,S,g),function(t,e,n,i,l,c){var u=t.selectAll(\"g.contourlines\").data([0]);u.enter().append(\"g\").classed(\"contourlines\",!0);var f=!1!==l.showlines,h=l.showlabels,d=f&&h,p=r.createLines(u,f||h,e),g=r.createLineClip(u,d,n._fullLayout._clips,i.trace.uid),v=t.selectAll(\"g.contourlabels\").data(h?[0]:[]);if(v.exit().remove(),v.enter().append(\"g\").classed(\"contourlabels\",!0),h){var y=[c],x=[];o.clearLocationCache();var b=r.labelFormatter(l,i.t.cb,n._fullLayout),_=s.tester.append(\"text\").attr(\"data-notex\",1).call(s.font,l.labelfont),w=e[0].xaxis._length,M=e[0].yaxis._length,k={left:Math.max(c[0][0],0),right:Math.min(c[2][0],w),top:Math.max(c[0][1],0),bottom:Math.min(c[2][1],M)};k.middle=(k.top+k.bottom)/2,k.center=(k.left+k.right)/2;var A=Math.sqrt(w*w+M*M),T=m.LABELDISTANCE*A/Math.max(1,e.length/m.LABELINCREASE);p.each(function(t){var e=r.calcTextOpts(t.level,b,_,n);a.select(this).selectAll(\"path\").each(function(){var t=o.getVisibleSegment(this,k,e.height/2);if(t&&!(t.len<(e.width+e.height)*m.LABELMIN))for(var n=Math.min(Math.ceil(t.len/T),m.LABELMAX),i=0;i=0&&(c=x,f=h):Math.abs(l[1]-c[1])<.01?Math.abs(l[1]-x[1])<.01&&(x[0]-l[0])*(c[0]-x[0])>=0&&(c=x,f=h):o.log(\"endpt to newendpt is not vert. or horz.\",l,c,x)}if(l=c,f>=0)break;m+=\"L\"+c}if(f===t.edgepaths.length){o.log(\"unclosed perimeter path\");break}g=f,(y=-1===v.indexOf(g))&&(g=v[0],m+=\"Z\")}for(g=0;gn.center?n.right-s:s-n.left)/(u+Math.abs(Math.sin(c)*a)),d=(l>n.middle?n.bottom-l:l-n.top)/(Math.abs(f)+Math.cos(c)*a);if(h<1||d<1)return 1/0;var p=g.EDGECOST*(1/(h-1)+1/(d-1));p+=g.ANGLECOST*c*c;for(var m=s-u,v=l-f,y=s+u,x=l+f,b=0;b2*g.MAXCOST)break;d&&(s/=2),l=(a=c-s/2)+1.5*s}if(h<=g.MAXCOST)return u},r.addLabelData=function(t,e,r,n){var i=e.width/2,a=e.height/2,o=t.x,s=t.y,l=t.theta,c=Math.sin(l),u=Math.cos(l),f=i*u,h=a*c,d=i*c,p=-a*u,m=[[o-f-h,s-d-p],[o+f-h,s+d-p],[o+f+h,s+d+p],[o-f+h,s-d+p]];r.push({text:e.text,x:o,y:s,dy:e.dy,theta:l,level:e.level,width:e.width,height:e.height}),n.push(m)},r.drawLabels=function(t,e,r,n,i){var o=t.selectAll(\"text\").data(e,function(t){return t.text+\",\"+t.x+\",\"+t.y+\",\"+t.theta});if(o.exit().remove(),o.enter().append(\"text\").attr({\"data-notex\":1,\"text-anchor\":\"middle\"}).each(function(t){var e=t.x+Math.sin(t.theta)*t.dy,n=t.y-Math.cos(t.theta)*t.dy;a.select(this).text(t.text).attr({x:e,y:n,transform:\"rotate(\"+180*t.theta/Math.PI+\" \"+e+\" \"+n+\")\"}).call(l.convertToTspans,r)}),i){for(var s=\"\",c=0;cx.end&&(x.start=x.end=(x.start+x.end)/2),e._input.contours=a({},x)}else{var _=x.start,w=x.end,M=e._input.contours;if(_>w&&(x.start=M.start=w,w=x.end=M.end=_,_=x.start),!(x.size>0)){var k;k=_===w?1:n(_,w,e.ncontours).dtick,M.size=x.size=k}}return y}}},{\"../../components/colorscale/calc\":625,\"../../lib\":743,\"../../plots/cartesian/axes\":789,\"../carpet/lookup_carpetid\":931,\"../heatmap/clean_2d_array\":979,\"../heatmap/convert_column_xyz\":981,\"../heatmap/find_empties\":983,\"../heatmap/has_columns\":984,\"../heatmap/interp2d\":987,\"../heatmap/make_bound_array\":988,\"../heatmap/max_row_length\":989,\"./defaults\":971}],966:[function(t,e,r){\"use strict\";e.exports=function(t,e,r,n){var i,a,o,s=n.a.length,l=n.b.length,c=n.z,u=-1/0,f=1/0;for(i=0;i\":case\">=\":n.contours.value>u&&(t[0].prefixBoundary=!0);break;case\"<\":case\"<=\":n.contours.valueu&&(t[0].prefixBoundary=!0);break;case\"][\":case\")(\":a=Math.min.apply(null,n.contours.value),o=Math.max.apply(null,n.contours.value),au&&(t[0].prefixBoundary=!0)}}},{}],967:[function(t,e,r){\"use strict\";e.exports={INEQUALITY_OPS:[\"=\",\"<\",\">=\",\">\",\"<=\"],INTERVAL_OPS:[\"[]\",\"()\",\"[)\",\"(]\",\"][\",\")(\",\"](\",\")[\"],SET_OPS:[\"{}\",\"}{\"]}},{}],968:[function(t,e,r){\"use strict\";function n(t,e){function r(t){return s(t)?+t:null}var n,i=Array.isArray(e);return-1!==o.INEQUALITY_OPS.indexOf(t)?n=r(i?e[0]:e):-1!==o.INTERVAL_OPS.indexOf(t)?n=i?[r(e[0]),r(e[1])]:[r(e),r(e)]:-1!==o.SET_OPS.indexOf(t)&&(n=i?e.map(r):[r(e)]),n}function i(t){return function(e){e=n(t,e);var r=Math.min(e[0],e[1]),i=Math.max(e[0],e[1]);return{start:r,end:i,size:i-r}}}function a(t){return function(e){return e=n(t,e),{start:e,end:1/0,size:1/0}}}var o=t(\"./constants\"),s=t(\"fast-isnumeric\");e.exports[\"[]\"]=i(\"[]\"),e.exports[\"()\"]=i(\"()\"),e.exports[\"[)\"]=i(\"[)\"),e.exports[\"(]\"]=i(\"(]\"),e.exports[\"][\"]=i(\"][\"),e.exports[\")(\"]=i(\")(\"),e.exports[\")[\"]=i(\")[\"),e.exports[\"](\"]=i(\"](\"),e.exports[\">\"]=a(\">\"),e.exports[\">=\"]=a(\">=\"),e.exports[\"<\"]=a(\"<\"),e.exports[\"<=\"]=a(\"<=\"),e.exports[\"=\"]=a(\"=\")},{\"./constants\":967,\"fast-isnumeric\":140}],969:[function(t,e,r){\"use strict\";var n=t(\"./constraint_mapping\"),i=t(\"fast-isnumeric\");e.exports=function(t,e){var r;-1===[\"=\",\"<\",\"<=\",\">\",\">=\"].indexOf(e.operation)?(t(\"contours.value\",[0,1]),Array.isArray(e.value)?e.value.length>2?e.value=e.value.slice(2):0===e.length?e.value=[0,1]:e.length<2?(r=parseFloat(e.value[0]),e.value=[r,r+1]):e.value=[parseFloat(e.value[0]),parseFloat(e.value[1])]:i(e.value)&&(r=parseFloat(e.value),e.value=[r,r+1])):(t(\"contours.value\",0),i(e.value)||(Array.isArray(e.value)?e.value=parseFloat(e.value[0]):e.value=0));var a=n[e.operation](e.value);e.start=a.start,e.end=a.end,e.size=a.size}},{\"./constraint_mapping\":968,\"fast-isnumeric\":140}],970:[function(t,e,r){\"use strict\";var n=t(\"../../lib\");e.exports=function(t,e){var r,i,a,o=function(t){return t.reverse()},s=function(t){return t};switch(e){case\"][\":case\")[\":case\"](\":case\")(\":var l=o;o=s,s=l;case\"[]\":case\"[)\":case\"(]\":case\"()\":if(2!==t.length)return void n.warn(\"Contour data invalid for the specified inequality range operation.\");for(i=t[0],a=t[1],r=0;r=\":case\">\":if(1!==t.length)return void n.warn(\"Contour data invalid for the specified inequality operation.\");for(i=t[0],r=0;r1e3){n.warn(\"Too many contours, clipping at 1000\",t);break}return a}},{\"../../lib\":743}],973:[function(t,e,r){\"use strict\";var n={};n.attributes=t(\"./attributes\"),n.supplyDefaults=t(\"./defaults\"),n.colorbar=t(\"../contour/colorbar\"),n.calc=t(\"./calc\"),n.plot=t(\"./plot\"),n.style=t(\"../contour/style\"),n.moduleType=\"trace\",n.name=\"contourcarpet\",n.basePlotModule=t(\"../../plots/cartesian\"),n.categories=[\"cartesian\",\"carpet\",\"contour\",\"symbols\",\"showLegend\",\"hasLines\",\"carpetDependent\"],n.meta={},e.exports=n},{\"../../plots/cartesian\":800,\"../contour/colorbar\":951,\"../contour/style\":962,\"./attributes\":964,\"./calc\":965,\"./defaults\":971,\"./plot\":976}],974:[function(t,e,r){\"use strict\";var n=t(\"../../components/drawing\"),i=t(\"../carpet/axis_aligned_line\"),a=t(\"../../lib\");e.exports=function(t,e,r,o,s,l,c,u){function f(t){return Math.abs(t[1]-r[0][1])=0&&(y=L,b=_):Math.abs(v[1]-y[1])=0&&(y=L,b=_):a.log(\"endpt to newendpt is not vert. or horz.\",v,y,L)}if(b>=0)break;M+=m(v,y),v=y}if(b===e.edgepaths.length){a.log(\"unclosed perimeter path\");break}g=b,(A=-1===k.indexOf(g))&&(g=k[0],M+=m(v,y)+\"Z\",v=null)}for(g=0;g=0;U--)N=k.clipsegments[U],j=l([],N.x,L.c2p),B=l([],N.y,C.c2p),j.reverse(),B.reverse(),q.push(c(j,B,N.bicubic));var H=\"M\"+q.join(\"L\")+\"Z\";!function(t,e,r,n,i,a){var o,s,u,f,h=t.selectAll(\"g.contourbg\").data([0]);h.enter().append(\"g\").classed(\"contourbg\",!0);var d=h.selectAll(\"path\").data(\"fill\"!==a||i?[]:[0]);d.enter().append(\"path\"),d.exit().remove();var p=[];for(f=0;fx&&(n.max=x);n.len=n.max-n.min}(this,r,t,n,h,e.height),!(n.len<(e.width+e.height)*m.LABELMIN)))for(var s=Math.min(Math.ceil(n.len/D),m.LABELMAX),l=0;lz){r(\"x scale is not linear\");break}}if(y.length&&\"fast\"===L){var D=(y[y.length-1]-y[0])/(y.length-1),I=Math.abs(D/100);for(w=0;wI){r(\"y scale is not linear\");break}}}var P=u(_),O=\"scaled\"===e.xtype?\"\":m,F=p(e,O,g,v,P,k),R=\"scaled\"===e.ytype?\"\":y,N=p(e,R,x,b,_.length,A);E||(a.expand(k,F),a.expand(A,N));var j={x:F,y:N,z:_,text:e.text};if(O&&O.length===F.length-1&&(j.xCenter=O),R&&R.length===N.length-1&&(j.yCenter=R),S&&(j.xRanges=M.xRanges,j.yRanges=M.yRanges,j.pts=M.pts),s(e,_,\"\",\"z\"),T&&e.contours&&\"heatmap\"===e.contours.coloring){var B={type:\"contour\"===e.type?\"heatmap\":\"histogram2d\",xcalendar:e.xcalendar,ycalendar:e.ycalendar};j.xfill=p(B,O,g,v,P,k),j.yfill=p(B,R,x,b,_.length,A)}return[j]}},{\"../../components/colorscale/calc\":625,\"../../lib\":743,\"../../plots/cartesian/axes\":789,\"../../registry\":873,\"../histogram2d/calc\":1010,\"./clean_2d_array\":979,\"./convert_column_xyz\":981,\"./find_empties\":983,\"./has_columns\":984,\"./interp2d\":987,\"./make_bound_array\":988,\"./max_row_length\":989}],979:[function(t,e,r){\"use strict\";var n=t(\"fast-isnumeric\");e.exports=function(t,e){function r(t){if(n(t))return+t}var i,a,o,s,l,c;if(e){for(i=0,l=0;l=0;o--)(s=((f[[(r=(a=h[o])[0])-1,i=a[1]]]||m)[2]+(f[[r+1,i]]||m)[2]+(f[[r,i-1]]||m)[2]+(f[[r,i+1]]||m)[2])/20)&&(l[a]=[r,i,s],h.splice(o,1),c=!0);if(!c)throw\"findEmpties iterated with no new neighbors\";for(a in l)f[a]=l[a],u.push(l[a])}return u.sort(function(t,e){return e[2]-t[2]})}},{\"./max_row_length\":989}],984:[function(t,e,r){\"use strict\";e.exports=function(t){return!Array.isArray(t.z[0])}},{}],985:[function(t,e,r){\"use strict\";var n=t(\"../../components/fx\"),i=t(\"../../lib\"),a=t(\"../../plots/cartesian/axes\"),o=n.constants.MAXDIST;e.exports=function(t,e,r,s,l,c){if(!(t.distance=b[0].length||d<0||d>b.length)return}else{if(n.inbox(e-y[0],e-y[y.length-1])>o||n.inbox(r-x[0],r-x[x.length-1])>o)return;if(c){var E;for(T=[2*y[0]-y[1]],E=1;Em&&(v=Math.max(v,Math.abs(t[i][a]-p)/(g-m))))}return v}var a=t(\"../../lib\"),o=[[-1,0],[1,0],[0,-1],[0,1]];e.exports=function(t,e,r){var o,s,l=1;if(Array.isArray(r))for(o=0;o.01;o++)l=i(t,e,n(l));return l>.01&&a.log(\"interp2d didn't converge quickly\",l),t}},{\"../../lib\":743}],988:[function(t,e,r){\"use strict\";var n=t(\"../../registry\");e.exports=function(t,e,r,i,a,o){var s,l,c,u=[],f=n.traceIs(t,\"contour\"),h=n.traceIs(t,\"histogram\"),d=n.traceIs(t,\"gl2d\");if(Array.isArray(e)&&e.length>1&&!h&&\"category\"!==o.type){var p=e.length;if(!(p<=a))return f?e.slice(0,a):e.slice(0,a+1);if(f||d)u=e.slice(0,a);else if(1===a)u=[e[0]-.5,e[0]+.5];else{for(u=[1.5*e[0]-.5*e[1]],c=1;c0;)w=v.c2p(E[T]),T--;for(w<_&&(M=w,w=_,_=M,F=!0),T=0;void 0===k&&T0;)A=y.c2p(L[T]),T--;if(A0&&(n=!0);for(var s=0;sa){var o=a-r[t];return r[t]=a,o}}return 0},max:function(t,e,r,i){var a=i[e];if(n(a)){if(a=Number(a),!n(r[t]))return r[t]=a,a;if(r[t]c){var l=a(e,i,o),u=a(r,i,o),f=t===s?0:1;return l[f]!==u[f]}return Math.floor(r/t)-Math.floor(e/t)>.1}(h,t,e,l,r,n))break;u=h}return u}function i(t,e){return e&&t>h?t>c?t>1.1*s?s:t>1.1*l?l:c:t>u?u:t>f?f:h:Math.pow(10,Math.floor(Math.log(t)/Math.LN10))}function a(t,e,r){var n=e.c2d(t,s,r).split(\"-\");return\"\"===n[0]&&(n.unshift(),n[0]=\"-\"+n[0]),n}var o=t(\"../../constants/numerical\"),s=o.ONEAVGYEAR,l=o.ONEAVGMONTH,c=o.ONEDAY,u=o.ONEHOUR,f=o.ONEMIN,h=o.ONESEC,d=t(\"../../plots/cartesian/axes\").tickIncrement;e.exports=function(t,e,r,i,a){var o,l,u=-1.1*e,f=-.1*e,h=t-f,p=r[0],m=r[1],g=Math.min(n(p+f,p+h,i,a),n(m+f,m+h,i,a)),v=Math.min(n(p+u,p+f,i,a),n(m+u,m+f,i,a));if(g>v&&vc){var y=o===s?1:6,x=o===s?\"M12\":\"M1\";return function(e,r){var n=i.c2d(e,s,a),o=n.indexOf(\"-\",y);o>0&&(n=n.substr(0,o));var c=i.d2c(n,0,a);if(cp.size/1.9?p.size:p.size/Math.ceil(p.size/b);var T=p.start+(p.size-b)/2;_=T-b*Math.ceil((T-_)/b)}for(f=0;f=0&&w=0;a--)i(a);else if(\"increasing\"===e){for(a=1;a=0;a--)t[a]+=t[a+1];\"exclude\"===r&&(t.push(0),t.shift())}}(a,x.direction,x.currentbin);var Z=Math.min(i.length,a.length),J=[],K=0,Q=Z-1;for(r=0;r=K;r--)if(a[r]){Q=r;break}for(r=K;r<=Q;r++)if(o(i[r])&&o(a[r])){var $={p:i[r],s:a[r],b:0};x.enabled||($.pts=z[r],q?$.p0=$.p1=z[r].length?A[z[r][0]]:i[r]:($.p0=X(S[r]),$.p1=X(S[r+1],!0))),J.push($)}return 1===J.length&&(J[0].width1=l.tickIncrement(J[0].p,k.size,!1,y)-J[0].p),c(J,e),Array.isArray(e.selectedpoints)&&s.tagSelected(J,e,Y),J}}},{\"../../constants/numerical\":721,\"../../lib\":743,\"../../plots/cartesian/axes\":789,\"../bar/arrays_to_calcdata\":882,\"./average\":998,\"./bin_functions\":1e3,\"./bin_label_vals\":1001,\"./clean_bins\":1003,\"./norm_functions\":1008,\"fast-isnumeric\":140}],1003:[function(t,e,r){\"use strict\";var n=t(\"fast-isnumeric\"),i=t(\"../../lib\").cleanDate,a=t(\"../../constants/numerical\"),o=a.ONEDAY,s=a.BADNUM;e.exports=function(t,e,r){var a=e.type,l=r+\"bins\",c=t[l];c||(c=t[l]={});var u=\"date\"===a?function(t){return t||0===t?i(t,s,c.calendar):null}:function(t){return n(t)?Number(t):null};c.start=u(c.start),c.end=u(c.end);var f=\"date\"===a?o:1,h=c.size;if(n(h))c.size=h>0?Number(h):f;else if(\"string\"!=typeof h)c.size=f;else{var d=h.charAt(0),p=h.substr(1);((p=n(p)?Number(p):0)<=0||\"date\"!==a||\"M\"!==d||p!==Math.round(p))&&(c.size=f)}var m=\"autobin\"+r;\"boolean\"!=typeof t[m]&&(t[m]=!((c.start||0===c.start)&&(c.end||0===c.end))),t[m]||delete t[\"nbins\"+r]}},{\"../../constants/numerical\":721,\"../../lib\":743,\"fast-isnumeric\":140}],1004:[function(t,e,r){\"use strict\";var n=t(\"../../registry\"),i=t(\"../../lib\"),a=t(\"../../components/color\"),o=t(\"./bin_defaults\"),s=t(\"../bar/style_defaults\"),l=t(\"../../components/errorbars/defaults\"),c=t(\"./attributes\");e.exports=function(t,e,r,u){function f(r,n){return i.coerce(t,e,c,r,n)}var h=f(\"x\"),d=f(\"y\");f(\"cumulative.enabled\")&&(f(\"cumulative.direction\"),f(\"cumulative.currentbin\")),f(\"text\");var p=f(\"orientation\",d&&!h?\"h\":\"v\"),m=e[\"v\"===p?\"x\":\"y\"];if(m&&m.length){n.getComponentMethod(\"calendars\",\"handleTraceDefaults\")(t,e,[\"x\",\"y\"],u);e[\"h\"===p?\"x\":\"y\"]&&f(\"histfunc\");o(t,e,f,\"h\"===p?[\"y\"]:[\"x\"]),s(t,e,f,r,u),l(t,e,a.defaultLine,{axis:\"y\"}),l(t,e,a.defaultLine,{axis:\"x\",inherit:\"y\"}),i.coerceSelectionMarkerOpacity(e,f)}else e.visible=!1}},{\"../../components/color\":618,\"../../components/errorbars/defaults\":648,\"../../lib\":743,\"../../registry\":873,\"../bar/style_defaults\":895,\"./attributes\":997,\"./bin_defaults\":999}],1005:[function(t,e,r){\"use strict\";e.exports=function(t,e,r,n,i){if(t.x=\"xVal\"in e?e.xVal:e.x,t.y=\"yVal\"in e?e.yVal:e.y,e.xa&&(t.xaxis=e.xa),e.ya&&(t.yaxis=e.ya),!(r.cumulative||{}).enabled){var a=Array.isArray(i)?n[0].pts[i[0]][i[1]]:n[i].pts;t.pointNumbers=a,t.binNumber=t.pointNumber,delete t.pointNumber,delete t.pointIndex;var o;if(r._indexToPoints){o=[];for(var s=0;sA&&g.splice(A,g.length-A),y.length>A&&y.splice(A,y.length-A),n(e,\"x\",g,m,_,M,x),n(e,\"y\",y,v,w,k,b);var T=[],S=[],E=[],L=\"string\"==typeof e.xbins.size,C=\"string\"==typeof e.ybins.size,z=[],D=[],I=L?z:e.xbins,P=C?D:e.ybins,O=0,F=[],R=[],N=e.histnorm,j=e.histfunc,B=-1!==N.indexOf(\"density\"),U=\"max\"===j||\"min\"===j?null:0,V=c.count,q=u[N],H=!1,G=[],Y=[],W=\"z\"in e?e.z:\"marker\"in e&&Array.isArray(e.marker.color)?e.marker.color:\"\";W&&\"count\"!==j&&(H=\"avg\"===j,V=c[j]);var X=e.xbins,Z=_(X.start),J=_(X.end)+(Z-l.tickIncrement(Z,X.size,!1,x))/1e6;for(r=Z;r=0&&d=0&&p0)o=c(t.alphahull,h);else{var d=[\"x\",\"y\",\"z\"].indexOf(t.delaunayaxis);o=l(h.map(function(t){return[t[(d+1)%3],t[(d+2)%3]]}))}var p={positions:h,cells:o,lightPosition:[t.lightposition.x,t.lightposition.y,t.lightposition.z],ambient:t.lighting.ambient,diffuse:t.lighting.diffuse,specular:t.lighting.specular,roughness:t.lighting.roughness,fresnel:t.lighting.fresnel,vertexNormalsEpsilon:t.lighting.vertexnormalsepsilon,faceNormalsEpsilon:t.lighting.facenormalsepsilon,opacity:t.opacity,contourEnable:t.contour.show,contourColor:f(t.contour.color).slice(0,3),contourWidth:t.contour.width,useFacetNormals:t.flatshading};t.intensity?(this.color=\"#fff\",p.vertexIntensity=t.intensity,p.vertexIntensityBounds=[t.cmin,t.cmax],p.colormap=function(t){return t.map(function(t){var e=t[0],r=s(t[1]).toRgb();return{index:e,rgb:[r.r,r.g,r.b,1]}})}(t.colorscale)):t.vertexcolor?(this.color=t.vertexcolor[0],p.vertexColors=i(t.vertexcolor)):t.facecolor?(this.color=t.facecolor[0],p.cellColors=i(t.facecolor)):(this.color=t.color,p.meshColor=f(t.color)),this.mesh.update(p)},h.dispose=function(){this.scene.glplot.remove(this.mesh),this.mesh.dispose()},e.exports=function(t,e){var r=t.glplot.gl,i=o({gl:r}),a=new n(t,i,e.uid);return i._trace=a,a.update(e),t.glplot.add(i),a}},{\"../../lib/str2rgbarray\":765,\"alpha-shape\":47,\"convex-hull\":109,\"delaunay-triangulate\":130,\"gl-mesh3d\":210,tinycolor2:546}],1022:[function(t,e,r){\"use strict\";var n=t(\"../../registry\"),i=t(\"../../lib\"),a=t(\"../../components/colorscale/defaults\"),o=t(\"./attributes\");e.exports=function(t,e,r,s){function l(r,n){return i.coerce(t,e,o,r,n)}function c(t){var e=t.map(function(t){var e=l(t);return e&&Array.isArray(e)?e:null});return e.every(function(t){return t&&t.length===e[0].length})&&e}var u=c([\"x\",\"y\",\"z\"]),f=c([\"i\",\"j\",\"k\"]);if(u){f&&f.forEach(function(t){for(var e=0;ei?r=!0:e1)){var f=a.simpleMap(u.x,e.d2c,0,r.xcalendar),h=a.distinctVals(f).minDiff;o=Math.min(o,h)}}for(o===1/0&&(o=1),c=0;c\");S.push(o,o,o,o,o,o,null)},R=0;Rs&&(n.log(\"parcoords traces support up to \"+s+\" dimensions at the moment\"),c.splice(s)),l=0;l0)&&(r(\"label\"),r(\"tickvals\"),r(\"ticktext\"),r(\"tickformat\"),r(\"range\"),r(\"constraintrange\"),f=Math.min(f,o.values.length)),o._index=l,u.push(o));if(isFinite(f))for(l=0;lf&&(o.values=o.values.slice(0,f));return u}(t,e);!function(t,e,r,i,s){s(\"line.color\",r),a(t,\"line\")&&n.isArray(t.line.color)?(s(\"line.colorscale\"),o(t,e,i,s,{prefix:\"line.\",cLetter:\"c\"})):s(\"line.color\",r)}(t,e,r,l,c),c(\"domain.x\"),c(\"domain.y\"),Array.isArray(u)&&u.length||(e.visible=!1);var f={family:l.font.family,size:Math.round(l.font.size*(10/12)),color:l.font.color};n.coerceFont(c,\"labelfont\",f),n.coerceFont(c,\"tickfont\",f),n.coerceFont(c,\"rangefont\",f)}},{\"../../components/colorscale/defaults\":628,\"../../components/colorscale/has_colorscale\":632,\"../../lib\":743,\"./attributes\":1031,\"./constants\":1035}],1037:[function(t,e,r){\"use strict\";var n={};n.attributes=t(\"./attributes\"),n.supplyDefaults=t(\"./defaults\"),n.calc=t(\"./calc\"),n.plot=t(\"./plot\"),n.colorbar=t(\"./colorbar\"),n.moduleType=\"trace\",n.name=\"parcoords\",n.basePlotModule=t(\"./base_plot\"),n.categories=[\"gl\",\"regl\",\"noOpacity\"],n.meta={},e.exports=n},{\"./attributes\":1031,\"./base_plot\":1032,\"./calc\":1033,\"./colorbar\":1034,\"./defaults\":1036,\"./plot\":1040}],1038:[function(t,e,r){\"use strict\";function n(t,e,r,n,i){var a=t._gl;a.enable(a.SCISSOR_TEST),a.scissor(e,r,n,i),t.clear({color:[0,0,0,0],depth:1})}function i(t,e,r,i,a,o){function s(c){var u;u=Math.min(i,a-c*i),o.offset=h*c*i,o.count=h*u,0===c&&(window.cancelAnimationFrame(r.currentRafs[l]),delete r.currentRafs[l],n(t,o.scissorX,o.scissorY,o.scissorWidth,o.viewBoxSize[1])),r.clearOnly||(e(o),c*i+u>>8*e)%256/255}function s(t,e){var r={};return[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15].map(function(r){return function(t,e,r){var n,i,a,o=[];for(i=0;i=f-4?o(s,f-2-l):.5);return i}(E,S,T,C),O=s(E,P),F=e.regl,R=F.texture({shape:[256,1],format:\"rgba\",type:\"uint8\",mag:\"nearest\",min:\"nearest\",data:function(t,e,r){for(var n=[],i=0;i<256;i++){var a=t(i/255);n.push((e?p:a).concat(r))}return n}(w,M,Math.round(255*(M?z:1)))}),N=F({profile:!1,blend:{enable:L,func:{srcRGB:\"src alpha\",dstRGB:\"one minus src alpha\",srcAlpha:1,dstAlpha:1},equation:{rgb:\"add\",alpha:\"add\"},color:[0,0,0,0]},depth:{enable:!L,mask:!0,func:\"less\",range:[0,1]},cull:{enable:!0,face:\"back\"},scissor:{enable:!0,box:{x:F.prop(\"scissorX\"),y:F.prop(\"scissorY\"),width:F.prop(\"scissorWidth\"),height:F.prop(\"scissorHeight\")}},viewport:{x:F.prop(\"viewportX\"),y:F.prop(\"viewportY\"),width:F.prop(\"viewportWidth\"),height:F.prop(\"viewportHeight\")},dither:!1,vert:k?\"precision highp float;\\n#define GLSLIFY 1\\n\\nattribute vec4 p0, p1, p2, p3,\\n p4, p5, p6, p7,\\n p8, p9, pa, pb,\\n pc, pd, pe;\\n\\nattribute vec4 pf;\\n\\nuniform mat4 dim1A, dim2A, dim1B, dim2B, dim1C, dim2C, dim1D, dim2D,\\n loA, hiA, loB, hiB, loC, hiC, loD, hiD;\\n\\nuniform vec2 resolution,\\n viewBoxPosition,\\n viewBoxSize;\\n\\nuniform sampler2D palette;\\n\\nuniform vec2 colorClamp;\\n\\nuniform float scatter;\\n\\nvarying vec4 fragColor;\\n\\nvec4 zero = vec4(0, 0, 0, 0);\\nvec4 unit = vec4(1, 1, 1, 1);\\nvec2 xyProjection = vec2(1, 1);\\n\\nmat4 mclamp(mat4 m, mat4 lo, mat4 hi) {\\n return mat4(clamp(m[0], lo[0], hi[0]),\\n clamp(m[1], lo[1], hi[1]),\\n clamp(m[2], lo[2], hi[2]),\\n clamp(m[3], lo[3], hi[3]));\\n}\\n\\nbool mshow(mat4 p, mat4 lo, mat4 hi) {\\n return mclamp(p, lo, hi) == p;\\n}\\n\\nfloat val(mat4 p, mat4 v) {\\n return dot(matrixCompMult(p, v) * unit, unit);\\n}\\n\\nvoid main() {\\n\\n float x = 0.5 * sign(pf[3]) + 0.5;\\n float prominence = abs(pf[3]);\\n float depth = 1.0 - prominence;\\n\\n mat4 pA = mat4(p0, p1, p2, p3);\\n mat4 pB = mat4(p4, p5, p6, p7);\\n mat4 pC = mat4(p8, p9, pa, pb);\\n mat4 pD = mat4(pc, pd, pe, abs(pf));\\n\\n float show = float(mshow(pA, loA, hiA) &&\\n mshow(pB, loB, hiB) &&\\n mshow(pC, loC, hiC) &&\\n mshow(pD, loD, hiD));\\n\\n vec2 yy = show * vec2(val(pA, dim2A) + val(pB, dim2B) + val(pC, dim2C) + val(pD, dim2D),\\n val(pA, dim1A) + val(pB, dim1B) + val(pC, dim1C) + val(pD, dim1D));\\n\\n vec2 dimensionToggle = vec2(x, 1.0 - x);\\n\\n vec2 scatterToggle = vec2(scatter, 1.0 - scatter);\\n\\n float y = dot(yy, dimensionToggle);\\n mat2 xy = mat2(viewBoxSize * yy + dimensionToggle, viewBoxSize * vec2(x, y));\\n\\n vec2 viewBoxXY = viewBoxPosition + xy * scatterToggle;\\n\\n float depthOrHide = depth + 2.0 * (1.0 - show);\\n\\n gl_Position = vec4(\\n xyProjection * (2.0 * viewBoxXY / resolution - 1.0),\\n depthOrHide,\\n 1.0\\n );\\n\\n // pick coloring\\n fragColor = vec4(pf.rgb, 1.0);\\n}\\n\":\"precision highp float;\\n#define GLSLIFY 1\\n\\nattribute vec4 p0, p1, p2, p3,\\n p4, p5, p6, p7,\\n p8, p9, pa, pb,\\n pc, pd, pe;\\n\\nattribute vec4 pf;\\n\\nuniform mat4 dim1A, dim2A, dim1B, dim2B, dim1C, dim2C, dim1D, dim2D,\\n loA, hiA, loB, hiB, loC, hiC, loD, hiD;\\n\\nuniform vec2 resolution,\\n viewBoxPosition,\\n viewBoxSize;\\n\\nuniform sampler2D palette;\\n\\nuniform vec2 colorClamp;\\n\\nuniform float scatter;\\n\\nvarying vec4 fragColor;\\n\\nvec4 zero = vec4(0, 0, 0, 0);\\nvec4 unit = vec4(1, 1, 1, 1);\\nvec2 xyProjection = vec2(1, 1);\\n\\nmat4 mclamp(mat4 m, mat4 lo, mat4 hi) {\\n return mat4(clamp(m[0], lo[0], hi[0]),\\n clamp(m[1], lo[1], hi[1]),\\n clamp(m[2], lo[2], hi[2]),\\n clamp(m[3], lo[3], hi[3]));\\n}\\n\\nbool mshow(mat4 p, mat4 lo, mat4 hi) {\\n return mclamp(p, lo, hi) == p;\\n}\\n\\nfloat val(mat4 p, mat4 v) {\\n return dot(matrixCompMult(p, v) * unit, unit);\\n}\\n\\nvoid main() {\\n\\n float x = 0.5 * sign(pf[3]) + 0.5;\\n float prominence = abs(pf[3]);\\n float depth = 1.0 - prominence;\\n\\n mat4 pA = mat4(p0, p1, p2, p3);\\n mat4 pB = mat4(p4, p5, p6, p7);\\n mat4 pC = mat4(p8, p9, pa, pb);\\n mat4 pD = mat4(pc, pd, pe, abs(pf));\\n\\n float show = float(mshow(pA, loA, hiA) &&\\n mshow(pB, loB, hiB) &&\\n mshow(pC, loC, hiC) &&\\n mshow(pD, loD, hiD));\\n\\n vec2 yy = show * vec2(val(pA, dim2A) + val(pB, dim2B) + val(pC, dim2C) + val(pD, dim2D),\\n val(pA, dim1A) + val(pB, dim1B) + val(pC, dim1C) + val(pD, dim1D));\\n\\n vec2 dimensionToggle = vec2(x, 1.0 - x);\\n\\n vec2 scatterToggle = vec2(scatter, 1.0 - scatter);\\n\\n float y = dot(yy, dimensionToggle);\\n mat2 xy = mat2(viewBoxSize * yy + dimensionToggle, viewBoxSize * vec2(x, y));\\n\\n vec2 viewBoxXY = viewBoxPosition + xy * scatterToggle;\\n\\n float depthOrHide = depth + 2.0 * (1.0 - show);\\n\\n gl_Position = vec4(\\n xyProjection * (2.0 * viewBoxXY / resolution - 1.0),\\n depthOrHide,\\n 1.0\\n );\\n\\n // visible coloring\\n float clampedColorIndex = clamp((prominence - colorClamp[0]) / (colorClamp[1] - colorClamp[0]), 0.0, 1.0);\\n fragColor = texture2D(palette, vec2((clampedColorIndex * 255.0 + 0.5) / 256.0, 0.5));\\n}\\n\",frag:\"precision lowp float;\\n#define GLSLIFY 1\\n\\nvarying vec4 fragColor;\\n\\nvoid main() {\\n gl_FragColor = fragColor;\\n}\\n\",primitive:\"lines\",lineWidth:1,attributes:O,uniforms:{resolution:F.prop(\"resolution\"),viewBoxPosition:F.prop(\"viewBoxPosition\"),viewBoxSize:F.prop(\"viewBoxSize\"),dim1A:F.prop(\"dim1A\"),dim2A:F.prop(\"dim2A\"),dim1B:F.prop(\"dim1B\"),dim2B:F.prop(\"dim2B\"),dim1C:F.prop(\"dim1C\"),dim2C:F.prop(\"dim2C\"),dim1D:F.prop(\"dim1D\"),dim2D:F.prop(\"dim2D\"),loA:F.prop(\"loA\"),hiA:F.prop(\"hiA\"),loB:F.prop(\"loB\"),hiB:F.prop(\"hiB\"),loC:F.prop(\"loC\"),hiC:F.prop(\"hiC\"),loD:F.prop(\"loD\"),hiD:F.prop(\"hiD\"),palette:R,colorClamp:F.prop(\"colorClamp\"),scatter:F.prop(\"scatter\")},offset:F.prop(\"offset\"),count:F.prop(\"count\")}),j=[0,1],B=[];return{setColorDomain:function(t){j[0]=t[0],j[1]=t[1]},render:function(t,e,a){var o,s,l,c=1/0,f=-1/0;for(o=0;of&&(f=t[o].dim2.canvasX,l=o),t[o].dim1.canvasXi)return a;i=o,a=n[r]}return n[n.length-1]}function o(t){return d.scale.linear().domain(i(t))}function s(t,e,r){var i=v(e),a=i.trace,s=i.lineColor,l=i.cscale,c=a.line,u=a.domain,p=a.dimensions,m=t.width,g=a.labelfont,y=a.tickfont,x=a.rangefont,b=h.extendDeep({},c,{color:s.map(o({values:s,range:[c.cmin,c.cmax]})),blockLineCount:f.blockLineCount,canvasOverdrag:f.overdrag*f.canvasPixelRatio}),_=Math.floor(m*(u.x[1]-u.x[0])),w=Math.floor(t.height*(u.y[1]-u.y[0])),M=t.margin||{l:80,r:80,t:100,b:80},k=_,A=w;return{key:r,colCount:p.filter(n).length,dimensions:p,tickDistance:f.tickDistance,unitToColor:function(t){var e=t.map(function(t){return t[0]}),r=t.map(function(t){return t[1]}).map(function(t){return d.rgb(t)}),n=\"rgb\".split(\"\").map(function(t){return d.scale.linear().clamp(!0).domain(e).range(r.map(function(t){return function(e){return e[t]}}(t)))});return function(t){return n.map(function(e){return e(t)})}}(l),lines:b,labelFont:g,tickFont:y,rangeFont:x,layoutWidth:m,layoutHeight:t.height,domain:u,translateX:u.x[0]*m,translateY:t.height-u.y[1]*t.height,pad:M,canvasWidth:k*f.canvasPixelRatio+2*b.canvasOverdrag,canvasHeight:A*f.canvasPixelRatio,width:k,height:A,canvasPixelRatio:f.canvasPixelRatio}}function l(t){var e=t.width,r=t.height,a=t.dimensions,s=t.canvasPixelRatio,l=function(r){return e*r/Math.max(1,t.colCount-1)},c=f.verticalPadding/(r*s),u=1-2*c,h=function(t){return c+u*t},p={key:t.key,xScale:l,model:t},m={};return p.dimensions=a.filter(n).map(function(e,n){var a=o(e),c=m[e.label];m[e.label]=(c||0)+1;return{key:e.label+(c?\"__\"+c:\"\"),label:e.label,tickFormat:e.tickformat,tickvals:e.tickvals,ticktext:e.ticktext,ordinal:!!e.tickvals,scatter:f.scatter||e.scatter,xIndex:n,crossfilterDimensionIndex:n,visibleIndex:e._index,height:r,values:e.values,paddedUnitValues:e.values.map(a).map(h),xScale:l,x:l(n),canvasX:l(n)*s,unitScale:function(t,e){return d.scale.linear().range([t-e,e])}(r,f.verticalPadding),domainScale:function(t,e,r){var n=i(r),a=r.ticktext;return r.tickvals?d.scale.ordinal().domain(r.tickvals.map(function(t,e){return function(r,n){if(e){var i=e[n];return null===i||void 0===i?t(r):i}return t(r)}}(d.format(r.tickformat),a))).range(r.tickvals.map(function(t){return(t-n[0])/(n[1]-n[0])}).map(function(r){return t-e+r*(e-(t-e))})):d.scale.linear().domain(n).range([t-e,e])}(r,f.verticalPadding,e),ordinalScale:function(t){var e=i(t);return t.tickvals&&d.scale.ordinal().domain(t.tickvals).range(t.tickvals.map(function(t){return(t-e[0])/(e[1]-e[0])}))}(e),domainToUnitScale:a,filter:e.constraintrange?e.constraintrange.map(a):[0,1],parent:p,model:t}}),p}function c(t){t.classed(f.cn.axisExtentText,!0).attr(\"text-anchor\",\"middle\").style(\"cursor\",\"default\").style(\"user-select\",\"none\")}var u=t(\"./lines\"),f=t(\"./constants\"),h=t(\"../../lib\"),d=t(\"d3\"),p=t(\"../../components/drawing\"),m=t(\"../../lib/gup\").keyFun,g=t(\"../../lib/gup\").repeat,v=t(\"../../lib/gup\").unwrap;e.exports=function(t,e,r,n,i,o){function y(t){return t.dimensions.some(function(t){return 0!==t.filter[0]||1!==t.filter[1]})}function x(t,e){return(f.scatter?function(t,e){for(var r=e.panels||(e.panels=[]),n=t.each(function(t){return t})[e.key].map(function(t){return t.__data__}),i=n.length-1,a=i,o=0;o=r||s>=n)return;var l=t.lineLayer.readPixel(a,n-1-s),c=0!==l[3],u=c?l[2]+256*(l[1]+256*l[0]):null,f={x:a,y:s,clientX:e.clientX,clientY:e.clientY,dataIndex:t.model.key,curveNumber:u};u!==L&&(c?o.hover(f):o.unhover&&o.unhover(f),L=u)}}),S.style(\"opacity\",function(t){return t.pick?.01:1}),e.style(\"background\",\"rgba(255, 255, 255, 0)\");var C=e.selectAll(\".\"+f.cn.parcoords).data(T,m);C.exit().remove(),C.enter().append(\"g\").classed(f.cn.parcoords,!0).attr(\"overflow\",\"visible\").style(\"box-sizing\",\"content-box\").style(\"position\",\"absolute\").style(\"left\",0).style(\"overflow\",\"visible\").style(\"shape-rendering\",\"crispEdges\").style(\"pointer-events\",\"none\").call(function(t){var e=t.selectAll(\"defs\").data(g,m);e.enter().append(\"defs\");var r=e.selectAll(\"#\"+f.id.filterBarPattern).data(g,m);r.enter().append(\"pattern\").attr(\"id\",f.id.filterBarPattern).attr(\"patternUnits\",\"userSpaceOnUse\"),r.attr(\"x\",-f.bar.width).attr(\"width\",f.bar.capturewidth).attr(\"height\",function(t){return t.model.height});var n=r.selectAll(\"rect\").data(g,m);n.enter().append(\"rect\").attr(\"shape-rendering\",\"crispEdges\"),n.attr(\"height\",function(t){return t.model.height}).attr(\"width\",f.bar.width).attr(\"x\",f.bar.width/2).attr(\"fill\",f.bar.fillcolor).attr(\"fill-opacity\",f.bar.fillopacity).attr(\"stroke\",f.bar.strokecolor).attr(\"stroke-opacity\",f.bar.strokeopacity).attr(\"stroke-width\",f.bar.strokewidth)}),C.attr(\"width\",function(t){return t.model.width+t.model.pad.l+t.model.pad.r}).attr(\"height\",function(t){return t.model.height+t.model.pad.t+t.model.pad.b}).attr(\"transform\",function(t){return\"translate(\"+t.model.translateX+\",\"+t.model.translateY+\")\"});var z=C.selectAll(\".\"+f.cn.parcoordsControlView).data(g,m);z.enter().append(\"g\").classed(f.cn.parcoordsControlView,!0).style(\"box-sizing\",\"content-box\"),z.attr(\"transform\",function(t){return\"translate(\"+t.model.pad.l+\",\"+t.model.pad.t+\")\"});var D=z.selectAll(\".\"+f.cn.yAxis).data(function(t){return t.dimensions},m);D.enter().append(\"g\").classed(f.cn.yAxis,!0).each(function(t){E.dimensions.push(t)}),z.each(function(t){x(D,t)}),S.filter(function(t){return!!t.viewModel}).each(function(t){t.lineLayer=u(this,t,f.scatter),t.viewModel[t.key]=t.lineLayer,E.renderers.push(function(){t.lineLayer.render(t.viewModel.panels,!0)}),t.lineLayer.render(t.viewModel.panels,!t.context)}),D.attr(\"transform\",function(t){return\"translate(\"+t.xScale(t.xIndex)+\", 0)\"}),D.call(d.behavior.drag().origin(function(t){return t}).on(\"drag\",function(t){var e=t.parent;A=!1,k||(t.x=Math.max(-f.overdrag,Math.min(t.model.width+f.overdrag,d.event.x)),t.canvasX=t.x*t.model.canvasPixelRatio,D.sort(function(t,e){return t.x-e.x}).each(function(e,r){e.xIndex=r,e.x=t===e?e.x:e.xScale(e.xIndex),e.canvasX=e.x*e.model.canvasPixelRatio}),x(D,e),D.filter(function(e){return 0!==Math.abs(t.xIndex-e.xIndex)}).attr(\"transform\",function(t){return\"translate(\"+t.xScale(t.xIndex)+\", 0)\"}),d.select(this).attr(\"transform\",\"translate(\"+t.x+\", 0)\"),D.each(function(r,n,i){i===t.parent.key&&(e.dimensions[n]=r)}),e.contextLayer&&e.contextLayer.render(e.panels,!1,!y(e)),e.focusLayer.render&&e.focusLayer.render(e.panels))}).on(\"dragend\",function(t){var e=t.parent;k?\"ending\"===k&&(k=!1):(t.x=t.xScale(t.xIndex),t.canvasX=t.x*t.model.canvasPixelRatio,x(D,e),d.select(this).attr(\"transform\",function(t){return\"translate(\"+t.x+\", 0)\"}),e.contextLayer&&e.contextLayer.render(e.panels,!1,!y(e)),e.focusLayer&&e.focusLayer.render(e.panels),e.pickLayer&&e.pickLayer.render(e.panels,!0),A=!0,o&&o.axesMoved&&o.axesMoved(e.key,e.dimensions.map(function(t){return t.crossfilterDimensionIndex})))})),D.exit().remove();var I=D.selectAll(\".\"+f.cn.axisOverlays).data(g,m);I.enter().append(\"g\").classed(f.cn.axisOverlays,!0),I.selectAll(\".\"+f.cn.axis).remove();var P=I.selectAll(\".\"+f.cn.axis).data(g,m);P.enter().append(\"g\").classed(f.cn.axis,!0),P.each(function(t){var e=t.model.height/t.model.tickDistance,r=t.domainScale,n=r.domain();d.select(this).call(d.svg.axis().orient(\"left\").tickSize(4).outerTickSize(2).ticks(e,t.tickFormat).tickValues(t.ordinal?n:null).tickFormat(t.ordinal?function(t){return t}:null).scale(r)),p.font(P.selectAll(\"text\"),t.model.tickFont)}),P.selectAll(\".domain, .tick>line\").attr(\"fill\",\"none\").attr(\"stroke\",\"black\").attr(\"stroke-opacity\",.25).attr(\"stroke-width\",\"1px\"),P.selectAll(\"text\").style(\"text-shadow\",\"1px 1px 1px #fff, -1px -1px 1px #fff, 1px -1px 1px #fff, -1px 1px 1px #fff\").style(\"cursor\",\"default\").style(\"user-select\",\"none\");var O=I.selectAll(\".\"+f.cn.axisHeading).data(g,m);O.enter().append(\"g\").classed(f.cn.axisHeading,!0);var F=O.selectAll(\".\"+f.cn.axisTitle).data(g,m);F.enter().append(\"text\").classed(f.cn.axisTitle,!0).attr(\"text-anchor\",\"middle\").style(\"cursor\",\"ew-resize\").style(\"user-select\",\"none\").style(\"pointer-events\",\"auto\"),F.attr(\"transform\",\"translate(0,\"+-f.axisTitleOffset+\")\").text(function(t){return t.label}).each(function(t){p.font(F,t.model.labelFont)});var R=I.selectAll(\".\"+f.cn.axisExtent).data(g,m);R.enter().append(\"g\").classed(f.cn.axisExtent,!0);var N=R.selectAll(\".\"+f.cn.axisExtentTop).data(g,m);N.enter().append(\"g\").classed(f.cn.axisExtentTop,!0),N.attr(\"transform\",\"translate(0,\"+-f.axisExtentOffset+\")\");var j=N.selectAll(\".\"+f.cn.axisExtentTopText).data(g,m);j.enter().append(\"text\").classed(f.cn.axisExtentTopText,!0).call(c),j.text(function(t){return b(t)(t.domainScale.domain().slice(-1)[0])}).each(function(t){p.font(j,t.model.rangeFont)});var B=R.selectAll(\".\"+f.cn.axisExtentBottom).data(g,m);B.enter().append(\"g\").classed(f.cn.axisExtentBottom,!0),B.attr(\"transform\",function(t){return\"translate(0,\"+(t.model.height+f.axisExtentOffset)+\")\"});var U=B.selectAll(\".\"+f.cn.axisExtentBottomText).data(g,m);U.enter().append(\"text\").classed(f.cn.axisExtentBottomText,!0).attr(\"dy\",\"0.75em\").call(c),U.text(function(t){return b(t)(t.domainScale.domain()[0])}).each(function(t){p.font(U,t.model.rangeFont)});var V=I.selectAll(\".\"+f.cn.axisBrush).data(g,m),q=V.enter().append(\"g\").classed(f.cn.axisBrush,!0);V.each(function(t){t.brush||(t.brush=d.svg.brush().y(t.unitScale).on(\"brushstart\",_).on(\"brush\",w).on(\"brushend\",M),0===t.filter[0]&&1===t.filter[1]||t.brush.extent(t.filter),d.select(this).call(t.brush))}),q.selectAll(\"rect\").attr(\"x\",-f.bar.capturewidth/2).attr(\"width\",f.bar.capturewidth),q.selectAll(\"rect.extent\").attr(\"fill\",\"url(#\"+f.id.filterBarPattern+\")\").style(\"cursor\",\"ns-resize\").filter(function(t){return 0===t.filter[0]&&1===t.filter[1]}).attr(\"y\",-100),q.selectAll(\".resize rect\").attr(\"height\",f.bar.handleheight).attr(\"opacity\",0).style(\"visibility\",\"visible\"),q.selectAll(\".resize.n rect\").style(\"cursor\",\"n-resize\").attr(\"y\",f.bar.handleoverlap-f.bar.handleheight),q.selectAll(\".resize.s rect\").style(\"cursor\",\"s-resize\").attr(\"y\",f.bar.handleoverlap);var H=!1,G=!1;return E}},{\"../../components/drawing\":643,\"../../lib\":743,\"../../lib/gup\":740,\"./constants\":1035,\"./lines\":1038,d3:128}],1040:[function(t,e,r){(function(r){\"use strict\";var n=t(\"./parcoords\"),i=t(\"regl\");e.exports=function(t,e){var a=t._fullLayout,o=a._toppaper,s=a._paperdiv,l=a._glcontainer;a._glcanvas.each(function(e){e.regl||(e.regl=i({canvas:this,attributes:{antialias:!e.pick,preserveDrawingBuffer:!0},pixelRatio:t._context.plotGlPixelRatio||r.devicePixelRatio}))});var c={},u={},f=a._size;e.forEach(function(e,r){c[r]=t.data[r].dimensions,u[r]=t.data[r].dimensions.slice()});n(s,o,l,e,{width:f.w,height:f.h,margin:{t:f.t,r:f.r,b:f.b,l:f.l}},{filterChanged:function(e,r,n){var i=u[e][r],a=i.constraintrange;a&&2===a.length||(a=i.constraintrange=[]),a[0]=n[0],a[1]=n[1],t.emit(\"plotly_restyle\")},hover:function(e){t.emit(\"plotly_hover\",e)},unhover:function(e){t.emit(\"plotly_unhover\",e)},axesMoved:function(e,r){function n(t){return!(\"visible\"in t)||t.visible}function i(t,e,r){var n=e.indexOf(r),i=t.indexOf(n);return-1===i&&(i+=e.length),i}var a=function(t){return function(e,n){return i(r,t,e)-i(r,t,n)}}(u[e].filter(n));c[e].sort(a),u[e].filter(function(t){return!n(t)}).sort(function(t){return u[e].indexOf(t)}).forEach(function(t){c[e].splice(c[e].indexOf(t),1),c[e].splice(u[e].indexOf(t),0,t)}),t.emit(\"plotly_restyle\")}})}}).call(this,\"undefined\"!=typeof global?global:\"undefined\"!=typeof self?self:\"undefined\"!=typeof window?window:{})},{\"./parcoords\":1039,regl:506}],1041:[function(t,e,r){\"use strict\";var n=t(\"../../components/color/attributes\"),i=t(\"../../plots/font_attributes\"),a=t(\"../../plots/attributes\"),o=t(\"../../plots/domain_attributes\"),s=t(\"../../lib/extend\").extendFlat,l=i({editType:\"calc\",colorEditType:\"style\"});e.exports={labels:{valType:\"data_array\",editType:\"calc\"},label0:{valType:\"number\",dflt:0,editType:\"calc\"},dlabel:{valType:\"number\",dflt:1,editType:\"calc\"},values:{valType:\"data_array\",editType:\"calc\"},marker:{colors:{valType:\"data_array\",editType:\"calc\"},line:{color:{valType:\"color\",dflt:n.defaultLine,arrayOk:!0,editType:\"style\"},width:{valType:\"number\",min:0,dflt:0,arrayOk:!0,editType:\"style\"},editType:\"calc\"},editType:\"calc\"},text:{valType:\"data_array\",editType:\"calc\"},hovertext:{valType:\"string\",dflt:\"\",arrayOk:!0,editType:\"style\"},scalegroup:{valType:\"string\",dflt:\"\",editType:\"calc\"},textinfo:{valType:\"flaglist\",flags:[\"label\",\"text\",\"value\",\"percent\"],extras:[\"none\"],editType:\"calc\"},hoverinfo:s({},a.hoverinfo,{flags:[\"label\",\"text\",\"value\",\"percent\",\"name\"]}),textposition:{valType:\"enumerated\",values:[\"inside\",\"outside\",\"auto\",\"none\"],dflt:\"auto\",arrayOk:!0,editType:\"calc\"},textfont:s({},l,{}),insidetextfont:s({},l,{}),outsidetextfont:s({},l,{}),domain:o({name:\"pie\",trace:!0,editType:\"calc\"}),hole:{valType:\"number\",min:0,max:1,dflt:0,editType:\"calc\"},sort:{valType:\"boolean\",dflt:!0,editType:\"calc\"},direction:{valType:\"enumerated\",values:[\"clockwise\",\"counterclockwise\"],dflt:\"counterclockwise\",editType:\"calc\"},rotation:{valType:\"number\",min:-360,max:360,dflt:0,editType:\"calc\"},pull:{valType:\"number\",min:0,max:1,dflt:0,arrayOk:!0,editType:\"calc\"}}},{\"../../components/color/attributes\":617,\"../../lib/extend\":732,\"../../plots/attributes\":787,\"../../plots/domain_attributes\":815,\"../../plots/font_attributes\":816}],1042:[function(t,e,r){\"use strict\";var n=t(\"../../registry\");r.name=\"pie\",r.plot=function(t){var e=n.getModule(\"pie\"),r=function(t,e){for(var r=[],n=0;n\")}}return y};var l},{\"../../components/color\":618,\"./helpers\":1046,\"fast-isnumeric\":140,tinycolor2:546}],1044:[function(t,e,r){\"use strict\";var n=t(\"../../lib\"),i=t(\"./attributes\");e.exports=function(t,e,r,a){function o(r,a){return n.coerce(t,e,i,r,a)}var s=n.coerceFont,l=o(\"values\"),c=o(\"labels\");if(!Array.isArray(c)){if(!Array.isArray(l)||!l.length)return void(e.visible=!1);o(\"label0\"),o(\"dlabel\")}o(\"marker.line.width\")&&o(\"marker.line.color\");var u=o(\"marker.colors\");Array.isArray(u)||(e.marker.colors=[]),o(\"scalegroup\");var f=o(\"text\"),h=o(\"textinfo\",Array.isArray(f)?\"text+percent\":\"percent\");if(o(\"hovertext\"),h&&\"none\"!==h){var d=o(\"textposition\"),p=Array.isArray(d)||\"auto\"===d,m=p||\"inside\"===d,g=p||\"outside\"===d;if(m||g){var v=s(o,\"textfont\",a.font);m&&s(o,\"insidetextfont\",v),g&&s(o,\"outsidetextfont\",v)}}o(\"domain.x\"),o(\"domain.y\"),o(\"hole\"),o(\"sort\"),o(\"direction\"),o(\"rotation\"),o(\"pull\")}},{\"../../lib\":743,\"./attributes\":1041}],1045:[function(t,e,r){\"use strict\";var n=t(\"../../components/fx/helpers\").appendArrayMultiPointValues;e.exports=function(t,e){var r={curveNumber:e.index,pointNumbers:t.pts,data:e._input,fullData:e,label:t.label,color:t.color,value:t.v,v:t.v};return 1===t.pts.length&&(r.pointNumber=r.i=t.pts[0]),n(r,e,t.pts),r}},{\"../../components/fx/helpers\":657}],1046:[function(t,e,r){\"use strict\";var n=t(\"../../lib\");r.formatPiePercent=function(t,e){var r=(100*t).toPrecision(3);return-1!==r.lastIndexOf(\".\")&&(r=r.replace(/[.]?0+$/,\"\")),n.numSeparate(r,e)+\"%\"},r.formatPieValue=function(t,e){var r=t.toPrecision(10);return-1!==r.lastIndexOf(\".\")&&(r=r.replace(/[.]?0+$/,\"\")),n.numSeparate(r,e)},r.getFirstFilled=function(t,e){if(Array.isArray(t))for(var r=0;r0?1:-1)/2,y:a/(1+r*r/(n*n)),outside:!0}}var a=t(\"d3\"),o=t(\"../../components/fx\"),s=t(\"../../components/color\"),l=t(\"../../components/drawing\"),c=t(\"../../lib/svg_text_utils\"),u=t(\"./helpers\"),f=t(\"./event_data\");e.exports=function(t,e){var r=t._fullLayout;!function(t,e){var r,n,i,a,o,s,l,c,u,f=[];for(i=0;il&&(l=s.pull[a]);o.r=Math.min(r,n)/(2+2*l),o.cx=e.l+e.w*(s.domain.x[1]+s.domain.x[0])/2,o.cy=e.t+e.h*(2-s.domain.y[1]-s.domain.y[0])/2,s.scalegroup&&-1===f.indexOf(s.scalegroup)&&f.push(s.scalegroup)}for(a=0;aa.vTotal/2?1:0)}(e),h.each(function(){var h=a.select(this).selectAll(\"g.slice\").data(e);h.enter().append(\"g\").classed(\"slice\",!0),h.exit().remove();var m=[[[],[]],[[],[]]],g=!1;h.each(function(e){function s(t,r,n,i){return\"a\"+i*d.r+\",\"+i*d.r+\" 0 \"+e.largeArc+(n?\" 1 \":\" 0 \")+i*(r[0]-t[0])+\",\"+i*(r[1]-t[1])}if(e.hidden)a.select(this).selectAll(\"path,g\").remove();else{e.pointNumber=e.i,e.curveNumber=p.index,m[e.pxmid[1]<0?0:1][e.pxmid[0]<0?0:1].push(e);var h=d.cx,v=d.cy,y=a.select(this),x=y.selectAll(\"path.surface\").data([e]),b=!1,_=!1;if(x.enter().append(\"path\").classed(\"surface\",!0).style({\"pointer-events\":\"all\"}),y.select(\"path.textline\").remove(),y.on(\"mouseover\",function(){var i=t._fullLayout,s=t._fullData[p.index];if(!t._dragging&&!1!==i.hovermode){var l=s.hoverinfo;if(Array.isArray(l)&&(l=o.castHoverinfo({hoverinfo:[u.castOption(l,e.pts)],_module:p._module},i,0)),\"all\"===l&&(l=\"label+text+value+percent+name\"),\"none\"!==l&&\"skip\"!==l&&l){var c=n(e,d),m=h+e.pxmid[0]*(1-c),g=v+e.pxmid[1]*(1-c),y=r.separators,x=[];if(-1!==l.indexOf(\"label\")&&x.push(e.label),-1!==l.indexOf(\"text\")){var w=u.castOption(s.hovertext||s.text,e.pts);w&&x.push(w)}-1!==l.indexOf(\"value\")&&x.push(u.formatPieValue(e.v,y)),-1!==l.indexOf(\"percent\")&&x.push(u.formatPiePercent(e.v/d.vTotal,y));var M=p.hoverlabel,k=M.font;o.loneHover({x0:m-c*d.r,x1:m+c*d.r,y:g,text:x.join(\"
\"),name:-1!==l.indexOf(\"name\")?s.name:void 0,idealAlign:e.pxmid[0]<0?\"left\":\"right\",color:u.castOption(M.bgcolor,e.pts)||e.color,borderColor:u.castOption(M.bordercolor,e.pts),fontFamily:u.castOption(k.family,e.pts),fontSize:u.castOption(k.size,e.pts),fontColor:u.castOption(k.color,e.pts)},{container:i._hoverlayer.node(),outerContainer:i._paper.node(),gd:t}),b=!0}t.emit(\"plotly_hover\",{points:[f(e,s)],event:a.event}),_=!0}}).on(\"mouseout\",function(r){var n=t._fullLayout,i=t._fullData[p.index];_&&(r.originalEvent=a.event,t.emit(\"plotly_unhover\",{points:[f(e,i)],event:a.event}),_=!1),b&&(o.loneUnhover(n._hoverlayer.node()),b=!1)}).on(\"click\",function(){var r=t._fullLayout,n=t._fullData[p.index];t._dragging||!1===r.hovermode||(t._hoverdata=[f(e,n)],o.click(t,a.event))}),p.pull){var w=+u.castOption(p.pull,e.pts)||0;w>0&&(h+=w*e.pxmid[0],v+=w*e.pxmid[1])}e.cxFinal=h,e.cyFinal=v;var M=p.hole;if(e.v===d.vTotal){var k=\"M\"+(h+e.px0[0])+\",\"+(v+e.px0[1])+s(e.px0,e.pxmid,!0,1)+s(e.pxmid,e.px0,!0,1)+\"Z\";M?x.attr(\"d\",\"M\"+(h+M*e.px0[0])+\",\"+(v+M*e.px0[1])+s(e.px0,e.pxmid,!1,M)+s(e.pxmid,e.px0,!1,M)+\"Z\"+k):x.attr(\"d\",k)}else{var A=s(e.px0,e.px1,!0,1);if(M){var T=1-M;x.attr(\"d\",\"M\"+(h+M*e.px1[0])+\",\"+(v+M*e.px1[1])+s(e.px1,e.px0,!1,M)+\"l\"+T*e.px0[0]+\",\"+T*e.px0[1]+A+\"Z\")}else x.attr(\"d\",\"M\"+h+\",\"+v+\"l\"+e.px0[0]+\",\"+e.px0[1]+A+\"Z\")}var S=u.castOption(p.textposition,e.pts),E=y.selectAll(\"g.slicetext\").data(e.text&&\"none\"!==S?[0]:[]);E.enter().append(\"g\").classed(\"slicetext\",!0),E.exit().remove(),E.each(function(){var r=a.select(this).selectAll(\"text\").data([0]);r.enter().append(\"text\").attr(\"data-notex\",1),r.exit().remove(),r.text(e.text).attr({class:\"slicetext\",transform:\"\",\"text-anchor\":\"middle\"}).call(l.font,\"outside\"===S?p.outsidetextfont:p.insidetextfont).call(c.convertToTspans,t);var o,s=l.bBox(r.node());\"outside\"===S?o=i(s,e):(o=function(t,e,r){var i=Math.sqrt(t.width*t.width+t.height*t.height),a=t.width/t.height,o=Math.PI*Math.min(e.v/r.vTotal,.5),s=1-r.trace.hole,l=n(e,r),c={scale:l*r.r*2/i,rCenter:1-l,rotate:0};if(c.scale>=1)return c;var u=a+1/(2*Math.tan(o)),f=r.r*Math.min(1/(Math.sqrt(u*u+.5)+u),s/(Math.sqrt(a*a+s/2)+a)),h={scale:2*f/t.height,rCenter:Math.cos(f/r.r)-f*a/r.r,rotate:(180/Math.PI*e.midangle+720)%180-90},d=1/a,p=d+1/(2*Math.tan(o)),m=r.r*Math.min(1/(Math.sqrt(p*p+.5)+p),s/(Math.sqrt(d*d+s/2)+d)),g={scale:2*m/t.width,rCenter:Math.cos(m/r.r)-m/a/r.r,rotate:(180/Math.PI*e.midangle+810)%180-90},v=g.scale>h.scale?g:h;return c.scale<1&&v.scale>c.scale?v:c}(s,e,d),\"auto\"===S&&o.scale<1&&(r.call(l.font,p.outsidetextfont),p.outsidetextfont.family===p.insidetextfont.family&&p.outsidetextfont.size===p.insidetextfont.size||(s=l.bBox(r.node())),o=i(s,e)));var u=h+e.pxmid[0]*o.rCenter+(o.x||0),f=v+e.pxmid[1]*o.rCenter+(o.y||0);o.outside&&(e.yLabelMin=f-s.height/2,e.yLabelMid=f,e.yLabelMax=f+s.height/2,e.labelExtraX=0,e.labelExtraY=0,g=!0),r.attr(\"transform\",\"translate(\"+u+\",\"+f+\")\"+(o.scale<1?\"scale(\"+o.scale+\")\":\"\")+(o.rotate?\"rotate(\"+o.rotate+\")\":\"\")+\"translate(\"+-(s.left+s.right)/2+\",\"+-(s.top+s.bottom)/2+\")\")})}}),g&&function(t,e){function r(t,e){return t.pxmid[1]-e.pxmid[1]}function n(t,e){return e.pxmid[1]-t.pxmid[1]}function i(t,r){r||(r={});var n,i,a,s,d=r.labelExtraY+(o?r.yLabelMax:r.yLabelMin),p=o?t.yLabelMin:t.yLabelMax,g=o?t.yLabelMax:t.yLabelMin,v=t.cyFinal+c(t.px0[1],t.px1[1]),y=d-p;if(y*h>0&&(t.labelExtraY=y),Array.isArray(e.pull))for(i=0;i=(u.castOption(e.pull,a.pts)||0)||((t.pxmid[1]-a.pxmid[1])*h>0?(y=a.cyFinal+c(a.px0[1],a.px1[1])-p-t.labelExtraY)*h>0&&(t.labelExtraY+=y):(g+t.labelExtraY-v)*h>0&&(n=3*f*Math.abs(i-m.indexOf(t)),(s=a.cxFinal+l(a.px0[0],a.px1[0])+n-(t.cxFinal+t.pxmid[0])-t.labelExtraX)*f>0&&(t.labelExtraX+=s)))}var a,o,s,l,c,f,h,d,p,m,g,v,y;for(o=0;o<2;o++)for(s=o?r:n,c=o?Math.max:Math.min,h=o?1:-1,a=0;a<2;a++){for(l=a?Math.max:Math.min,f=a?1:-1,(d=t[o][a]).sort(s),p=t[1-o][a],m=p.concat(d),v=[],g=0;gMath.abs(c)?i+=\"l\"+c*t.pxmid[0]/t.pxmid[1]+\",\"+c+\"H\"+(n+t.labelExtraX+o):i+=\"l\"+t.labelExtraX+\",\"+l+\"v\"+(c-l)+\"h\"+o}else i+=\"V\"+(t.yLabelMid+t.labelExtraY)+\"h\"+o;e.append(\"path\").classed(\"textline\",!0).call(s.stroke,p.outsidetextfont.color).attr({\"stroke-width\":Math.min(2,p.outsidetextfont.size/8),d:i,fill:\"none\"})}})})}),setTimeout(function(){h.selectAll(\"tspan\").each(function(){var t=a.select(this);t.attr(\"dy\")&&t.attr(\"dy\",t.attr(\"dy\"))})},0)}},{\"../../components/color\":618,\"../../components/drawing\":643,\"../../components/fx\":660,\"../../lib/svg_text_utils\":766,\"./event_data\":1045,\"./helpers\":1046,d3:128}],1051:[function(t,e,r){\"use strict\";var n=t(\"d3\"),i=t(\"./style_one\");e.exports=function(t){t._fullLayout._pielayer.selectAll(\".trace\").each(function(t){var e=t[0].trace,r=n.select(this);r.style({opacity:e.opacity}),r.selectAll(\"path.surface\").each(function(t){n.select(this).call(i,t,e)})})}},{\"./style_one\":1052,d3:128}],1052:[function(t,e,r){\"use strict\";var n=t(\"../../components/color\"),i=t(\"./helpers\").castOption;e.exports=function(t,e,r){var a=r.marker.line,o=i(a.color,e.pts)||n.defaultLine,s=i(a.width,e.pts)||0;t.style({\"stroke-width\":s}).call(n.fill,e.color).call(n.stroke,o)}},{\"../../components/color\":618,\"./helpers\":1046}],1053:[function(t,e,r){\"use strict\";var n=t(\"../scatter/attributes\");e.exports={x:n.x,y:n.y,xy:{valType:\"data_array\",editType:\"calc\"},indices:{valType:\"data_array\",editType:\"calc\"},xbounds:{valType:\"data_array\",editType:\"calc\"},ybounds:{valType:\"data_array\",editType:\"calc\"},text:n.text,marker:{color:{valType:\"color\",arrayOk:!1,editType:\"calc\"},opacity:{valType:\"number\",min:0,max:1,dflt:1,arrayOk:!1,editType:\"calc\"},blend:{valType:\"boolean\",dflt:null,editType:\"calc\"},sizemin:{valType:\"number\",min:.1,max:2,dflt:.5,editType:\"calc\"},sizemax:{valType:\"number\",min:.1,dflt:20,editType:\"calc\"},border:{color:{valType:\"color\",arrayOk:!1,editType:\"calc\"},arearatio:{valType:\"number\",min:0,max:1,dflt:0,editType:\"calc\"},editType:\"calc\"},editType:\"calc\"}}},{\"../scatter/attributes\":1066}],1054:[function(t,e,r){\"use strict\";function n(t,e){this.scene=t,this.uid=e,this.type=\"pointcloud\",this.pickXData=[],this.pickYData=[],this.xData=[],this.yData=[],this.textLabels=[],this.color=\"rgb(0, 0, 0)\",this.name=\"\",this.hoverinfo=\"all\",this.idToIndex=new Int32Array(0),this.bounds=[0,0,0,0],this.pointcloudOptions={positions:new Float32Array(0),idToIndex:this.idToIndex,sizemin:.5,sizemax:12,color:[0,0,0,1],areaRatio:1,borderColor:[0,0,0,1]},this.pointcloud=i(t.glplot,this.pointcloudOptions),this.pointcloud._trace=this}var i=t(\"gl-pointcloud2d\"),a=t(\"../../lib/str2rgbarray\"),o=t(\"../scatter/get_trace_color\"),s=[\"xaxis\",\"yaxis\"],l=n.prototype;l.handlePick=function(t){var e=this.idToIndex[t.pointId];return{trace:this,dataCoord:t.dataCoord,traceCoord:this.pickXYData?[this.pickXYData[2*e],this.pickXYData[2*e+1]]:[this.pickXData[e],this.pickYData[e]],textLabel:Array.isArray(this.textLabels)?this.textLabels[e]:this.textLabels,color:this.color,name:this.name,pointIndex:e,hoverinfo:this.hoverinfo}},l.update=function(t){this.index=t.index,this.textLabels=t.text,this.name=t.name,this.hoverinfo=t.hoverinfo,this.bounds=[1/0,1/0,-1/0,-1/0],this.updateFast(t),this.color=o(t,{})},l.updateFast=function(t){var e,r,n,i,o,s,l=this.xData=this.pickXData=t.x,c=this.yData=this.pickYData=t.y,u=this.pickXYData=t.xy,f=t.xbounds&&t.ybounds,h=t.indices,d=this.bounds;if(u){if(n=u,e=u.length>>>1,f)d[0]=t.xbounds[0],d[2]=t.xbounds[1],d[1]=t.ybounds[0],d[3]=t.ybounds[1];else for(s=0;sd[2]&&(d[2]=i),od[3]&&(d[3]=o);if(h)r=h;else for(r=new Int32Array(e),s=0;sd[2]&&(d[2]=i),od[3]&&(d[3]=o);this.idToIndex=r,this.pointcloudOptions.idToIndex=r,this.pointcloudOptions.positions=n;var p=a(t.marker.color),m=a(t.marker.border.color),g=t.opacity*t.marker.opacity;p[3]*=g,this.pointcloudOptions.color=p;var v=t.marker.blend;if(null===v){v=l.length<100||c.length<100}this.pointcloudOptions.blend=v,m[3]*=g,this.pointcloudOptions.borderColor=m;var y=t.marker.sizemin,x=Math.max(t.marker.sizemax,t.marker.sizemin);this.pointcloudOptions.sizeMin=y,this.pointcloudOptions.sizeMax=x,this.pointcloudOptions.areaRatio=t.marker.border.arearatio,this.pointcloud.update(this.pointcloudOptions),this.expandAxesFast(d,x/2)},l.expandAxesFast=function(t,e){for(var r,n,i,a=e||.5,o=0;o<2;o++)(n=(r=this.scene[s[o]])._min)||(n=[]),n.push({val:t[o],pad:a}),(i=r._max)||(i=[]),i.push({val:t[o+2],pad:a})},l.dispose=function(){this.pointcloud.dispose()},e.exports=function(t,e){var r=new n(t,e.uid);return r.update(e),r}},{\"../../lib/str2rgbarray\":765,\"../scatter/get_trace_color\":1076,\"gl-pointcloud2d\":235}],1055:[function(t,e,r){\"use strict\";var n=t(\"../../lib\"),i=t(\"./attributes\");e.exports=function(t,e,r){function a(r,a){return n.coerce(t,e,i,r,a)}a(\"x\"),a(\"y\"),a(\"xbounds\"),a(\"ybounds\"),t.xy&&t.xy instanceof Float32Array&&(e.xy=t.xy),t.indices&&t.indices instanceof Int32Array&&(e.indices=t.indices),a(\"text\"),a(\"marker.color\",r),a(\"marker.opacity\"),a(\"marker.blend\"),a(\"marker.sizemin\"),a(\"marker.sizemax\"),a(\"marker.border.color\",r),a(\"marker.border.arearatio\")}},{\"../../lib\":743,\"./attributes\":1053}],1056:[function(t,e,r){\"use strict\";var n={};n.attributes=t(\"./attributes\"),n.supplyDefaults=t(\"./defaults\"),n.calc=t(\"../scatter3d/calc\"),n.plot=t(\"./convert\"),n.moduleType=\"trace\",n.name=\"pointcloud\",n.basePlotModule=t(\"../../plots/gl2d\"),n.categories=[\"gl\",\"gl2d\",\"showLegend\"],n.meta={},e.exports=n},{\"../../plots/gl2d\":829,\"../scatter3d/calc\":1092,\"./attributes\":1053,\"./convert\":1054,\"./defaults\":1055}],1057:[function(t,e,r){\"use strict\";var n=t(\"../../plots/font_attributes\"),i=t(\"../../plots/attributes\"),a=t(\"../../components/color/attributes\"),o=t(\"../../components/fx/attributes\"),s=t(\"../../plots/domain_attributes\"),l=t(\"../../lib/extend\").extendFlat,c=t(\"../../plot_api/edit_types\").overrideAll;e.exports=c({hoverinfo:l({},i.hoverinfo,{flags:[\"label\",\"text\",\"value\",\"percent\",\"name\"]}),hoverlabel:o.hoverlabel,domain:s({name:\"sankey\",trace:!0}),orientation:{valType:\"enumerated\",values:[\"v\",\"h\"],dflt:\"h\"},valueformat:{valType:\"string\",dflt:\".3s\"},valuesuffix:{valType:\"string\",dflt:\"\"},arrangement:{valType:\"enumerated\",values:[\"snap\",\"perpendicular\",\"freeform\",\"fixed\"],dflt:\"snap\"},textfont:n({}),node:{label:{valType:\"data_array\",dflt:[]},color:{valType:\"color\",arrayOk:!0},line:{color:{valType:\"color\",dflt:a.defaultLine,arrayOk:!0},width:{valType:\"number\",min:0,dflt:.5,arrayOk:!0}},pad:{valType:\"number\",arrayOk:!1,min:0,dflt:20},thickness:{valType:\"number\",arrayOk:!1,min:1,dflt:20}},link:{label:{valType:\"data_array\",dflt:[]},color:{valType:\"color\",arrayOk:!0},line:{color:{valType:\"color\",dflt:a.defaultLine,arrayOk:!0},width:{valType:\"number\",min:0,dflt:0,arrayOk:!0}},source:{valType:\"data_array\",dflt:[]},target:{valType:\"data_array\",dflt:[]},value:{valType:\"data_array\",dflt:[]}}},\"calc\",\"nested\")},{\"../../components/color/attributes\":617,\"../../components/fx/attributes\":652,\"../../lib/extend\":732,\"../../plot_api/edit_types\":773,\"../../plots/attributes\":787,\"../../plots/domain_attributes\":815,\"../../plots/font_attributes\":816}],1058:[function(t,e,r){\"use strict\";var n=t(\"../../plot_api/edit_types\").overrideAll,i=t(\"../../plots/get_data\").getModuleCalcData,a=t(\"./plot\"),o=t(\"../../components/fx/layout_attributes\");r.name=\"sankey\",r.baseLayoutAttrOverrides=n({hoverlabel:o.hoverlabel},\"plot\",\"nested\"),r.plot=function(t){var e=i(t.calcdata,\"sankey\");a(t,e)},r.clean=function(t,e,r,n){var i=n._has&&n._has(\"sankey\"),a=e._has&&e._has(\"sankey\");i&&!a&&n._paperdiv.selectAll(\".sankey\").remove()}},{\"../../components/fx/layout_attributes\":661,\"../../plot_api/edit_types\":773,\"../../plots/get_data\":826,\"./plot\":1063}],1059:[function(t,e,r){\"use strict\";var n=t(\"strongly-connected-components\"),i=t(\"../../lib\"),a=t(\"../../lib/gup\").wrap;e.exports=function(t,e){return function(t,e,r){for(var i=t.map(function(){return[]}),a=0;a1})}(e.node.label,e.link.source,e.link.target)&&(i.error(\"Circularity is present in the Sankey data. Removing all nodes and links.\"),e.link.label=[],e.link.source=[],e.link.target=[],e.link.value=[],e.link.color=[],e.node.label=[],e.node.color=[]),a({link:e.link,node:e.node})}},{\"../../lib\":743,\"../../lib/gup\":740,\"strongly-connected-components\":537}],1060:[function(t,e,r){\"use strict\";e.exports={nodeTextOffsetHorizontal:4,nodeTextOffsetVertical:3,nodePadAcross:10,sankeyIterations:50,forceIterations:5,forceTicksPerFrame:10,duration:500,ease:\"cubic-in-out\",cn:{sankey:\"sankey\",sankeyLinks:\"sankey-links\",sankeyLink:\"sankey-link\",sankeyNodeSet:\"sankey-node-set\",sankeyNode:\"sankey-node\",nodeRect:\"node-rect\",nodeCapture:\"node-capture\",nodeCentered:\"node-entered\",nodeLabelGuide:\"node-label-guide\",nodeLabel:\"node-label\",nodeLabelTextPath:\"node-label-text-path\"}}},{}],1061:[function(t,e,r){\"use strict\";var n=t(\"../../lib\"),i=t(\"./attributes\"),a=t(\"../../components/color\"),o=t(\"tinycolor2\");e.exports=function(t,e,r,s){function l(r,a){return n.coerce(t,e,i,r,a)}l(\"node.label\"),l(\"node.pad\"),l(\"node.thickness\"),l(\"node.line.color\"),l(\"node.line.width\");var c=s.colorway;l(\"node.color\",e.node.label.map(function(t,e){return a.addOpacity(function(t){return c[t%c.length]}(e),.8)})),l(\"link.label\"),l(\"link.source\"),l(\"link.target\"),l(\"link.value\"),l(\"link.line.color\"),l(\"link.line.width\"),l(\"link.color\",e.link.value.map(function(){return o(s.paper_bgcolor).getLuminance()<.333?\"rgba(255, 255, 255, 0.6)\":\"rgba(0, 0, 0, 0.2)\"})),l(\"domain.x\"),l(\"domain.y\"),l(\"orientation\"),l(\"valueformat\"),l(\"valuesuffix\"),l(\"arrangement\"),n.coerceFont(l,\"textfont\",n.extendFlat({},s.font));e.node.label.some(function(t,r){return-1===e.link.source.indexOf(r)&&-1===e.link.target.indexOf(r)})&&n.warn(\"Some of the nodes are neither sources nor targets, they will not be displayed.\")}},{\"../../components/color\":618,\"../../lib\":743,\"./attributes\":1057,tinycolor2:546}],1062:[function(t,e,r){\"use strict\";var n={};n.attributes=t(\"./attributes\"),n.supplyDefaults=t(\"./defaults\"),n.calc=t(\"./calc\"),n.plot=t(\"./plot\"),n.moduleType=\"trace\",n.name=\"sankey\",n.basePlotModule=t(\"./base_plot\"),n.categories=[\"noOpacity\"],n.meta={},e.exports=n},{\"./attributes\":1057,\"./base_plot\":1058,\"./calc\":1059,\"./defaults\":1061,\"./plot\":1063}],1063:[function(t,e,r){\"use strict\";function n(t){return\"\"!==t}function i(t,e){return t.filter(function(t){return t.key===e.traceId})}function a(t,e){p.select(t).select(\"path\").style(\"fill-opacity\",e),p.select(t).select(\"rect\").style(\"fill-opacity\",e)}function o(t){p.select(t).select(\"text.name\").style(\"fill\",\"black\")}function s(t){return function(e){return-1!==t.node.sourceLinks.indexOf(e.link)||-1!==t.node.targetLinks.indexOf(e.link)}}function l(t){return function(e){return-1!==e.node.sourceLinks.indexOf(t.link)||-1!==e.node.targetLinks.indexOf(t.link)}}function c(t,e,r){e&&r&&i(r,e).selectAll(\".\"+x.sankeyLink).filter(s(e)).call(f.bind(0,e,r,!1))}function u(t,e,r){e&&r&&i(r,e).selectAll(\".\"+x.sankeyLink).filter(s(e)).call(h.bind(0,e,r,!1))}function f(t,e,r,n){var a=n.datum().link.label;n.style(\"fill-opacity\",.4),a&&i(e,t).selectAll(\".\"+x.sankeyLink).filter(function(t){return t.link.label===a}).style(\"fill-opacity\",.4),r&&i(e,t).selectAll(\".\"+x.sankeyNode).filter(l(t)).call(c)}function h(t,e,r,n){var a=n.datum().link.label;n.style(\"fill-opacity\",function(t){return t.tinyColorAlpha}),a&&i(e,t).selectAll(\".\"+x.sankeyLink).filter(function(t){return t.link.label===a}).style(\"fill-opacity\",function(t){return t.tinyColorAlpha}),r&&i(e,t).selectAll(x.sankeyNode).filter(l(t)).call(u)}function d(t,e){var r=t.hoverlabel||{},n=y.nestedProperty(r,e).get();return!Array.isArray(n)&&n}var p=t(\"d3\"),m=t(\"./render\"),g=t(\"../../components/fx\"),v=t(\"../../components/color\"),y=t(\"../../lib\"),x=t(\"./constants\").cn,b=y._;e.exports=function(t,e){var r=t._fullLayout,i=r._paper,s=r._size,l=b(t,\"source:\")+\" \",y=b(t,\"target:\")+\" \",_=b(t,\"incoming flow count:\")+\" \",w=b(t,\"outgoing flow count:\")+\" \";m(i,e,{width:s.w,height:s.h,margin:{t:s.t,r:s.r,b:s.b,l:s.l}},{linkEvents:{hover:function(e,r,n){p.select(e).call(f.bind(0,r,n,!0)),t.emit(\"plotly_hover\",{event:p.event,points:[r.link]})},follow:function(e,i){var s=i.link.trace,c=t._fullLayout._paperdiv.node().getBoundingClientRect(),u=e.getBoundingClientRect(),f=u.left+u.width/2,h=u.top+u.height/2,m=g.loneHover({x:f-c.left,y:h-c.top,name:p.format(i.valueFormat)(i.link.value)+i.valueSuffix,text:[i.link.label||\"\",l+i.link.source.label,y+i.link.target.label].filter(n).join(\"
\"),color:d(s,\"bgcolor\")||v.addOpacity(i.tinyColorHue,1),borderColor:d(s,\"bordercolor\"),fontFamily:d(s,\"font.family\"),fontSize:d(s,\"font.size\"),fontColor:d(s,\"font.color\"),idealAlign:p.event.x\"),color:d(s,\"bgcolor\")||i.tinyColorHue,borderColor:d(s,\"bordercolor\"),fontFamily:d(s,\"font.family\"),fontSize:d(s,\"font.size\"),fontColor:d(s,\"font.color\"),idealAlign:\"left\"},{container:r._hoverlayer.node(),outerContainer:r._paper.node(),gd:t});a(v,.85),o(v)},unhover:function(e,n,i){p.select(e).call(u,n,i),t.emit(\"plotly_unhover\",{event:p.event,points:[n.node]}),g.loneUnhover(r._hoverlayer.node())},select:function(e,r,n){var i=r.node;i.originalEvent=p.event,t._hoverdata=[i],p.select(e).call(u,r,n),g.click(t,{target:!0})}}})}},{\"../../components/color\":618,\"../../components/fx\":660,\"../../lib\":743,\"./constants\":1060,\"./render\":1064,d3:128}],1064:[function(t,e,r){\"use strict\";function n(t){t.lastDraggedX=t.x,t.lastDraggedY=t.y}function i(t){return function(e){return e.node.originalX===t.node.originalX}}function a(t){for(var e=0;e1||t.linkLineWidth>0}function h(t){return\"translate(\"+t.translateX+\",\"+t.translateY+\")\"+(t.horizontal?\"matrix(1 0 0 1 0 0)\":\"matrix(0 1 1 0 0 0)\")}function d(t){return\"translate(\"+(t.horizontal?0:t.labelY)+\" \"+(t.horizontal?t.labelY:0)+\")\"}function p(t){return w.svg.line()([[t.horizontal?t.left?-t.sizeAcross:t.visibleWidth+_.nodeTextOffsetHorizontal:_.nodeTextOffsetHorizontal,0],[t.horizontal?t.left?-_.nodeTextOffsetHorizontal:t.sizeAcross:t.visibleHeight-_.nodeTextOffsetHorizontal,0]])}function m(t){return t.horizontal?\"matrix(1 0 0 1 0 0)\":\"matrix(0 1 1 0 0 0)\"}function g(t){return t.horizontal?\"scale(1 1)\":\"scale(-1 1)\"}function v(t){return t.darkBackground&&!t.horizontal?\"rgb(255,255,255)\":\"rgb(0,0,0)\"}function y(t){return t.horizontal&&t.left?\"100%\":\"0%\"}function x(t,e,r){t.on(\".basic\",null).on(\"mouseover.basic\",function(t){t.interactionState.dragInProgress||(r.hover(this,t,e),t.interactionState.hovered=[this,t])}).on(\"mousemove.basic\",function(t){t.interactionState.dragInProgress||(r.follow(this,t),t.interactionState.hovered=[this,t])}).on(\"mouseout.basic\",function(t){t.interactionState.dragInProgress||(r.unhover(this,t,e),t.interactionState.hovered=!1)}).on(\"click.basic\",function(t){t.interactionState.hovered&&(r.unhover(this,t,e),t.interactionState.hovered=!1),t.interactionState.dragInProgress||r.select(this,t,e)})}function b(t,e,r){var a=w.behavior.drag().origin(function(t){return t.node}).on(\"dragstart\",function(a){if(\"fixed\"!==a.arrangement&&(E.raiseToTop(this),a.interactionState.dragInProgress=a.node,n(a.node),a.interactionState.hovered&&(r.nodeEvents.unhover.apply(0,a.interactionState.hovered),a.interactionState.hovered=!1),\"snap\"===a.arrangement)){var o=a.traceId+\"|\"+Math.floor(a.node.originalX);a.forceLayouts[o]?a.forceLayouts[o].alpha(1):function(t,e,r){var n=r.sankey.nodes().filter(function(t){return t.originalX===r.node.originalX});r.forceLayouts[e]=S.forceSimulation(n).alphaDecay(0).force(\"collide\",S.forceCollide().radius(function(t){return t.dy/2+r.nodePad/2}).strength(1).iterations(_.forceIterations)).force(\"constrain\",function(t,e,r,n){return function(){for(var t=0,i=0;i0&&n.forceLayouts[e].alpha(0)}}(0,e,n,r)).stop()}(0,o,a),function(t,e,r,n){window.requestAnimationFrame(function a(){for(var o=0;o<_.forceTicksPerFrame;o++)r.forceLayouts[n].tick();r.sankey.relayout(),c(t.filter(i(r)),e),r.forceLayouts[n].alpha()>0&&window.requestAnimationFrame(a)})}(t,e,a,o)}}).on(\"drag\",function(r){if(\"fixed\"!==r.arrangement){var a=w.event.x,o=w.event.y;\"snap\"===r.arrangement?(r.node.x=a,r.node.y=o):(\"freeform\"===r.arrangement&&(r.node.x=a),r.node.y=Math.max(r.node.dy/2,Math.min(r.size-r.node.dy/2,o))),n(r.node),\"snap\"!==r.arrangement&&(r.sankey.relayout(),c(t.filter(i(r)),e))}}).on(\"dragend\",function(t){t.interactionState.dragInProgress=!1});t.on(\".drag\",null).call(a)}var _=t(\"./constants\"),w=t(\"d3\"),M=t(\"tinycolor2\"),k=t(\"../../components/color\"),A=t(\"../../components/drawing\"),T=t(\"@plotly/d3-sankey\").sankey,S=t(\"d3-force\"),E=t(\"../../lib\"),L=t(\"../../lib/gup\").keyFun,C=t(\"../../lib/gup\").repeat,z=t(\"../../lib/gup\").unwrap;e.exports=function(t,e,r,n){var i=t.selectAll(\".\"+_.cn.sankey).data(e.filter(function(t){return z(t).trace.visible}).map(function(t,e,r){for(var n,i=z(e).trace,o=i.domain,s=i.node,l=i.link,c=i.arrangement,u=\"h\"===i.orientation,f=i.node.pad,h=i.node.thickness,d=i.node.line.color,p=i.node.line.width,m=i.link.line.color,g=i.link.line.width,v=i.valueformat,y=i.valuesuffix,x=i.textfont,b=t.width*(o.x[1]-o.x[0]),w=t.height*(o.y[1]-o.y[0]),M=s.label.map(function(t,e){return{pointNumber:e,label:t,color:E.isArray(s.color)?s.color[e]:s.color}}),k=l.value.map(function(t,e){return{pointNumber:e,label:l.label[e],color:E.isArray(l.color)?l.color[e]:l.color,source:l.source[e],target:l.target[e],value:t}}),A=T().size(u?[b,w]:[w,b]).nodeWidth(h).nodePadding(f).nodes(M).links(k).layout(_.sankeyIterations),S=A.nodes(),L=0;L5?t.node.label:\"\"}).attr(\"text-anchor\",function(t){return t.horizontal&&t.left?\"end\":\"start\"}),R.transition().ease(_.ease).duration(_.duration).attr(\"startOffset\",y).style(\"fill\",v)}},{\"../../components/color\":618,\"../../components/drawing\":643,\"../../lib\":743,\"../../lib/gup\":740,\"./constants\":1060,\"@plotly/d3-sankey\":41,d3:128,\"d3-force\":124,tinycolor2:546}],1065:[function(t,e,r){\"use strict\";var n=t(\"../../lib\");e.exports=function(t,e){for(var r=0;re&&l.splice(e,l.length-e),l.map(r)}return r(n.size)}}var i=t(\"fast-isnumeric\"),a=t(\"../../plots/cartesian/axes\"),o=t(\"../../constants/numerical\").BADNUM,s=t(\"./subtypes\"),l=t(\"./colorscale_calc\"),c=t(\"./arrays_to_calcdata\"),u=t(\"./calc_selection\");e.exports={calc:function(t,e){var r=a.getFromId(t,e.xaxis||\"x\"),f=a.getFromId(t,e.yaxis||\"y\"),h=r.makeCalcdata(e,\"x\"),d=f.makeCalcdata(e,\"y\"),p=Math.min(h.length,d.length);r._minDtick=0,f._minDtick=0,h.length>p&&h.splice(p,h.length-p),d.length>p&&d.splice(p,d.length-p);var m={padded:!0},g={padded:!0},v=n(e,p);v&&(m.ppad=g.ppad=v),!(\"tozerox\"===e.fill||\"tonextx\"===e.fill&&t.firstscatter)||h[0]===h[p-1]&&d[0]===d[p-1]?e.error_y.visible||-1===[\"tonexty\",\"tozeroy\"].indexOf(e.fill)&&(s.hasMarkers(e)||s.hasText(e))||(m.padded=!1,m.ppad=0):m.tozero=!0,!(\"tozeroy\"===e.fill||\"tonexty\"===e.fill&&t.firstscatter)||h[0]===h[p-1]&&d[0]===d[p-1]?-1!==[\"tonextx\",\"tozerox\"].indexOf(e.fill)&&(g.padded=!1):g.tozero=!0,a.expand(r,h,m),a.expand(f,d,g);for(var y=new Array(p),x=0;x=0;i--){var a=t[i];if(\"scatter\"===a.type&&a.xaxis===r.xaxis&&a.yaxis===r.yaxis){a.opacity=void 0;break}}}}}},{}],1070:[function(t,e,r){\"use strict\";var n=t(\"fast-isnumeric\"),i=t(\"../../lib\"),a=t(\"../../plots/plots\"),o=t(\"../../components/colorscale\"),s=t(\"../../components/colorbar/draw\");e.exports=function(t,e){var r=e[0].trace,l=r.marker,c=\"cb\"+r.uid;if(t._fullLayout._infolayer.selectAll(\".\"+c).remove(),void 0!==l&&l.showscale){var u=l.color,f=l.cmin,h=l.cmax;n(f)||(f=i.aggNums(Math.min,null,u)),n(h)||(h=i.aggNums(Math.max,null,u));var d=e[0].t.cb=s(t,c),p=o.makeColorScaleFunc(o.extractScale(l.colorscale,f,h),{noNumericCheck:!0});d.fillcolor(p).filllevels({start:f,end:h,size:(h-f)/254}).options(l.colorbar)()}else a.autoMargin(t,c)}},{\"../../components/colorbar/draw\":622,\"../../components/colorscale\":633,\"../../lib\":743,\"../../plots/plots\":852,\"fast-isnumeric\":140}],1071:[function(t,e,r){\"use strict\";var n=t(\"../../components/colorscale/has_colorscale\"),i=t(\"../../components/colorscale/calc\"),a=t(\"./subtypes\");e.exports=function(t){a.hasLines(t)&&n(t,\"line\")&&i(t,t.line.color,\"line\",\"c\"),a.hasMarkers(t)&&(n(t,\"marker\")&&i(t,t.marker.color,\"marker\",\"c\"),n(t,\"marker.line\")&&i(t,t.marker.line.color,\"marker.line\",\"c\"))}},{\"../../components/colorscale/calc\":625,\"../../components/colorscale/has_colorscale\":632,\"./subtypes\":1088}],1072:[function(t,e,r){\"use strict\";e.exports={PTS_LINESONLY:20,minTolerance:.2,toleranceGrowth:10,maxScreensAway:20}},{}],1073:[function(t,e,r){\"use strict\";var n=t(\"../../lib\"),i=t(\"./attributes\"),a=t(\"./constants\"),o=t(\"./subtypes\"),s=t(\"./xy_defaults\"),l=t(\"./marker_defaults\"),c=t(\"./line_defaults\"),u=t(\"./line_shape_defaults\"),f=t(\"./text_defaults\"),h=t(\"./fillcolor_defaults\"),d=t(\"../../components/errorbars/defaults\");e.exports=function(t,e,r,p){function m(r,a){return n.coerce(t,e,i,r,a)}var g=s(t,e,p,m),v=gH!=(F=z[L][1])>=H&&(I=z[L-1][0],P=z[L][0],F-O&&(D=I+(P-I)*(H-O)/(F-O),B=Math.min(B,D),U=Math.max(U,D)));B=Math.max(B,0),U=Math.min(U,d._length);var G=s.defaultLine;return s.opacity(h.fillcolor)?G=h.fillcolor:s.opacity((h.line||{}).color)&&(G=h.line.color),n.extendFlat(t,{distance:c+10,x0:B,x1:U,y0:H,y1:H,color:G}),delete t.index,h.text&&!Array.isArray(h.text)?t.text=String(h.text):t.text=h.name,[t]}}}},{\"../../components/color\":618,\"../../components/errorbars\":649,\"../../components/fx\":660,\"../../lib\":743,\"./fill_hover_text\":1074,\"./get_trace_color\":1076}],1078:[function(t,e,r){\"use strict\";var n={},i=t(\"./subtypes\");n.hasLines=i.hasLines,n.hasMarkers=i.hasMarkers,n.hasText=i.hasText,n.isBubble=i.isBubble,n.attributes=t(\"./attributes\"),n.supplyDefaults=t(\"./defaults\"),n.cleanData=t(\"./clean_data\"),n.calc=t(\"./calc\").calc,n.arraysToCalcdata=t(\"./arrays_to_calcdata\"),n.plot=t(\"./plot\"),n.colorbar=t(\"./colorbar\"),n.style=t(\"./style\").style,n.hoverPoints=t(\"./hover\"),n.selectPoints=t(\"./select\"),n.animatable=!0,n.moduleType=\"trace\",n.name=\"scatter\",n.basePlotModule=t(\"../../plots/cartesian\"),n.categories=[\"cartesian\",\"symbols\",\"markerColorscale\",\"errorBarsOK\",\"showLegend\",\"scatter-like\"],n.meta={},e.exports=n},{\"../../plots/cartesian\":800,\"./arrays_to_calcdata\":1065,\"./attributes\":1066,\"./calc\":1067,\"./clean_data\":1069,\"./colorbar\":1070,\"./defaults\":1073,\"./hover\":1077,\"./plot\":1085,\"./select\":1086,\"./style\":1087,\"./subtypes\":1088}],1079:[function(t,e,r){\"use strict\";var n=t(\"../../components/colorscale/has_colorscale\"),i=t(\"../../components/colorscale/defaults\");e.exports=function(t,e,r,a,o,s){var l=(t.marker||{}).color;if(o(\"line.color\",r),n(t,\"line\"))i(t,e,a,o,{prefix:\"line.\",cLetter:\"c\"});else{o(\"line.color\",!Array.isArray(l)&&l||r)}o(\"line.width\"),(s||{}).noDash||o(\"line.dash\")}},{\"../../components/colorscale/defaults\":628,\"../../components/colorscale/has_colorscale\":632}],1080:[function(t,e,r){\"use strict\";var n=t(\"../../constants/numerical\").BADNUM,i=t(\"../../lib\"),a=i.segmentsIntersect,o=i.constrain,s=t(\"./constants\");e.exports=function(t,e){function r(e){var r=t[e],i=P.c2p(r.x),a=O.c2p(r.y);return i===n||a===n?r.intoCenter||!1:[i,a]}function l(t){var e=t[0]/P._length,r=t[1]/O._length;return(1+s.toleranceGrowth*Math.max(0,-e,e-1,-r,r-1))*N}function c(t,e){var r=t[0]-e[0],n=t[1]-e[1];return Math.sqrt(r*r+n*n)}function u(t,e){for(var r=[],n=0,i=0;i<4;i++){var o=nt[i],s=a(t[0],t[1],e[0],e[1],o[0],o[1],o[2],o[3]);s&&(!n||Math.abs(s.x-r[0][0])>1||Math.abs(s.y-r[0][1])>1)&&(s=[s.x,s.y],n&&c(s,t)tt||t[1]rt)return[o(t[0],$,tt),o(t[1],et,rt)]}function h(t,e){return t[0]===e[0]&&(t[0]===$||t[0]===tt)||(t[1]===e[1]&&(t[1]===et||t[1]===rt)||void 0)}function d(t,e){var r=[],n=f(t),i=f(e);return n&&i&&h(n,i)?r:(n&&r.push(n),i&&r.push(i),r)}function p(t,e,r){return function(n,a){var o=f(n),s=f(a),l=[];if(o&&s&&h(o,s))return l;o&&l.push(o),s&&l.push(s);var c=2*i.constrain((n[t]+a[t])/2,e,r)-((o||n)[t]+(s||a)[t]);if(c){(o&&s?c>0==o[t]>s[t]?o:s:o||s)[t]+=c}return l}}function m(t){var e=t[0],r=t[1],n=e===q[H-1][0],i=r===q[H-1][1];if(!n||!i)if(H>1){var a=e===q[H-2][0],o=r===q[H-2][1];n&&(e===$||e===tt)&&a?o?H--:q[H-1]=t:i&&(r===et||r===rt)&&o?a?H--:q[H-1]=t:q[H++]=t}else q[H++]=t}function g(t){q[H-1][0]!==t[0]&&q[H-1][1]!==t[1]&&m([W,X]),m(t),Z=null,W=X=0}function v(t){if(G=t[0]<$?$:t[0]>tt?tt:0,Y=t[1]rt?rt:0,G||Y){if(H)if(Z){var e=K(Z,t);e.length>1&&(g(e[0]),q[H++]=e[1])}else J=K(q[H-1],t)[0],q[H++]=J;else q[H++]=[G||t[0],Y||t[1]];var r=q[H-1];G&&Y&&(r[0]!==G||r[1]!==Y)?(Z&&(W!==G&&X!==Y?m(W&&X?function(t,e){var r=e[0]-t[0],n=(e[1]-t[1])/r;return(t[1]*e[0]-e[1]*t[0])/r>0?[n>0?$:tt,rt]:[n>0?tt:$,et]}(Z,t):[W||G,X||Y]):W&&X&&m([W,X])),m([G,Y])):W-G&&X-Y&&m([G||W,Y||X]),Z=t,W=G,X=Y}else Z&&g(K(Z,t)[0]),q[H++]=t}var y,x,b,_,w,M,k,A,T,S,E,L,C,z,D,I,P=e.xaxis,O=e.yaxis,F=e.simplify,R=e.connectGaps,N=e.baseTolerance,j=e.shape,B=\"linear\"===j,U=[],V=s.minTolerance,q=new Array(t.length),H=0;F||(N=V=-1);var G,Y,W,X,Z,J,K,Q=s.maxScreensAway,$=-P._length*Q,tt=P._length*(1+Q),et=-O._length*Q,rt=O._length*(1+Q),nt=[[$,et,tt,et],[tt,et,tt,rt],[tt,rt,$,rt],[$,rt,$,et]];for(\"linear\"===j||\"spline\"===j?K=u:\"hv\"===j||\"vh\"===j?K=d:\"hvh\"===j?K=p(0,$,tt):\"vhv\"===j&&(K=p(1,et,rt)),y=0;yl(M))break;b=M,(C=T[0]*A[0]+T[1]*A[1])>E?(E=C,_=M,k=!1):C=t.length||!M)break;v(M),x=M}}else v(_)}Z&&m([W||Z[0],X||Z[1]]),U.push(q.slice(0,H))}return U}},{\"../../constants/numerical\":721,\"../../lib\":743,\"./constants\":1072}],1081:[function(t,e,r){\"use strict\";e.exports=function(t,e,r){\"spline\"===r(\"line.shape\")&&r(\"line.smoothing\")}},{}],1082:[function(t,e,r){\"use strict\";e.exports=function(t,e,r){var n,i,a=null;for(i=0;i0?Math.max(e,i):0}}},{\"fast-isnumeric\":140}],1084:[function(t,e,r){\"use strict\";var n=t(\"../../components/color\"),i=t(\"../../components/colorscale/has_colorscale\"),a=t(\"../../components/colorscale/defaults\"),o=t(\"./subtypes\");e.exports=function(t,e,r,s,l,c){var u=o.isBubble(t),f=(t.line||{}).color;if(c=c||{},f&&(r=f),l(\"marker.symbol\"),l(\"marker.opacity\",u?.7:1),l(\"marker.size\"),l(\"marker.color\",r),i(t,\"marker\")&&a(t,e,s,l,{prefix:\"marker.\",cLetter:\"c\"}),c.noSelect||(l(\"selected.marker.color\"),l(\"unselected.marker.color\"),l(\"selected.marker.size\"),l(\"unselected.marker.size\")),c.noLine||(l(\"marker.line.color\",f&&!Array.isArray(f)&&e.marker.color!==f?f:u?n.background:n.defaultLine),i(t,\"marker.line\")&&a(t,e,s,l,{prefix:\"marker.line.\",cLetter:\"c\"}),l(\"marker.line.width\",u?1:0)),u&&(l(\"marker.sizeref\"),l(\"marker.sizemin\"),l(\"marker.sizemode\")),c.gradient){\"none\"!==l(\"marker.gradient.type\")&&l(\"marker.gradient.color\")}}},{\"../../components/color\":618,\"../../components/colorscale/defaults\":628,\"../../components/colorscale/has_colorscale\":632,\"./subtypes\":1088}],1085:[function(t,e,r){\"use strict\";function n(t,e,r,n,u,h,d){function p(t){return w?t.transition():t}function m(t){p(t).attr(\"d\",\"M0,0Z\")}function g(t){return t.filter(function(t){return t.vis})}function v(t){return t.id}function y(){return!1}function x(e){var n,s,c=e[0].trace,u=i.select(this),f=l.hasMarkers(c),h=l.hasText(c),d=function(t){if(t.ids)return v}(c),m=y,x=y;f&&(m=c.marker.maxdisplayed||c._needsCull?g:a.identity),h&&(x=c.marker.maxdisplayed||c._needsCull?g:a.identity);var b=(n=u.selectAll(\"path.point\").data(m,d)).enter().append(\"path\").classed(\"point\",!0);w&&b.call(o.pointStyle,c,t).call(o.translatePoints,M,k).style(\"opacity\",0).transition().style(\"opacity\",1);var _=f&&o.tryColorscale(c.marker,\"\"),A=f&&o.tryColorscale(c.marker,\"line\");n.order(),n.each(function(e){var n=i.select(this),a=p(n);(s=o.translatePoint(e,a,M,k))?(o.singlePointStyle(e,a,c,_,A,t),r.layerClipId&&o.hideOutsideRangePoint(e,a,M,k,c.xcalendar,c.ycalendar),c.customdata&&n.classed(\"plotly-customdata\",null!==e.data&&void 0!==e.data)):a.remove()}),w?n.exit().transition().style(\"opacity\",0).remove():n.exit().remove(),(n=u.selectAll(\"g\").data(x,d)).enter().append(\"g\").classed(\"textpoint\",!0).append(\"text\"),n.order(),n.each(function(t){var e=i.select(this),n=p(e.select(\"text\"));(s=o.translatePoint(t,n,M,k))?r.layerClipId&&o.hideOutsideRangePoint(t,e,M,k,c.xcalendar,c.ycalendar):e.remove()}),n.selectAll(\"text\").call(o.textPointStyle,c,t).each(function(t){var e=M.c2p(t.x),r=k.c2p(t.y);i.select(this).selectAll(\"tspan.line\").each(function(){p(i.select(this)).attr({x:e,y:r})})}),n.exit().remove()}var b,_;!function(t,e,r,n,o){var s=r.xaxis,c=r.yaxis,u=i.extent(a.simpleMap(s.range,s.r2c)),f=i.extent(a.simpleMap(c.range,c.r2c)),h=n[0].trace;if(!l.hasMarkers(h))return;var d=h.marker.maxdisplayed;if(0===d)return;var p=n.filter(function(t){return t.x>=u[0]&&t.x<=u[1]&&t.y>=f[0]&&t.y<=f[1]}),m=Math.ceil(p.length/d),g=0;o.forEach(function(t,r){var n=t[0].trace;l.hasMarkers(n)&&n.marker.maxdisplayed>0&&r0,M=r.xaxis,k=r.yaxis,A=n[0].trace,T=A.line,S=i.select(h);if(S.call(s.plot,r,d),!0===A.visible){p(S).style(\"opacity\",A.opacity);var E,L,C=A.fill.charAt(A.fill.length-1);\"x\"!==C&&\"y\"!==C&&(C=\"\"),n[0].node3=S;var z=\"\",D=[],I=A._prevtrace;I&&(z=I._prevRevpath||\"\",L=I._nextFill,D=I._polygons);var P,O,F,R,N,j,B,U,V,q=\"\",H=\"\",G=[],Y=a.noop;if(E=A._ownFill,l.hasLines(A)||\"none\"!==A.fill){for(L&&L.datum(n),-1!==[\"hv\",\"vh\",\"hvh\",\"vhv\"].indexOf(T.shape)?(F=o.steps(T.shape),R=o.steps(T.shape.split(\"\").reverse().join(\"\"))):F=R=\"spline\"===T.shape?function(t){var e=t[t.length-1];return t.length>1&&t[0][0]===e[0]&&t[0][1]===e[1]?o.smoothclosed(t.slice(1),T.smoothing):o.smoothopen(t,T.smoothing)}:function(t){return\"M\"+t.join(\"L\")},N=function(t){return R(t.reverse())},G=c(n,{xaxis:M,yaxis:k,connectGaps:A.connectgaps,baseTolerance:Math.max(T.width||1,3)/4,shape:T.shape,simplify:T.simplify}),V=A._polygons=new Array(G.length),_=0;_1){var r=i.select(this);if(r.datum(n),t)p(r.style(\"opacity\",0).attr(\"d\",P).call(o.lineGroupStyle)).style(\"opacity\",1);else{var a=p(r);a.attr(\"d\",P),o.singleLineStyle(n,a)}}}}}var W=S.selectAll(\".js-line\").data(G);p(W.exit()).style(\"opacity\",0).remove(),W.each(Y(!1)),W.enter().append(\"path\").classed(\"js-line\",!0).style(\"vector-effect\",\"non-scaling-stroke\").call(o.lineGroupStyle).each(Y(!0)),o.setClipUrl(W,r.layerClipId),G.length?(E?j&&U&&(C?(\"y\"===C?j[1]=U[1]=k.c2p(0,!0):\"x\"===C&&(j[0]=U[0]=M.c2p(0,!0)),p(E).attr(\"d\",\"M\"+U+\"L\"+j+\"L\"+q.substr(1)).call(o.singleFillStyle)):p(E).attr(\"d\",q+\"Z\").call(o.singleFillStyle)):L&&(\"tonext\"===A.fill.substr(0,6)&&q&&z?(\"tonext\"===A.fill?p(L).attr(\"d\",q+\"Z\"+z+\"Z\").call(o.singleFillStyle):p(L).attr(\"d\",q+\"L\"+z.substr(1)+\"Z\").call(o.singleFillStyle),A._polygons=A._polygons.concat(D)):(m(L),A._polygons=null)),A._prevRevpath=H,A._prevPolygons=V):(E?m(E):L&&m(L),A._polygons=A._prevRevpath=A._prevPolygons=null);var X=S.selectAll(\".points\");b=X.data([n]),X.each(x),b.enter().append(\"g\").classed(\"points\",!0).each(x),b.exit().remove(),b.each(function(t){var e=!1===t[0].trace.cliponaxis;o.setClipUrl(i.select(this),e?null:r.layerClipId)})}}var i=t(\"d3\"),a=t(\"../../lib\"),o=t(\"../../components/drawing\"),s=t(\"../../components/errorbars\"),l=t(\"./subtypes\"),c=t(\"./line_points\"),u=t(\"./link_traces\"),f=t(\"../../lib/polygon\").tester;e.exports=function(t,e,r,a,s){var l,c,f,h,d=e.plot.select(\"g.scatterlayer\"),p=!a,m=!!a&&a.duration>0;for((f=d.selectAll(\"g.trace\").data(r,function(t){return t[0].trace.uid})).enter().append(\"g\").attr(\"class\",function(t){return\"trace scatter trace\"+t[0].trace.uid}).style(\"stroke-miterlimit\",2),u(t,e,r),function(t,e,r){var n;e.selectAll(\"g.trace\").each(function(t){var e=i.select(this);if((n=t[0].trace)._nexttrace){if(n._nextFill=e.select(\".js-fill.js-tonext\"),!n._nextFill.size()){var a=\":first-child\";e.select(\".js-fill.js-tozero\").size()&&(a+=\" + *\"),n._nextFill=e.insert(\"path\",a).attr(\"class\",\"js-fill js-tonext\")}}else e.selectAll(\".js-fill.js-tonext\").remove(),n._nextFill=null;n.fill&&(\"tozero\"===n.fill.substr(0,6)||\"toself\"===n.fill||\"to\"===n.fill.substr(0,2)&&!n._prevtrace)?(n._ownFill=e.select(\".js-fill.js-tozero\"),n._ownFill.size()||(n._ownFill=e.insert(\"path\",\":first-child\").attr(\"class\",\"js-fill js-tozero\"))):(e.selectAll(\".js-fill.js-tozero\").remove(),n._ownFill=null),e.selectAll(\".js-fill\").call(o.setClipUrl,r.layerClipId)})}(0,d,e),l=0,c={};lc[e[0].trace.uid]?1:-1}),m){s&&(h=s());i.transition().duration(a.duration).ease(a.easing).each(\"end\",function(){h&&h()}).each(\"interrupt\",function(){h&&h()}).each(function(){d.selectAll(\"g.trace\").each(function(i,o){n(t,o,e,i,r,this,a)})})}else d.selectAll(\"g.trace\").each(function(i,o){n(t,o,e,i,r,this,a)});p&&f.exit().remove(),d.selectAll(\"path:not([d])\").remove()}},{\"../../components/drawing\":643,\"../../components/errorbars\":649,\"../../lib\":743,\"../../lib/polygon\":755,\"./line_points\":1080,\"./link_traces\":1082,\"./subtypes\":1088,d3:128}],1086:[function(t,e,r){\"use strict\";var n=t(\"./subtypes\");e.exports=function(t,e){var r,i,a,o,s=t.cd,l=t.xaxis,c=t.yaxis,u=[],f=s[0].trace;if(!n.hasMarkers(f)&&!n.hasText(f))return[];if(!1===e)for(r=0;r=0&&(e[1]+=1),t.indexOf(\"top\")>=0&&(e[1]-=1),t.indexOf(\"left\")>=0&&(e[0]-=1),t.indexOf(\"right\")>=0&&(e[0]+=1),e)}(e.textposition),r.textColor=g(e.textfont,1,S),r.textSize=o(e.textfont.size,S,p.identity,12),r.textFont=e.textfont.family,r.textAngle=0);var D=[\"x\",\"y\",\"z\"];for(r.project=[!1,!1,!1],r.projectScale=[1,1,1],r.projectOpacity=[1,1,1],n=0;n<3;++n){var I=e.projection[D[n]];(r.project[n]=I.show)&&(r.projectOpacity[n]=I.opacity,r.projectScale[n]=I.scale)}r.errorBounds=b(e,d);var P=function(t){for(var e=[0,0,0],r=[[0,0,0],[0,0,0],[0,0,0]],n=[0,0,0],i=0;i<3;i++){var a=t[i];a&&!1!==a.copy_zstyle&&(a=t[2]),a&&(e[i]=a.width/2,r[i]=m(a.color),n=a.thickness)}return{capSize:e,color:r,lineWidth:n}}([e.error_x,e.error_y,e.error_z]);return r.errorColor=P.color,r.errorLineWidth=P.lineWidth,r.errorCapSize=P.capSize,r.delaunayAxis=e.surfaceaxis,r.delaunayColor=m(e.surfacecolor),r}function l(t){if(Array.isArray(t)){var e=t[0];return Array.isArray(e)&&(t=e),\"rgb(\"+t.slice(0,3).map(function(t){return Math.round(255*t)})+\")\"}return null}var c=t(\"gl-line3d\"),u=t(\"gl-scatter3d\"),f=t(\"gl-error3d\"),h=t(\"gl-mesh3d\"),d=t(\"delaunay-triangulate\"),p=t(\"../../lib\"),m=t(\"../../lib/str2rgbarray\"),g=t(\"../../lib/gl_format_color\"),v=t(\"../scatter/make_bubble_size_func\"),y=t(\"../../constants/gl3d_dashes\"),x=t(\"../../constants/gl3d_markers\"),b=t(\"./calc_errors\"),_=n.prototype;_.handlePick=function(t){if(t.object&&(t.object===this.linePlot||t.object===this.delaunayMesh||t.object===this.textMarkers||t.object===this.scatterPlot)){t.object.highlight&&t.object.highlight(null),this.scatterPlot&&(t.object=this.scatterPlot,this.scatterPlot.highlight(t.data)),this.textLabels?void 0!==this.textLabels[t.data.index]?t.textLabel=this.textLabels[t.data.index]:t.textLabel=this.textLabels:t.textLabel=\"\";var e=t.index=t.data.index;return t.traceCoordinate=[this.data.x[e],this.data.y[e],this.data.z[e]],!0}},_.update=function(t){var e,r,n,i,a=this.scene.glplot.gl,o=y.solid;this.data=t;var p=s(this.scene,t);\"mode\"in p&&(this.mode=p.mode),\"lineDashes\"in p&&p.lineDashes in y&&(o=y[p.lineDashes]),this.color=l(p.scatterColor)||l(p.lineColor),this.dataPoints=p.position,e={gl:a,position:p.position,color:p.lineColor,lineWidth:p.lineWidth||1,dashes:o[0],dashScale:o[1],opacity:t.opacity,connectGaps:t.connectgaps},-1!==this.mode.indexOf(\"lines\")?this.linePlot?this.linePlot.update(e):(this.linePlot=c(e),this.linePlot._trace=this,this.scene.glplot.add(this.linePlot)):this.linePlot&&(this.scene.glplot.remove(this.linePlot),this.linePlot.dispose(),this.linePlot=null);var m=t.opacity;if(t.marker&&t.marker.opacity&&(m*=t.marker.opacity),r={gl:a,position:p.position,color:p.scatterColor,size:p.scatterSize,glyph:p.scatterMarker,opacity:m,orthographic:!0,lineWidth:p.scatterLineWidth,lineColor:p.scatterLineColor,project:p.project,projectScale:p.projectScale,projectOpacity:p.projectOpacity},-1!==this.mode.indexOf(\"markers\")?this.scatterPlot?this.scatterPlot.update(r):(this.scatterPlot=u(r),this.scatterPlot._trace=this,this.scatterPlot.highlightScale=1,this.scene.glplot.add(this.scatterPlot)):this.scatterPlot&&(this.scene.glplot.remove(this.scatterPlot),this.scatterPlot.dispose(),this.scatterPlot=null),i={gl:a,position:p.position,glyph:p.text,color:p.textColor,size:p.textSize,angle:p.textAngle,alignment:p.textOffset,font:p.textFont,orthographic:!0,lineWidth:0,project:!1,opacity:t.opacity},this.textLabels=t.hovertext||t.text,-1!==this.mode.indexOf(\"text\")?this.textMarkers?this.textMarkers.update(i):(this.textMarkers=u(i),this.textMarkers._trace=this,this.textMarkers.highlightScale=1,this.scene.glplot.add(this.textMarkers)):this.textMarkers&&(this.scene.glplot.remove(this.textMarkers),this.textMarkers.dispose(),this.textMarkers=null),n={gl:a,position:p.position,color:p.errorColor,error:p.errorBounds,lineWidth:p.errorLineWidth,capSize:p.errorCapSize,opacity:t.opacity},this.errorBars?p.errorBounds?this.errorBars.update(n):(this.scene.glplot.remove(this.errorBars),this.errorBars.dispose(),this.errorBars=null):p.errorBounds&&(this.errorBars=f(n),this.errorBars._trace=this,this.scene.glplot.add(this.errorBars)),p.delaunayAxis>=0){var g=function(t,e,r){var n,i=(r+1)%3,a=(r+2)%3,o=[],s=[];for(n=0;n=0&&h(\"surfacecolor\",d||p);for(var m=[\"x\",\"y\",\"z\"],g=0;g<3;++g){var v=\"projection.\"+m[g];h(v+\".show\")&&(h(v+\".opacity\"),h(v+\".scale\"))}c(t,e,r,{axis:\"z\"}),c(t,e,r,{axis:\"y\",inherit:\"z\"}),c(t,e,r,{axis:\"x\",inherit:\"z\"})}else e.visible=!1}},{\"../../components/errorbars/defaults\":648,\"../../lib\":743,\"../../registry\":873,\"../scatter/line_defaults\":1079,\"../scatter/marker_defaults\":1084,\"../scatter/subtypes\":1088,\"../scatter/text_defaults\":1089,\"./attributes\":1091}],1096:[function(t,e,r){\"use strict\";var n={};n.plot=t(\"./convert\"),n.attributes=t(\"./attributes\"),n.markerSymbols=t(\"../../constants/gl3d_markers\"),n.supplyDefaults=t(\"./defaults\"),n.colorbar=t(\"../scatter/colorbar\"),n.calc=t(\"./calc\"),n.moduleType=\"trace\",n.name=\"scatter3d\",n.basePlotModule=t(\"../../plots/gl3d\"),n.categories=[\"gl3d\",\"symbols\",\"markerColorscale\",\"showLegend\"],n.meta={},e.exports=n},{\"../../constants/gl3d_markers\":719,\"../../plots/gl3d\":832,\"../scatter/colorbar\":1070,\"./attributes\":1091,\"./calc\":1092,\"./convert\":1094,\"./defaults\":1095}],1097:[function(t,e,r){\"use strict\";var n=t(\"../scatter/attributes\"),i=t(\"../../plots/attributes\"),a=t(\"../../components/colorscale/color_attributes\"),o=t(\"../../components/colorbar/attributes\"),s=t(\"../../lib/extend\").extendFlat,l=n.marker,c=n.line,u=l.line;e.exports={carpet:{valType:\"string\",editType:\"calc\"},a:{valType:\"data_array\",editType:\"calc\"},b:{valType:\"data_array\",editType:\"calc\"},mode:s({},n.mode,{dflt:\"markers\"}),text:s({},n.text,{}),line:{color:c.color,width:c.width,dash:c.dash,shape:s({},c.shape,{values:[\"linear\",\"spline\"]}),smoothing:c.smoothing,editType:\"calc\"},connectgaps:n.connectgaps,fill:s({},n.fill,{values:[\"none\",\"toself\",\"tonext\"]}),fillcolor:n.fillcolor,marker:s({symbol:l.symbol,opacity:l.opacity,maxdisplayed:l.maxdisplayed,size:l.size,sizeref:l.sizeref,sizemin:l.sizemin,sizemode:l.sizemode,line:s({width:u.width,editType:\"calc\"},a(\"marker\".line)),gradient:l.gradient,editType:\"calc\"},a(\"marker\"),{showscale:l.showscale,colorbar:o}),textfont:n.textfont,textposition:n.textposition,selected:n.selected,unselected:n.unselected,hoverinfo:s({},i.hoverinfo,{flags:[\"a\",\"b\",\"text\",\"name\"]}),hoveron:n.hoveron}},{\"../../components/colorbar/attributes\":619,\"../../components/colorscale/color_attributes\":626,\"../../lib/extend\":732,\"../../plots/attributes\":787,\"../scatter/attributes\":1066}],1098:[function(t,e,r){\"use strict\";var n=t(\"fast-isnumeric\"),i=t(\"../scatter/colorscale_calc\"),a=t(\"../scatter/arrays_to_calcdata\"),o=t(\"../scatter/calc_selection\"),s=t(\"../scatter/calc\").calcMarkerSize,l=t(\"../carpet/lookup_carpetid\");e.exports=function(t,e){var r=e.carpetTrace=l(t,e);if(r&&r.visible&&\"legendonly\"!==r.visible){var c;e.xaxis=r.xaxis,e.yaxis=r.yaxis;var u,f,h=e.a.length,d=new Array(h),p=!1;for(c=0;c0?t.labelprefix.replace(/ = $/,\"\"):t._hovertitle,g.push(r+\": \"+e.toFixed(3)+t.labelsuffix)}var o=n(t,e,r,i);if(o&&!1!==o[0].index){var s=o[0];if(void 0===s.index){var l=1-s.y0/t.ya._length,c=t.xa._length,u=c*l/2,f=c-u;return s.x0=Math.max(Math.min(s.x0,f),u),s.x1=Math.max(Math.min(s.x1,f),u),o}var h=s.cd[s.index];s.a=h.a,s.b=h.b,s.xLabelVal=void 0,s.yLabelVal=void 0;var d=s.trace,p=d._carpet,m=(h.hi||d.hoverinfo).split(\"+\"),g=[];-1!==m.indexOf(\"all\")&&(m=[\"a\",\"b\"]),-1!==m.indexOf(\"a\")&&a(p.aaxis,h.a),-1!==m.indexOf(\"b\")&&a(p.baxis,h.b);var v=p.ab2ij([h.a,h.b]),y=Math.floor(v[0]),x=v[0]-y,b=Math.floor(v[1]),_=v[1]-b,w=p.evalxy([],y,b,x,_);return g.push(\"y: \"+w[1].toFixed(3)),s.extraText=g.join(\"
\"),o}}},{\"../scatter/hover\":1077}],1102:[function(t,e,r){\"use strict\";var n={};n.attributes=t(\"./attributes\"),n.supplyDefaults=t(\"./defaults\"),n.colorbar=t(\"../scatter/colorbar\"),n.calc=t(\"./calc\"),n.plot=t(\"./plot\"),n.style=t(\"../scatter/style\").style,n.hoverPoints=t(\"./hover\"),n.selectPoints=t(\"../scatter/select\"),n.eventData=t(\"./event_data\"),n.moduleType=\"trace\",n.name=\"scattercarpet\",n.basePlotModule=t(\"../../plots/cartesian\"),n.categories=[\"carpet\",\"symbols\",\"markerColorscale\",\"showLegend\",\"carpetDependent\"],n.meta={},e.exports=n},{\"../../plots/cartesian\":800,\"../scatter/colorbar\":1070,\"../scatter/select\":1086,\"../scatter/style\":1087,\"./attributes\":1097,\"./calc\":1098,\"./defaults\":1099,\"./event_data\":1100,\"./hover\":1101,\"./plot\":1103}],1103:[function(t,e,r){\"use strict\";var n=t(\"../scatter/plot\"),i=t(\"../../plots/cartesian/axes\"),a=t(\"../../components/drawing\");e.exports=function(t,e,r){var o,s,l,c=r[0][0].carpet,u={xaxis:i.getFromId(t,c.xaxis||\"x\"),yaxis:i.getFromId(t,c.yaxis||\"y\"),plot:e.plot};for(n(t,u,r),o=0;o\")}(u,g,d.mockAxis,c[0].t.labels),[t]}}},{\"../../components/fx\":660,\"../../constants/numerical\":721,\"../../plots/cartesian/axes\":789,\"../scatter/fill_hover_text\":1074,\"../scatter/get_trace_color\":1076,\"./attributes\":1104}],1109:[function(t,e,r){\"use strict\";var n={};n.attributes=t(\"./attributes\"),n.supplyDefaults=t(\"./defaults\"),n.colorbar=t(\"../scatter/colorbar\"),n.calc=t(\"./calc\"),n.plot=t(\"./plot\"),n.style=t(\"./style\"),n.hoverPoints=t(\"./hover\"),n.eventData=t(\"./event_data\"),n.selectPoints=t(\"./select\"),n.moduleType=\"trace\",n.name=\"scattergeo\",n.basePlotModule=t(\"../../plots/geo\"),n.categories=[\"geo\",\"symbols\",\"markerColorscale\",\"showLegend\",\"scatter-like\"],n.meta={},e.exports=n},{\"../../plots/geo\":820,\"../scatter/colorbar\":1070,\"./attributes\":1104,\"./calc\":1105,\"./defaults\":1106,\"./event_data\":1107,\"./hover\":1108,\"./plot\":1110,\"./select\":1111,\"./style\":1112}],1110:[function(t,e,r){\"use strict\";var n=t(\"d3\"),i=t(\"../../lib\"),a=t(\"../../constants/numerical\").BADNUM,o=t(\"../../lib/topojson_utils\").getTopojsonFeatures,s=t(\"../../lib/geo_location_utils\").locationToFeature,l=t(\"../../lib/geojson_utils\"),c=t(\"../scatter/subtypes\"),u=t(\"./style\");e.exports=function(t,e,r){function f(t,e){t.lonlat[0]===a&&n.select(e).remove()}for(var h=0;h1,f=r.error_x&&!0===r.error_x.visible,h=r.error_y&&!0===r.error_y.visible,p=f||h,m=d.hasMarkers(r),x=!!r.fill&&\"none\"!==r.fill);var E,L,C,z,D,I,O,F,R=p?l.calcFromTrace(r,b):null;if(f){(C={}).positions=n;var N=new Float64Array(4*_);if(\"log\"===T.type)for(o=0;o<_;++o)N[k++]=n[2*o]-T.d2l(R[o].xs)||0,N[k++]=T.d2l(R[o].xh)-n[2*o]||0,N[k++]=0,N[k++]=0;else for(o=0;o<_;++o)N[k++]=n[2*o]-R[o].xs||0,N[k++]=R[o].xh-n[2*o]||0,N[k++]=0,N[k++]=0;r.error_x.copy_ystyle&&(r.error_x=r.error_y),C.errors=N,C.capSize=2*r.error_x.width,C.lineWidth=r.error_x.thickness,C.color=r.error_x.color}if(h){(z={}).positions=n;var j=new Float64Array(4*_);if(\"log\"===S.type)for(o=0;o<_;++o)j[A++]=0,j[A++]=0,j[A++]=n[2*o+1]-S.d2l(R[o].ys)||0,j[A++]=S.d2l(R[o].yh)-n[2*o+1]||0;else for(o=0;o<_;++o)j[A++]=0,j[A++]=0,j[A++]=n[2*o+1]-R[o].ys||0,j[A++]=R[o].yh-n[2*o+1]||0;z.errors=j,z.capSize=2*r.error_y.width,z.lineWidth=r.error_y.thickness,z.color=r.error_y.color}if(s){(E={}).thickness=r.line.width,E.color=r.line.color,E.opacity=r.opacity,E.overlay=!0;var B=(v[r.line.dash]||[1]).slice();for(o=0;oP?\"rect\":m?\"rect\":\"round\",U&&r.connectgaps){var V=F[0],q=F[1];for(o=0;os&&(A[0]=s),A[1]l&&(T[0]=l),T[1]=0?Math.floor((e+180)/360):Math.ceil((e-180)/360)),h=e-f;if(n.getClosest(s,function(t){var e=t.lonlat;if(e[0]===o)return 1/0;var n=Math.abs(c.c2p(e)-c.c2p([h,e[1]])),i=Math.abs(u.c2p(e)-u.c2p([e[0],r])),a=Math.max(3,t.mrc||0);return Math.max(Math.sqrt(n*n+i*i)-a,1-3/a)},t),!1!==t.index){var d=s[t.index],p=d.lonlat,m=[p[0]+f,p[1]],g=c.c2p(m),v=u.c2p(m),y=d.mrc||1;return t.x0=g-y,t.x1=g+y,t.y0=v-y,t.y1=v+y,t.color=i(l,d),t.extraText=function(t,e,r){function n(t){return t+\"\\xb0\"}var i=(e.hi||t.hoverinfo).split(\"+\"),o=-1!==i.indexOf(\"all\"),s=-1!==i.indexOf(\"lon\"),l=-1!==i.indexOf(\"lat\"),c=e.lonlat,u=[];return o||s&&l?u.push(\"(\"+n(c[0])+\", \"+n(c[1])+\")\"):s?u.push(r.lon+n(c[0])):l&&u.push(r.lat+n(c[1])),(o||-1!==i.indexOf(\"text\"))&&a(e,t,u),u.join(\"
\")}(l,d,s[0].t.labels),[t]}}},{\"../../components/fx\":660,\"../../constants/numerical\":721,\"../scatter/fill_hover_text\":1074,\"../scatter/get_trace_color\":1076}],1121:[function(t,e,r){\"use strict\";var n={};n.attributes=t(\"./attributes\"),n.supplyDefaults=t(\"./defaults\"),n.colorbar=t(\"../scatter/colorbar\"),n.calc=t(\"../scattergeo/calc\"),n.plot=t(\"./plot\"),n.hoverPoints=t(\"./hover\"),n.eventData=t(\"./event_data\"),n.selectPoints=t(\"./select\"),n.style=function(t,e){if(e){e[0].trace._glTrace.update(e)}},n.moduleType=\"trace\",n.name=\"scattermapbox\",n.basePlotModule=t(\"../../plots/mapbox\"),n.categories=[\"mapbox\",\"gl\",\"symbols\",\"markerColorscale\",\"showLegend\",\"scatterlike\"],n.meta={},e.exports=n},{\"../../plots/mapbox\":846,\"../scatter/colorbar\":1070,\"../scattergeo/calc\":1105,\"./attributes\":1116,\"./defaults\":1118,\"./event_data\":1119,\"./hover\":1120,\"./plot\":1122,\"./select\":1123}],1122:[function(t,e,r){\"use strict\";function n(t,e){this.mapbox=t,this.map=t.map,this.uid=e,this.idSourceFill=e+\"-source-fill\",this.idSourceLine=e+\"-source-line\",this.idSourceCircle=e+\"-source-circle\",this.idSourceSymbol=e+\"-source-symbol\",this.idLayerFill=e+\"-layer-fill\",this.idLayerLine=e+\"-layer-line\",this.idLayerCircle=e+\"-layer-circle\",this.idLayerSymbol=e+\"-layer-symbol\",this.mapbox.initSource(this.idSourceFill),this.mapbox.initSource(this.idSourceLine),this.mapbox.initSource(this.idSourceCircle),this.mapbox.initSource(this.idSourceSymbol),this.map.addLayer({id:this.idLayerFill,source:this.idSourceFill,type:\"fill\"}),this.map.addLayer({id:this.idLayerLine,source:this.idSourceLine,type:\"line\"}),this.map.addLayer({id:this.idLayerCircle,source:this.idSourceCircle,type:\"circle\"}),this.map.addLayer({id:this.idLayerSymbol,source:this.idSourceSymbol,type:\"symbol\"})}function i(t){return\"visible\"===t.layout.visibility}var a=t(\"./convert\"),o=n.prototype;o.update=function(t){var e=this.mapbox,r=a(t);e.setOptions(this.idLayerFill,\"setLayoutProperty\",r.fill.layout),e.setOptions(this.idLayerLine,\"setLayoutProperty\",r.line.layout),e.setOptions(this.idLayerCircle,\"setLayoutProperty\",r.circle.layout),e.setOptions(this.idLayerSymbol,\"setLayoutProperty\",r.symbol.layout),i(r.fill)&&(e.setSourceData(this.idSourceFill,r.fill.geojson),e.setOptions(this.idLayerFill,\"setPaintProperty\",r.fill.paint)),i(r.line)&&(e.setSourceData(this.idSourceLine,r.line.geojson),e.setOptions(this.idLayerLine,\"setPaintProperty\",r.line.paint)),i(r.circle)&&(e.setSourceData(this.idSourceCircle,r.circle.geojson),e.setOptions(this.idLayerCircle,\"setPaintProperty\",r.circle.paint)),i(r.symbol)&&(e.setSourceData(this.idSourceSymbol,r.symbol.geojson),e.setOptions(this.idLayerSymbol,\"setPaintProperty\",r.symbol.paint)),t[0].trace._glTrace=this},o.dispose=function(){var t=this.map;t.removeLayer(this.idLayerFill),t.removeLayer(this.idLayerLine),t.removeLayer(this.idLayerCircle),t.removeLayer(this.idLayerSymbol),t.removeSource(this.idSourceFill),t.removeSource(this.idSourceLine),t.removeSource(this.idSourceCircle),t.removeSource(this.idSourceSymbol)},e.exports=function(t,e){var r=new n(t,e[0].trace.uid);return r.update(e),r}},{\"./convert\":1117}],1123:[function(t,e,r){\"use strict\";var n=t(\"../scatter/subtypes\");e.exports=function(t,e){var r,i,a,o,s,l=t.cd,c=t.xaxis,u=t.yaxis,f=[],h=l[0].trace;if(!n.hasMarkers(h))return[];if(!1===e)for(s=0;s\")}var i=t(\"../scatter/hover\"),a=t(\"../../plots/cartesian/axes\"),o=t(\"../../lib\");e.exports={hoverPoints:function(t,e,r,a){var o=i(t,e,r,a);if(o&&!1!==o[0].index){var s=o[0];if(void 0===s.index)return o;var l=t.subplot,c=s.cd[s.index],u=s.trace;if(l.isPtWithinSector(c))return s.xLabelVal=void 0,s.yLabelVal=void 0,s.extraText=n(c,u,l),o}},makeHoverPointText:n}},{\"../../lib\":743,\"../../plots/cartesian/axes\":789,\"../scatter/hover\":1077}],1128:[function(t,e,r){\"use strict\";e.exports={moduleType:\"trace\",name:\"scatterpolar\",basePlotModule:t(\"../../plots/polar\"),categories:[\"polar\",\"symbols\",\"markerColorscale\",\"showLegend\",\"scatter-like\"],attributes:t(\"./attributes\"),supplyDefaults:t(\"./defaults\"),calc:t(\"./calc\"),plot:t(\"./plot\"),style:t(\"../scatter/style\").style,hoverPoints:t(\"./hover\").hoverPoints,selectPoints:t(\"../scatter/select\"),meta:{}}},{\"../../plots/polar\":855,\"../scatter/select\":1086,\"../scatter/style\":1087,\"./attributes\":1124,\"./calc\":1125,\"./defaults\":1126,\"./hover\":1127,\"./plot\":1129}],1129:[function(t,e,r){\"use strict\";var n=t(\"../scatter/plot\"),i=t(\"../../constants/numerical\").BADNUM;e.exports=function(t,e,r){var a,o,s,l={xaxis:e.xaxis,yaxis:e.yaxis,plot:e.framework,layerClipId:e._hasClipOnAxisFalse?e.clipIds.circle:null},c=e.radialAxis,u=c.range;for(s=u[0]>u[1]?function(t){return t<=0}:function(t){return t>=0},a=0;a=0?(g=o.c2r(m)-l[0],y=d(v),E[p]=S[2*p]=g*Math.cos(y),L[p]=S[2*p+1]=g*Math.sin(y)):E[p]=L[p]=S[2*p]=S[2*p+1]=NaN;var C=a.sceneOptions(t,e,b,S);C.fill&&!u.fill2d&&(u.fill2d=!0),C.marker&&!u.scatter2d&&(u.scatter2d=!0),C.line&&!u.line2d&&(u.line2d=!0),!C.errorX&&!C.errorY||u.error2d||(u.error2d=!0),c.hasMarkers(b)&&(C.selected.positions=C.unselected.positions=C.marker.positions),u.lineOptions.push(C.line),u.errorXOptions.push(C.errorX),u.errorYOptions.push(C.errorY),u.fillOptions.push(C.fill),u.markerOptions.push(C.marker),u.selectedOptions.push(C.selected),u.unselectedOptions.push(C.unselected),u.count=r.length,_.scene=u,_.index=h,_.x=E,_.y=L,_.rawx=E,_.rawy=L,_.r=w,_.theta=M,_.positions=S,_.count=T,_.tree=n(S,512)}}),a.plot(t,e,r)},hoverPoints:function(t,e,r,n){var i=t.cd[0].t,o=i.r,s=i.theta,c=a.hoverPoints(t,e,r,n);if(c&&!1!==c[0].index){var u=c[0];if(void 0===u.index)return c;var f=t.subplot,h=f.angularAxis,d=u.cd[u.index],p=u.trace;if(d.r=o[u.index],d.theta=s[u.index],d.rad=h.c2rad(d.theta,p.thetaunit),f.isPtWithinSector(d))return u.xLabelVal=void 0,u.yLabelVal=void 0,u.extraText=l(d,p,f),c}},style:a.style,selectPoints:a.selectPoints,meta:{}}},{\"../../plots/cartesian/axes\":789,\"../../plots/polar\":855,\"../scatter/colorscale_calc\":1071,\"../scatter/subtypes\":1088,\"../scattergl\":1115,\"../scatterpolar/hover\":1127,\"./attributes\":1130,\"./defaults\":1131,\"fast-isnumeric\":140,kdgrass:292}],1133:[function(t,e,r){\"use strict\";var n=t(\"../scatter/attributes\"),i=t(\"../../plots/attributes\"),a=t(\"../../components/colorscale/color_attributes\"),o=t(\"../../components/colorbar/attributes\"),s=t(\"../../components/drawing/attributes\").dash,l=t(\"../../lib/extend\").extendFlat,c=n.marker,u=n.line,f=c.line;e.exports={a:{valType:\"data_array\",editType:\"calc\"},b:{valType:\"data_array\",editType:\"calc\"},c:{valType:\"data_array\",editType:\"calc\"},sum:{valType:\"number\",dflt:0,min:0,editType:\"calc\"},mode:l({},n.mode,{dflt:\"markers\"}),text:l({},n.text,{}),hovertext:l({},n.hovertext,{}),line:{color:u.color,width:u.width,dash:s,shape:l({},u.shape,{values:[\"linear\",\"spline\"]}),smoothing:u.smoothing,editType:\"calc\"},connectgaps:n.connectgaps,cliponaxis:n.cliponaxis,fill:l({},n.fill,{values:[\"none\",\"toself\",\"tonext\"]}),fillcolor:n.fillcolor,marker:l({symbol:c.symbol,opacity:c.opacity,maxdisplayed:c.maxdisplayed,size:c.size,sizeref:c.sizeref,sizemin:c.sizemin,sizemode:c.sizemode,line:l({width:f.width,editType:\"calc\"},a(\"marker.line\")),gradient:c.gradient,editType:\"calc\"},a(\"marker\"),{showscale:c.showscale,colorbar:o}),textfont:n.textfont,textposition:n.textposition,selected:n.selected,unselected:n.unselected,hoverinfo:l({},i.hoverinfo,{flags:[\"a\",\"b\",\"c\",\"text\",\"name\"]}),hoveron:n.hoveron}},{\"../../components/colorbar/attributes\":619,\"../../components/colorscale/color_attributes\":626,\"../../components/drawing/attributes\":642,\"../../lib/extend\":732,\"../../plots/attributes\":787,\"../scatter/attributes\":1066}],1134:[function(t,e,r){\"use strict\";var n=t(\"fast-isnumeric\"),i=t(\"../scatter/colorscale_calc\"),a=t(\"../scatter/arrays_to_calcdata\"),o=t(\"../scatter/calc_selection\"),s=t(\"../scatter/calc\").calcMarkerSize,l=[\"a\",\"b\",\"c\"],c={a:[\"b\",\"c\"],b:[\"a\",\"c\"],c:[\"a\",\"b\"]};e.exports=function(t,e){var r,u,f,h,d,p,m=t._fullLayout[e.subplot].sum,g=e.sum||m;for(r=0;r\"),s}}},{\"../../plots/cartesian/axes\":789,\"../scatter/hover\":1077}],1138:[function(t,e,r){\"use strict\";var n={};n.attributes=t(\"./attributes\"),n.supplyDefaults=t(\"./defaults\"),n.colorbar=t(\"../scatter/colorbar\"),n.calc=t(\"./calc\"),n.plot=t(\"./plot\"),n.style=t(\"../scatter/style\").style,n.hoverPoints=t(\"./hover\"),n.selectPoints=t(\"../scatter/select\"),n.eventData=t(\"./event_data\"),n.moduleType=\"trace\",n.name=\"scatterternary\",n.basePlotModule=t(\"../../plots/ternary\"),n.categories=[\"ternary\",\"symbols\",\"markerColorscale\",\"showLegend\",\"scatter-like\"],n.meta={},e.exports=n},{\"../../plots/ternary\":866,\"../scatter/colorbar\":1070,\"../scatter/select\":1086,\"../scatter/style\":1087,\"./attributes\":1133,\"./calc\":1134,\"./defaults\":1135,\"./event_data\":1136,\"./hover\":1137,\"./plot\":1139}],1139:[function(t,e,r){\"use strict\";var n=t(\"../scatter/plot\");e.exports=function(t,e,r){var i=e.plotContainer;i.select(\".scatterlayer\").selectAll(\"*\").remove();var a={xaxis:e.xaxis,yaxis:e.yaxis,plot:i,layerClipId:e._hasClipOnAxisFalse?e.clipIdRelative:null};n(t,a,r)}},{\"../scatter/plot\":1085}],1140:[function(t,e,r){\"use strict\";function n(t){return{show:{valType:\"boolean\",dflt:!1},project:{x:{valType:\"boolean\",dflt:!1},y:{valType:\"boolean\",dflt:!1},z:{valType:\"boolean\",dflt:!1}},color:{valType:\"color\",dflt:i.defaultLine},usecolormap:{valType:\"boolean\",dflt:!1},width:{valType:\"number\",min:1,max:16,dflt:2},highlight:{valType:\"boolean\",dflt:!0},highlightcolor:{valType:\"color\",dflt:i.defaultLine},highlightwidth:{valType:\"number\",min:1,max:16,dflt:2}}}var i=t(\"../../components/color\"),a=t(\"../../components/colorscale/attributes\"),o=t(\"../../components/colorbar/attributes\"),s=t(\"../../lib/extend\").extendFlat,l=t(\"../../plot_api/edit_types\").overrideAll,c=e.exports=l({z:{valType:\"data_array\"},x:{valType:\"data_array\"},y:{valType:\"data_array\"},text:{valType:\"data_array\"},surfacecolor:{valType:\"data_array\"},cauto:a.zauto,cmin:a.zmin,cmax:a.zmax,colorscale:a.colorscale,autocolorscale:s({},a.autocolorscale,{dflt:!1}),reversescale:a.reversescale,showscale:a.showscale,colorbar:o,contours:{x:n(),y:n(),z:n()},hidesurface:{valType:\"boolean\",dflt:!1},lightposition:{x:{valType:\"number\",min:-1e5,max:1e5,dflt:10},y:{valType:\"number\",min:-1e5,max:1e5,dflt:1e4},z:{valType:\"number\",min:-1e5,max:1e5,dflt:0}},lighting:{ambient:{valType:\"number\",min:0,max:1,dflt:.8},diffuse:{valType:\"number\",min:0,max:1,dflt:.8},specular:{valType:\"number\",min:0,max:2,dflt:.05},roughness:{valType:\"number\",min:0,max:1,dflt:.5},fresnel:{valType:\"number\",min:0,max:5,dflt:.2}},opacity:{valType:\"number\",min:0,max:1,dflt:1},_deprecated:{zauto:s({},a.zauto,{}),zmin:s({},a.zmin,{}),zmax:s({},a.zmax,{})}},\"calc\",\"nested\");c.x.editType=c.y.editType=c.z.editType=\"calc+clearAxisTypes\"},{\"../../components/color\":618,\"../../components/colorbar/attributes\":619,\"../../components/colorscale/attributes\":624,\"../../lib/extend\":732,\"../../plot_api/edit_types\":773}],1141:[function(t,e,r){\"use strict\";var n=t(\"../../components/colorscale/calc\");e.exports=function(t,e){e.surfacecolor?n(e,e.surfacecolor,\"\",\"c\"):n(e,e.z,\"\",\"c\")}},{\"../../components/colorscale/calc\":625}],1142:[function(t,e,r){\"use strict\";var n=t(\"fast-isnumeric\"),i=t(\"../../lib\"),a=t(\"../../plots/plots\"),o=t(\"../../components/colorscale\"),s=t(\"../../components/colorbar/draw\");e.exports=function(t,e){var r=e[0].trace,l=\"cb\"+r.uid,c=r.cmin,u=r.cmax,f=r.surfacecolor||r.z;if(n(c)||(c=i.aggNums(Math.min,null,f)),n(u)||(u=i.aggNums(Math.max,null,f)),t._fullLayout._infolayer.selectAll(\".\"+l).remove(),r.showscale){var h=e[0].t.cb=s(t,l),d=o.makeColorScaleFunc(o.extractScale(r.colorscale,c,u),{noNumericCheck:!0});h.fillcolor(d).filllevels({start:c,end:u,size:(u-c)/254}).options(r.colorbar)()}else a.autoMargin(t,l)}},{\"../../components/colorbar/draw\":622,\"../../components/colorscale\":633,\"../../lib\":743,\"../../plots/plots\":852,\"fast-isnumeric\":140}],1143:[function(t,e,r){\"use strict\";function n(t,e,r){this.scene=t,this.uid=r,this.surface=e,this.data=null,this.showContour=[!1,!1,!1],this.dataScale=1}function i(t){var e=t.shape,r=[e[0]+2,e[1]+2],n=o(new Float32Array(r[0]*r[1]),r);return c.assign(n.lo(1,1).hi(e[0],e[1]),t),c.assign(n.lo(1).hi(e[0],1),t.hi(e[0],1)),c.assign(n.lo(1,r[1]-1).hi(e[0],1),t.lo(0,e[1]-1).hi(e[0],1)),c.assign(n.lo(0,1).hi(1,e[1]),t.hi(1)),c.assign(n.lo(r[0]-1,1).hi(1,e[1]),t.lo(e[0]-1)),n.set(0,0,t.get(0,0)),n.set(0,r[1]-1,t.get(0,e[1]-1)),n.set(r[0]-1,0,t.get(e[0]-1,0)),n.set(r[0]-1,r[1]-1,t.get(e[0]-1,e[1]-1)),n}var a=t(\"gl-surface3d\"),o=t(\"ndarray\"),s=t(\"ndarray-homography\"),l=t(\"ndarray-fill\"),c=t(\"ndarray-ops\"),u=t(\"tinycolor2\"),f=t(\"../../lib/str2rgbarray\"),h=128,d=n.prototype;d.handlePick=function(t){if(t.object===this.surface){var e=t.index=[Math.min(0|Math.round(t.data.index[0]/this.dataScale-1),this.data.z[0].length-1),Math.min(0|Math.round(t.data.index[1]/this.dataScale-1),this.data.z.length-1)],r=[0,0,0];Array.isArray(this.data.x[0])?r[0]=this.data.x[e[1]][e[0]]:r[0]=this.data.x[e[0]],Array.isArray(this.data.y[0])?r[1]=this.data.y[e[1]][e[0]]:r[1]=this.data.y[e[1]],r[2]=this.data.z[e[1]][e[0]],t.traceCoordinate=r;var n=this.scene.fullSceneLayout;t.dataCoordinate=[n.xaxis.d2l(r[0],0,this.data.xcalendar)*this.scene.dataScale[0],n.yaxis.d2l(r[1],0,this.data.ycalendar)*this.scene.dataScale[1],n.zaxis.d2l(r[2],0,this.data.zcalendar)*this.scene.dataScale[2]];var i=this.data.text;return i&&i[e[1]]&&void 0!==i[e[1]][e[0]]?t.textLabel=i[e[1]][e[0]]:t.textLabel=\"\",t.data.dataCoordinate=t.dataCoordinate.slice(),this.surface.highlight(t.data),this.scene.glplot.spikes.position=t.dataCoordinate,!0}},d.setContourLevels=function(){for(var t=[[],[],[]],e=!1,r=0;r<3;++r)this.showContour[r]&&(e=!0,t[r]=this.scene.contourLevels[r]);e&&this.surface.update({levels:t})},d.update=function(t){var e,r=this.scene,n=r.fullSceneLayout,a=this.surface,c=t.opacity,d=function(t,e){return void 0===e&&(e=1),t.map(function(t){var r=t[0],n=u(t[1]).toRgb();return{index:r,rgb:[n.r,n.g,n.b,e]}})}(t.colorscale,c),p=t.z,m=t.x,g=t.y,v=n.xaxis,y=n.yaxis,x=n.zaxis,b=r.dataScale,_=p[0].length,w=p.length,M=[o(new Float32Array(_*w),[_,w]),o(new Float32Array(_*w),[_,w]),o(new Float32Array(_*w),[_,w])],k=M[0],A=M[1],T=r.contourLevels;this.data=t;var S=t.xcalendar,E=t.ycalendar,L=t.zcalendar;l(M[2],function(t,e){return x.d2l(p[e][t],0,L)*b[2]}),Array.isArray(m[0])?l(k,function(t,e){return v.d2l(m[e][t],0,S)*b[0]}):l(k,function(t){return v.d2l(m[t],0,S)*b[0]}),Array.isArray(g[0])?l(A,function(t,e){return y.d2l(g[e][t],0,E)*b[1]}):l(A,function(t,e){return y.d2l(g[e],0,E)*b[1]});var C={colormap:d,levels:[[],[],[]],showContour:[!0,!0,!0],showSurface:!t.hidesurface,contourProject:[[!1,!1,!1],[!1,!1,!1],[!1,!1,!1]],contourWidth:[1,1,1],contourColor:[[1,1,1,1],[1,1,1,1],[1,1,1,1]],contourTint:[1,1,1],dynamicColor:[[1,1,1,1],[1,1,1,1],[1,1,1,1]],dynamicWidth:[1,1,1],dynamicTint:[1,1,1],opacity:t.opacity};if(C.intensityBounds=[t.cmin,t.cmax],t.surfacecolor){var z=o(new Float32Array(_*w),[_,w]);l(z,function(e,r){return t.surfacecolor[r][e]}),M.push(z)}else C.intensityBounds[0]*=b[2],C.intensityBounds[1]*=b[2];this.dataScale=function(t){var e=Math.max(t[0].shape[0],t[0].shape[1]);if(e\",uplift:5,goldenRatio:1.618,columnTitleOffset:28,columnExtentOffset:10,transitionEase:\"cubic-out\",transitionDuration:100,releaseTransitionEase:\"cubic-out\",releaseTransitionDuration:120,scrollbarWidth:8,scrollbarCaptureWidth:18,scrollbarOffset:5,scrollbarHideDelay:1e3,scrollbarHideDuration:1e3,cn:{table:\"table\",tableControlView:\"table-control-view\",scrollBackground:\"scroll-background\",yColumn:\"y-column\",columnBlock:\"column-block\",scrollAreaClip:\"scroll-area-clip\",scrollAreaClipRect:\"scroll-area-clip-rect\",columnBoundary:\"column-boundary\",columnBoundaryClippath:\"column-boundary-clippath\",columnBoundaryRect:\"column-boundary-rect\",columnCells:\"column-cells\",columnCell:\"column-cell\",cellRect:\"cell-rect\",cellText:\"cell-text\",cellTextHolder:\"cell-text-holder\",scrollbarKit:\"scrollbar-kit\",scrollbar:\"scrollbar\",scrollbarSlider:\"scrollbar-slider\",scrollbarGlyph:\"scrollbar-glyph\",scrollbarCaptureZone:\"scrollbar-capture-zone\"}}},{}],1150:[function(t,e,r){\"use strict\";function n(t){return t.calcdata.columns.reduce(function(e,r){return r.xIndex=e||c===t.length-1)&&(n[i]=o,o.key=l++,o.firstRowIndex=s,o.lastRowIndex=c,o={firstRowIndex:null,lastRowIndex:null,rows:[]},i+=a,s=c+1,a=0);return n}var o=t(\"./constants\"),s=t(\"../../lib/extend\").extendFlat,l=t(\"fast-isnumeric\");e.exports=function(t,e){var r=e.header.values.map(function(t){return Array.isArray(t)?t:[t]}),c=e.cells.values,u=e.domain,f=Math.floor(t._fullLayout._size.w*(u.x[1]-u.x[0])),h=Math.floor(t._fullLayout._size.h*(u.y[1]-u.y[0])),d=r.length?r[0].map(function(){return e.header.height}):[],p=c.length?c[0].map(function(){return e.cells.height}):[],m=d.reduce(function(t,e){return t+e},0),g=a(p,h-m+o.uplift),v=i(a(d,m),[]),y=i(g,v),x={},b=e._fullInput.columnorder,_=r.map(function(t,r){var n=Array.isArray(e.columnwidth)?e.columnwidth[Math.min(r,e.columnwidth.length-1)]:e.columnwidth;return l(n)?Number(n):1}),w=_.reduce(function(t,e){return t+e},0);_=_.map(function(t){return t/w*f});var M={key:e.index,translateX:u.x[0]*t._fullLayout._size.w,translateY:t._fullLayout._size.h*(1-u.y[1]),size:t._fullLayout._size,width:f,height:h,columnOrder:b,groupHeight:h,rowBlocks:y,headerRowBlocks:v,scrollY:0,cells:e.cells,headerCells:s({},e.header,{values:r}),gdColumns:r.map(function(t){return t[0]}),gdColumnsOriginalOrder:r.map(function(t){return t[0]}),prevPages:[0,0],scrollbarState:{scrollbarScrollInProgress:!1},columns:r.map(function(t,e){var r=x[t];x[t]=(r||0)+1;return{key:t+\"__\"+x[t],label:t,specIndex:e,xIndex:b[e],xScale:n,x:void 0,calcdata:void 0,columnWidth:_[e]}})};return M.columns.forEach(function(t){t.calcdata=M,t.x=n(t)}),M}},{\"../../lib/extend\":732,\"./constants\":1149,\"fast-isnumeric\":140}],1151:[function(t,e,r){\"use strict\";var n=t(\"../../lib/extend\").extendFlat;r.splitToPanels=function(t){var e=[0,0],r=n({},t,{key:\"header\",type:\"header\",page:0,prevPages:e,currentRepaint:[null,null],dragHandle:!0,values:t.calcdata.headerCells.values[t.specIndex],rowBlocks:t.calcdata.headerRowBlocks,calcdata:n({},t.calcdata,{cells:t.calcdata.headerCells})});return[n({},t,{key:\"cells1\",type:\"cells\",page:0,prevPages:e,currentRepaint:[null,null],dragHandle:!1,values:t.calcdata.cells.values[t.specIndex],rowBlocks:t.calcdata.rowBlocks}),n({},t,{key:\"cells2\",type:\"cells\",page:1,prevPages:e,currentRepaint:[null,null],dragHandle:!1,values:t.calcdata.cells.values[t.specIndex],rowBlocks:t.calcdata.rowBlocks}),r]},r.splitToCells=function(t){var e=function(t){var e=t.rowBlocks[t.page],r=e?e.rows[0].rowIndex:0;return[r,e?r+e.rows.length:0]}(t);return t.values.slice(e[0],e[1]).map(function(r,n){return{keyWithinBlock:n+(\"string\"==typeof r&&r.match(/[<$&> ]/)?\"_keybuster_\"+Math.random():\"\"),key:e[0]+n,column:t,calcdata:t.calcdata,page:t.page,rowBlocks:t.rowBlocks,value:r}})}},{\"../../lib/extend\":732}],1152:[function(t,e,r){\"use strict\";var n=t(\"../../lib\"),i=t(\"./attributes\");e.exports=function(t,e,r,a){function o(r,a){return n.coerce(t,e,i,r,a)}o(\"domain.x\"),o(\"domain.y\"),o(\"columnwidth\"),o(\"header.values\"),o(\"header.format\"),o(\"header.align\"),o(\"header.prefix\"),o(\"header.suffix\"),o(\"header.height\"),o(\"header.line.width\"),o(\"header.line.color\"),o(\"header.fill.color\"),n.coerceFont(o,\"header.font\",n.extendFlat({},a.font)),function(t,e){for(var r=t.columnorder||[],n=t.header.values.length,i=r.slice(0,n),a=i.slice().sort(function(t,e){return t-e}),o=i.map(function(t){return a.indexOf(t)}),s=o.length;s/i),o=!i||a;t.mayHaveMarkup=i&&n.match(/[<&>]/);var s=function(t){return\"string\"==typeof t&&t.match(M.latexCheck)}(n);t.latex=s;var l,f=s?\"\":u(t.calcdata.cells.prefix,e,r)||\"\",h=s?\"\":u(t.calcdata.cells.suffix,e,r)||\"\",d=s?null:u(t.calcdata.cells.format,e,r)||null,p=f+(d?k.format(d)(t.value):t.value)+h;t.wrappingNeeded=!t.wrapped&&!o&&!s&&(l=c(p)),t.cellHeightMayIncrease=a||s||t.mayHaveMarkup||(void 0===l?c(p):l),t.needsConvertToTspans=t.mayHaveMarkup||t.wrappingNeeded||t.latex;var m;if(t.wrappingNeeded){var g=(\" \"===M.wrapSplitCharacter?p.replace(/c&&(t.value+=s.join(M.wrapSpacer)+M.lineBreaker,s=[],l=0),s.push(r.text),l+=i;l&&(t.value+=s.join(M.wrapSpacer)),t.wrapped=!0}),n.selectAll(\"tspan.line\").remove(),l(n.select(\".\"+M.cn.cellText),r,t),k.select(e.parentNode.parentNode).call(x)}}:function(t,e,r,n,i){return function(){if(!i.settledY){var a=k.select(e.parentNode),s=w(i),l=i.key-s.firstRowIndex,c=s.rows[l].rowHeight,u=i.cellHeightMayIncrease?e.parentNode.getBoundingClientRect().height+2*M.cellPad:c,f=Math.max(u,c),d=f-s.rows[l].rowHeight;d&&(s.rows[l].rowHeight=f,t.selectAll(\".\"+M.cn.columnCell).call(x),m(null,t.filter(h),0),o(r,n,!0)),a.attr(\"transform\",function(){var t=this.parentNode,e=t.getBoundingClientRect(),r=k.select(this.parentNode).select(\".\"+M.cn.cellRect).node().getBoundingClientRect(),n=this.transform.baseVal.consolidate(),a=r.top-e.top+(n?n.matrix.f:M.cellPad);return\"translate(\"+y(i,k.select(this.parentNode).select(\".\"+M.cn.cellTextHolder).node().getBoundingClientRect().width)+\" \"+a+\")\"}),i.settledY=!0}}};t.needsConvertToTspans?S.convertToTspans(i,n,a(r,this,e,n,t)):k.select(this.parentNode).attr(\"transform\",function(t){return\"translate(\"+y(t)+\" \"+M.cellPad+\")\"}).attr(\"text-anchor\",function(t){return{left:\"start\",center:\"middle\",right:\"end\"}[t.align]})})}function c(t){return-1!==t.indexOf(M.wrapSplitCharacter)}function u(t,e,r){if(Array.isArray(t)){var n=t[Math.min(e,t.length-1)];return Array.isArray(n)?n[Math.min(r,n.length-1)]:n}return t}function f(t,e,r){t.transition().ease(M.releaseTransitionEase).duration(M.releaseTransitionDuration).attr(\"transform\",\"translate(\"+e.x+\" \"+r+\")\")}function h(t){return\"cells\"===t.type}function d(t){return\"header\"===t.type}function p(t){return(t.rowBlocks.length?t.rowBlocks[0].auxiliaryBlocks:[]).reduce(function(t,e){return t+_(e,1/0)},0)}function m(t,e,r){var n=a(e)[0];if(void 0!==n){var i=n.rowBlocks,s=n.calcdata,l=b(i,i.length),c=n.calcdata.groupHeight-p(n),u=s.scrollY=Math.max(0,Math.min(l-c,s.scrollY)),f=function(t,e,r){for(var n=[],i=0,a=0;ai&&n.push(a),i+=l}return n}(i,u,c);1===f.length&&(f[0]===i.length-1?f.unshift(f[0]-1):f.push(f[0]+1)),f[0]%2&&f.reverse(),e.each(function(t,e){t.page=f[e],t.scrollY=u}),e.attr(\"transform\",function(t){return\"translate(0 \"+(b(t.rowBlocks,t.page)-t.scrollY)+\")\"}),t&&(v(t,r,e,f,n.prevPages,n,0),v(t,r,e,f,n.prevPages,n,1),o(r,t))}}function g(t,e,r,n){return function(i){var a=i.calcdata?i.calcdata:i,o=e.filter(function(t){return a.key===t.key}),s=r||a.scrollbarState.dragMultiplier;a.scrollY=void 0===n?a.scrollY+s*k.event.dy:n;var l=o.selectAll(\".\"+M.cn.yColumn).selectAll(\".\"+M.cn.columnBlock).filter(h);m(t,l,o)}}function v(t,e,r,n,i,a,o){n[o]!==i[o]&&(clearTimeout(a.currentRepaint[o]),a.currentRepaint[o]=setTimeout(function(){var a=r.filter(function(t,e){return e===o&&n[e]!==i[e]});s(t,e,a,r),i[o]=n[o]}))}function y(t,e){switch(t.align){case\"left\":return M.cellPad;case\"right\":return t.column.columnWidth-(e||0)-M.cellPad;case\"center\":return(t.column.columnWidth-(e||0))/2;default:return M.cellPad}}function x(t){t.attr(\"transform\",function(t){var e=t.rowBlocks[0].auxiliaryBlocks.reduce(function(t,e){return t+_(e,1/0)},0);return\"translate(0 \"+(_(w(t),t.key)+e)+\")\"}).selectAll(\".\"+M.cn.cellRect).attr(\"height\",function(t){return function(t,e){return t.rows[e-t.firstRowIndex]}(w(t),t.key).rowHeight})}function b(t,e){for(var r=0,n=e-1;n>=0;n--)r+=function(t){var e=t.allRowsHeight;if(void 0!==e)return e;for(var r=0,n=0;n0){var y,x,b,_,w,M=t.xa,k=t.ya;\"h\"===h.orientation?(w=e,y=\"y\",b=k,x=\"x\",_=M):(w=r,y=\"x\",b=M,x=\"y\",_=k);var A=f[t.index];if(w>=A.span[0]&&w<=A.span[1]){var T=n.extendFlat({},t),S=_.c2p(w,!0),E=o.getKdeValue(A,h,w),L=o.getPositionOnKdePath(A,h,S),C=b._offset,z=b._length;T[y+\"0\"]=L[0],T[y+\"1\"]=L[1],T[x+\"0\"]=T[x+\"1\"]=S,T[x+\"Label\"]=x+\": \"+i.hoverLabelText(_,w)+\", \"+f[0].t.labels.kde+\" \"+E.toFixed(3),g.push(T),(u={stroke:t.color})[y+\"1\"]=n.constrain(C+L[0],C,C+z),u[y+\"2\"]=n.constrain(C+L[1],C,C+z),u[x+\"1\"]=u[x+\"2\"]=_._offset+S}}}-1!==d.indexOf(\"points\")&&(c=a.hoverOnPoints(t,e,r));var D=l.selectAll(\".violinline-\"+h.uid).data(u?[0]:[]);return D.enter().append(\"line\").classed(\"violinline-\"+h.uid,!0).attr(\"stroke-width\",1.5),D.exit().remove(),D.attr(u),\"closest\"===s?c?[c]:g:c?(g.push(c),g):g}},{\"../../lib\":743,\"../../plots/cartesian/axes\":789,\"../box/hover\":899,\"./helpers\":1158}],1160:[function(t,e,r){\"use strict\";e.exports={attributes:t(\"./attributes\"),layoutAttributes:t(\"./layout_attributes\"),supplyDefaults:t(\"./defaults\"),supplyLayoutDefaults:t(\"./layout_defaults\"),calc:t(\"./calc\"),setPositions:t(\"./set_positions\"),plot:t(\"./plot\"),style:t(\"./style\"),hoverPoints:t(\"./hover\"),selectPoints:t(\"../box/select\"),moduleType:\"trace\",name:\"violin\",basePlotModule:t(\"../../plots/cartesian\"),categories:[\"cartesian\",\"symbols\",\"oriented\",\"box-violin\",\"showLegend\"],meta:{}}},{\"../../plots/cartesian\":800,\"../box/select\":904,\"./attributes\":1155,\"./calc\":1156,\"./defaults\":1157,\"./hover\":1159,\"./layout_attributes\":1161,\"./layout_defaults\":1162,\"./plot\":1163,\"./set_positions\":1164,\"./style\":1165}],1161:[function(t,e,r){\"use strict\";var n=t(\"../box/layout_attributes\"),i=t(\"../../lib\").extendFlat;e.exports={violinmode:i({},n.boxmode,{}),violingap:i({},n.boxgap,{}),violingroupgap:i({},n.boxgroupgap,{})}},{\"../../lib\":743,\"../box/layout_attributes\":901}],1162:[function(t,e,r){\"use strict\";var n=t(\"../../lib\"),i=t(\"./layout_attributes\"),a=t(\"../box/layout_defaults\");e.exports=function(t,e,r){a._supply(t,e,r,function(r,a){return n.coerce(t,e,i,r,a)},\"violin\")}},{\"../../lib\":743,\"../box/layout_defaults\":902,\"./layout_attributes\":1161}],1163:[function(t,e,r){\"use strict\";var n=t(\"d3\"),i=t(\"../../lib\"),a=t(\"../../components/drawing\"),o=t(\"../box/plot\"),s=t(\"../scatter/line_points\"),l=t(\"./helpers\");e.exports=function(t,e,r){function c(t){var e=s(t,{xaxis:f,yaxis:h,connectGaps:!0,baseTolerance:.75,shape:\"spline\",simplify:!0});return a.smoothopen(e[0],1)}var u=t._fullLayout,f=e.xaxis,h=e.yaxis;e.plot.select(\".violinlayer\").selectAll(\"g.trace.violins\").data(r).enter().append(\"g\").attr(\"class\",\"trace violins\").each(function(t){var r=t[0],a=r.t,s=r.trace,d=r.node3=n.select(this),p=u._numViolins,m=\"group\"===u.violinmode&&p>1,g=a.bdPos=a.dPos*(1-u.violingap)*(1-u.violingroupgap)/(m?p:1),v=a.bPos=m?2*a.dPos*((a.num+.5)/p-.5)*(1-u.violingap):0;if(!0!==s.visible||a.empty)n.select(this).remove();else{var y=e[a.valLetter+\"axis\"],x=e[a.posLetter+\"axis\"],b=\"both\"===s.side,_=b||\"positive\"===s.side,w=b||\"negative\"===s.side,M=s.box&&s.box.visible,k=s.meanline&&s.meanline.visible,A=u._violinScaleGroupStats[s.scalegroup];if(d.selectAll(\"path.violin\").data(i.identity).enter().append(\"path\").style(\"vector-effect\",\"non-scaling-stroke\").attr(\"class\",\"violin\").each(function(t){var e,r=n.select(this),i=t.density,o=i.length,l=t.pos+v,u=x.c2p(l);switch(s.scalemode){case\"width\":e=A.maxWidth/g;break;case\"count\":e=A.maxWidth/g*(A.maxCount/t.pts.length)}var f,h,d,p,m,M,k;if(_){for(M=new Array(o),p=0;pi&&(i=c,a=l)}}return i?s(a):f};case\"rms\":return function(t,e){for(var r=0,i=0,a=0;a=\",\">\",\"<=\"],l=[\"[]\",\"()\",\"[)\",\"(]\",\"][\",\")(\",\"](\",\")[\"],c=[\"{}\",\"}{\"];r.moduleType=\"transform\",r.name=\"filter\",r.attributes={enabled:{valType:\"boolean\",dflt:!0,editType:\"calc\"},target:{valType:\"string\",strict:!0,noBlank:!0,arrayOk:!0,dflt:\"x\",editType:\"calc\"},operation:{valType:\"enumerated\",values:[].concat(s).concat(l).concat(c),dflt:\"=\",editType:\"calc\"},value:{valType:\"any\",dflt:0,editType:\"calc\"},preservegaps:{valType:\"boolean\",dflt:!1,editType:\"calc\"},editType:\"calc\"},r.supplyDefaults=function(t){function e(e,i){return n.coerce(t,a,r.attributes,e,i)}var a={};if(e(\"enabled\")){e(\"preservegaps\"),e(\"operation\"),e(\"value\"),e(\"target\");var o=i.getComponentMethod(\"calendars\",\"handleDefaults\");o(t,a,\"valuecalendar\",null),o(t,a,\"targetcalendar\",null)}return a},r.calcTransform=function(t,e,r){function i(t,r){for(var i=0;i\":return function(t){return h(t)>i};case\">=\":return function(t){return h(t)>=i};case\"[]\":return function(t){var e=h(t);return e>=i[0]&&e<=i[1]};case\"()\":return function(t){var e=h(t);return e>i[0]&&e=i[0]&&ei[0]&&e<=i[1]};case\"][\":return function(t){var e=h(t);return e<=i[0]||e>=i[1]};case\")(\":return function(t){var e=h(t);return ei[1]};case\"](\":return function(t){var e=h(t);return e<=i[0]||e>i[1]};case\")[\":return function(t){var e=h(t);return e=i[1]};case\"{}\":return function(t){return-1!==i.indexOf(h(t))};case\"}{\":return function(t){return-1===i.indexOf(h(t))}}}(r,a.getDataToCoordFunc(t,e,f,u),d),x={},b={},_=0;r.preservegaps?(g=function(t){x[t.astr]=n.extendDeep([],t.get()),t.set(new Array(h))},v=function(t,e){var r=x[t.astr][e];t.get()[e]=r}):(g=function(t){x[t.astr]=n.extendDeep([],t.get()),t.set([])},v=function(t,e){var r=x[t.astr][e];t.get().push(r)}),i(g);for(var w=o(e.transforms,r),M=0;M1?\"%{group} (%{trace})\":\"%{group}\");var l=t.styles,c=s.styles=[];if(l)for(o=0;o" + ], + "text/vnd.plotly.v1+html": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "# Imports\n", + "from plotly.offline import init_notebook_mode, plot, iplot\n", + "import plotly.graph_objs as go\n", + "\n", + "# Initialize notebook mode (Needed by iplot)\n", + "init_notebook_mode()" + ] + }, + { + "cell_type": "code", + "execution_count": 16, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "'file:///Users/measejm1/Programming/PyDataStack/repos/plotly.py/specs/ipyplotly_integration/exports/tmp.html'" + ] + }, + "execution_count": 16, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# The graph_obj constructors (inluding Figure) are now pretty compatible with legacy code\n", + "fig = go.Figure([go.Scatter(x=[1, 2, 3], y=[3, 1, 6], marker=go.Marker(color='green'))])\n", + "plot(fig, filename='exports/tmp.html')" + ] + }, + { + "cell_type": "code", + "execution_count": 10, + "metadata": {}, + "outputs": [ + { + "data": { + "application/vnd.plotly.v1+json": { + "data": [ + { + "marker": { + "color": "green" + }, + "type": "scatter", + "uid": "c37518da-15ca-11e8-8682-a0999b0c017b", + "x": [ + 1, + 2, + 3 + ], + "xaxis": "x", + "y": [ + 3, + 1, + 6 + ], + "yaxis": "y" + } + ], + "layout": {} + }, + "text/html": [ + "
" + ], + "text/vnd.plotly.v1+html": [ + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "iplot(fig)" + ] + }, + { + "cell_type": "code", + "execution_count": 11, + "metadata": {}, + "outputs": [ + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "89e3be80b4bc48b5bda9115d75bb90db", + "version_major": 2, + "version_minor": 0 + }, + "text/html": [ + "

Failed to display Jupyter Widget of type FigureWidget.

\n", + "

\n", + " If you're reading this message in the Jupyter Notebook or JupyterLab Notebook, it may mean\n", + " that the widgets JavaScript is still loading. If this message persists, it\n", + " likely means that the widgets JavaScript library is either not installed or\n", + " not enabled. See the Jupyter\n", + " Widgets Documentation for setup instructions.\n", + "

\n", + "

\n", + " If you're reading this message in another frontend (for example, a static\n", + " rendering on GitHub or NBViewer),\n", + " it may mean that your frontend doesn't currently support widgets.\n", + "

\n" + ], + "text/plain": [ + "FigureWidget()" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "# Instead of using iplot, we can construct a FigureWidget and it will be displayed in the notebook automatically\n", + "fig_widget = go.FigureWidget([go.Scatter(x=[1, 2, 3], y=[3, 1, 6], marker=go.Marker(color='green'))])\n", + "fig_widget" + ] + }, + { + "cell_type": "code", + "execution_count": 12, + "metadata": {}, + "outputs": [], + "source": [ + "# Now we can update x-axis range in-place and see the updates reflected in the already displayed figure above\n", + "fig_widget.layout.xaxis.range = [0, 5]\n" + ] + }, + { + "cell_type": "code", + "execution_count": 13, + "metadata": {}, + "outputs": [], + "source": [ + "# Trace properties can be modified in place as well\n", + "scatt = fig_widget.data[0]\n", + "scatt.line.dash = 'longdash'" + ] + }, + { + "cell_type": "code", + "execution_count": 14, + "metadata": {}, + "outputs": [ + { + "ename": "ValueError", + "evalue": "\n Invalid value of type 'builtins.str' received for the 'mode' property of trace.scatter\n Received value: 'marker'\n\n The 'mode' property is a flaglist and may be specified as a string containing:\n - Any combination of ['lines', 'markers', 'text'] joined with '+' characters (e.g. 'lines+markers')\n OR exactly one of ['none'] (e.g. 'none')\n", + "output_type": "error", + "traceback": [ + "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", + "\u001b[0;31mValueError\u001b[0m Traceback (most recent call last)", + "\u001b[0;32m\u001b[0m in \u001b[0;36m\u001b[0;34m()\u001b[0m\n\u001b[1;32m 1\u001b[0m \u001b[0;31m# Detailed value validation is performed on parameters passed to the Figure constructor\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 2\u001b[0m \u001b[0;31m# Here we set 'moded to 'marker' instead of 'markers'\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m----> 3\u001b[0;31m \u001b[0mgo\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mFigure\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0mgo\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mScatter\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mx\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0;36m1\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;36m2\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;36m3\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0my\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0;36m3\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;36m1\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;36m6\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mmarker\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0mgo\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mMarker\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mcolor\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0;34m'green'\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mmode\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0;34m'marker'\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m", + "\u001b[0;32m~/Programming/PyDataStack/repos/plotly.py/plotly/datatypes/trace/__init__.py\u001b[0m in \u001b[0;36m__init__\u001b[0;34m(self, cliponaxis, connectgaps, customdata, customdatasrc, dx, dy, error_x, error_y, fill, fillcolor, hoverinfo, hoverinfosrc, hoverlabel, hoveron, hovertext, hovertextsrc, ids, idssrc, legendgroup, line, marker, mode, name, opacity, r, rsrc, selected, selectedpoints, showlegend, stream, t, text, textfont, textposition, textpositionsrc, textsrc, tsrc, uid, unselected, visible, x, x0, xaxis, xcalendar, xsrc, y, y0, yaxis, ycalendar, ysrc, **kwargs)\u001b[0m\n\u001b[1;32m 26269\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mline\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mline\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 26270\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mmarker\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mmarker\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m> 26271\u001b[0;31m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mmode\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mmode\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 26272\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mname\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mname\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 26273\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mopacity\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mopacity\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", + "\u001b[0;32m~/Programming/PyDataStack/repos/plotly.py/plotly/basedatatypes.py\u001b[0m in \u001b[0;36m__setattr__\u001b[0;34m(self, prop, value)\u001b[0m\n\u001b[1;32m 1250\u001b[0m \u001b[0;32mif\u001b[0m \u001b[0mprop\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mstartswith\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m'_'\u001b[0m\u001b[0;34m)\u001b[0m \u001b[0;32mor\u001b[0m \u001b[0mhasattr\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mself\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mprop\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 1251\u001b[0m \u001b[0;31m# Let known properties and private properties through\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m-> 1252\u001b[0;31m \u001b[0msuper\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0m__setattr__\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mprop\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mvalue\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 1253\u001b[0m \u001b[0;32melse\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 1254\u001b[0m \u001b[0;31m# Raise error on unknown public properties\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", + "\u001b[0;32m~/Programming/PyDataStack/repos/plotly.py/plotly/datatypes/trace/__init__.py\u001b[0m in \u001b[0;36mmode\u001b[0;34m(self, val)\u001b[0m\n\u001b[1;32m 25235\u001b[0m \u001b[0;34m@\u001b[0m\u001b[0mmode\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0msetter\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 25236\u001b[0m \u001b[0;32mdef\u001b[0m \u001b[0mmode\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mself\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mval\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m> 25237\u001b[0;31m \u001b[0mself\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0;34m'mode'\u001b[0m\u001b[0;34m]\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mval\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 25238\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 25239\u001b[0m \u001b[0;31m# name\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", + "\u001b[0;32m~/Programming/PyDataStack/repos/plotly.py/plotly/basedatatypes.py\u001b[0m in \u001b[0;36m__setitem__\u001b[0;34m(self, key, value)\u001b[0m\n\u001b[1;32m 1405\u001b[0m \u001b[0;32melse\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 1406\u001b[0m \u001b[0;31m# Simple property\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m-> 1407\u001b[0;31m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0m_set_prop\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mkey\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mvalue\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 1408\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 1409\u001b[0m \u001b[0;34m@\u001b[0m\u001b[0mproperty\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", + "\u001b[0;32m~/Programming/PyDataStack/repos/plotly.py/plotly/basedatatypes.py\u001b[0m in \u001b[0;36m_set_prop\u001b[0;34m(self, prop, val)\u001b[0m\n\u001b[1;32m 1424\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 1425\u001b[0m \u001b[0mvalidator\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0m_validators\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mget\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mprop\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m-> 1426\u001b[0;31m \u001b[0mval\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mvalidator\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mvalidate_coerce\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mval\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 1427\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 1428\u001b[0m \u001b[0;32mif\u001b[0m \u001b[0mval\u001b[0m \u001b[0;32mis\u001b[0m \u001b[0;32mNone\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", + "\u001b[0;32m~/Programming/PyDataStack/repos/plotly.py/plotly/basevalidators.py\u001b[0m in \u001b[0;36mvalidate_coerce\u001b[0;34m(self, v)\u001b[0m\n\u001b[1;32m 925\u001b[0m \u001b[0mvalidated_v\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mperform_validate_coerce\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mv\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 926\u001b[0m \u001b[0;32mif\u001b[0m \u001b[0mvalidated_v\u001b[0m \u001b[0;32mis\u001b[0m \u001b[0;32mNone\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m--> 927\u001b[0;31m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mraise_invalid_val\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mv\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 928\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 929\u001b[0m \u001b[0mv\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mvalidated_v\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", + "\u001b[0;32m~/Programming/PyDataStack/repos/plotly.py/plotly/basevalidators.py\u001b[0m in \u001b[0;36mraise_invalid_val\u001b[0;34m(self, v)\u001b[0m\n\u001b[1;32m 104\u001b[0m \u001b[0mtyp\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0mtype_str\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mv\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 105\u001b[0m \u001b[0mv\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0mrepr\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mv\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m--> 106\u001b[0;31m vald_clr_desc=self.description()))\n\u001b[0m\u001b[1;32m 107\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 108\u001b[0m \u001b[0;32mdef\u001b[0m \u001b[0mraise_invalid_elements\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mself\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0minvalid_els\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", + "\u001b[0;31mValueError\u001b[0m: \n Invalid value of type 'builtins.str' received for the 'mode' property of trace.scatter\n Received value: 'marker'\n\n The 'mode' property is a flaglist and may be specified as a string containing:\n - Any combination of ['lines', 'markers', 'text'] joined with '+' characters (e.g. 'lines+markers')\n OR exactly one of ['none'] (e.g. 'none')\n" + ] + } + ], + "source": [ + "# Detailed value validation is performed on parameters passed to the Figure constructor\n", + "# Here we set 'moded to 'marker' instead of 'markers'\n", + "go.Figure([go.Scatter(x=[1, 2, 3], y=[3, 1, 6], marker=go.Marker(color='green'), mode='marker')])" + ] + }, + { + "cell_type": "code", + "execution_count": 15, + "metadata": {}, + "outputs": [ + { + "ename": "ValueError", + "evalue": "\n Invalid value of type 'builtins.str' received for the 'mode' property of trace.scatter\n Received value: 'marker'\n\n The 'mode' property is a flaglist and may be specified as a string containing:\n - Any combination of ['lines', 'markers', 'text'] joined with '+' characters (e.g. 'lines+markers')\n OR exactly one of ['none'] (e.g. 'none')\n", + "output_type": "error", + "traceback": [ + "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", + "\u001b[0;31mValueError\u001b[0m Traceback (most recent call last)", + "\u001b[0;32m\u001b[0m in \u001b[0;36m\u001b[0;34m()\u001b[0m\n\u001b[1;32m 1\u001b[0m \u001b[0;31m# The same validation is performed on property assignment\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m----> 2\u001b[0;31m \u001b[0mscatt\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mmode\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0;34m'marker'\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m", + "\u001b[0;32m~/Programming/PyDataStack/repos/plotly.py/plotly/basedatatypes.py\u001b[0m in \u001b[0;36m__setattr__\u001b[0;34m(self, prop, value)\u001b[0m\n\u001b[1;32m 1250\u001b[0m \u001b[0;32mif\u001b[0m \u001b[0mprop\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mstartswith\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m'_'\u001b[0m\u001b[0;34m)\u001b[0m \u001b[0;32mor\u001b[0m \u001b[0mhasattr\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mself\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mprop\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 1251\u001b[0m \u001b[0;31m# Let known properties and private properties through\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m-> 1252\u001b[0;31m \u001b[0msuper\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0m__setattr__\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mprop\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mvalue\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 1253\u001b[0m \u001b[0;32melse\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 1254\u001b[0m \u001b[0;31m# Raise error on unknown public properties\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", + "\u001b[0;32m~/Programming/PyDataStack/repos/plotly.py/plotly/datatypes/trace/__init__.py\u001b[0m in \u001b[0;36mmode\u001b[0;34m(self, val)\u001b[0m\n\u001b[1;32m 25235\u001b[0m \u001b[0;34m@\u001b[0m\u001b[0mmode\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0msetter\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 25236\u001b[0m \u001b[0;32mdef\u001b[0m \u001b[0mmode\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mself\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mval\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m> 25237\u001b[0;31m \u001b[0mself\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0;34m'mode'\u001b[0m\u001b[0;34m]\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mval\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 25238\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 25239\u001b[0m \u001b[0;31m# name\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", + "\u001b[0;32m~/Programming/PyDataStack/repos/plotly.py/plotly/basedatatypes.py\u001b[0m in \u001b[0;36m__setitem__\u001b[0;34m(self, key, value)\u001b[0m\n\u001b[1;32m 1405\u001b[0m \u001b[0;32melse\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 1406\u001b[0m \u001b[0;31m# Simple property\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m-> 1407\u001b[0;31m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0m_set_prop\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mkey\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mvalue\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 1408\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 1409\u001b[0m \u001b[0;34m@\u001b[0m\u001b[0mproperty\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", + "\u001b[0;32m~/Programming/PyDataStack/repos/plotly.py/plotly/basedatatypes.py\u001b[0m in \u001b[0;36m_set_prop\u001b[0;34m(self, prop, val)\u001b[0m\n\u001b[1;32m 1424\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 1425\u001b[0m \u001b[0mvalidator\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0m_validators\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mget\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mprop\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m-> 1426\u001b[0;31m \u001b[0mval\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mvalidator\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mvalidate_coerce\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mval\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 1427\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 1428\u001b[0m \u001b[0;32mif\u001b[0m \u001b[0mval\u001b[0m \u001b[0;32mis\u001b[0m \u001b[0;32mNone\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", + "\u001b[0;32m~/Programming/PyDataStack/repos/plotly.py/plotly/basevalidators.py\u001b[0m in \u001b[0;36mvalidate_coerce\u001b[0;34m(self, v)\u001b[0m\n\u001b[1;32m 925\u001b[0m \u001b[0mvalidated_v\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mperform_validate_coerce\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mv\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 926\u001b[0m \u001b[0;32mif\u001b[0m \u001b[0mvalidated_v\u001b[0m \u001b[0;32mis\u001b[0m \u001b[0;32mNone\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m--> 927\u001b[0;31m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mraise_invalid_val\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mv\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 928\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 929\u001b[0m \u001b[0mv\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mvalidated_v\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", + "\u001b[0;32m~/Programming/PyDataStack/repos/plotly.py/plotly/basevalidators.py\u001b[0m in \u001b[0;36mraise_invalid_val\u001b[0;34m(self, v)\u001b[0m\n\u001b[1;32m 104\u001b[0m \u001b[0mtyp\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0mtype_str\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mv\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 105\u001b[0m \u001b[0mv\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0mrepr\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mv\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m--> 106\u001b[0;31m vald_clr_desc=self.description()))\n\u001b[0m\u001b[1;32m 107\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 108\u001b[0m \u001b[0;32mdef\u001b[0m \u001b[0mraise_invalid_elements\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mself\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0minvalid_els\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", + "\u001b[0;31mValueError\u001b[0m: \n Invalid value of type 'builtins.str' received for the 'mode' property of trace.scatter\n Received value: 'marker'\n\n The 'mode' property is a flaglist and may be specified as a string containing:\n - Any combination of ['lines', 'markers', 'text'] joined with '+' characters (e.g. 'lines+markers')\n OR exactly one of ['none'] (e.g. 'none')\n" + ] + } + ], + "source": [ + "# The same validation is performed on property assignment\n", + "scatt.mode = 'marker'" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python [conda env:ipyplotly_integration]", + "language": "python", + "name": "conda-env-ipyplotly_integration-py" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.6.4" + }, + "widgets": { + "application/vnd.jupyter.widget-state+json": { + "state": { + "7df79e56dce64c1ab7be9e8b1df64d49": { + "model_module": "plotlywidget", + "model_module_version": "1.0.0", + "model_name": "FigureModel", + "state": { + "_data": [ + { + "_relayout_msg_id": 2, + "_restyle_msg_id": 1, + "line": { + "dash": "longdash" + }, + "marker": { + "color": "green" + }, + "type": "scatter", + "uid": "079cc02c-15c5-11e8-862d-a0999b0c017b", + "x": [ + 1, + 2, + 3 + ], + "xaxis": "x", + "y": [ + 3, + 1, + 6 + ], + "yaxis": "y" + } + ], + "_js2py_pointsCallback": {}, + "_js2py_relayout": {}, + "_js2py_restyle": [], + "_js2py_styleDelta": null, + "_js2py_update": {}, + "_last_relayout_msg_id": 2, + "_last_restyle_msg_id": 1, + "_layout": { + "_relayout_msg_id": 1, + "xaxis": { + "range": [ + 0, + 5 + ] + } + }, + "_py2js_addTraces": [], + "_py2js_animate": [], + "_py2js_deleteTraces": {}, + "_py2js_moveTraces": [], + "_py2js_removeLayoutProps": [], + "_py2js_removeStyleProps": [], + "_py2js_requestSvg": "", + "_py2js_update": [], + "_view_count": 1, + "_view_module_version": "" + } + } + }, + "version_major": 2, + "version_minor": 0 + } + } + }, + "nbformat": 4, + "nbformat_minor": 2 +} diff --git a/specs/ipyplotly_integration/DataShaderExample.ipynb b/specs/ipyplotly_integration/DataShaderExample.ipynb new file mode 100644 index 00000000000..0ccde10d532 --- /dev/null +++ b/specs/ipyplotly_integration/DataShaderExample.ipynb @@ -0,0 +1,527 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Overview\n", + "This notebook demonstrates how to use DataShader to display large datasets inside a plotly FigureWidget. Change callbacks are used to recompute the datashader image whenever the axis range or figure size changes" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Install Datashader" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "`$ conda install datashader -y`" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Imports" + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "metadata": {}, + "outputs": [], + "source": [ + "# ipyplotly\n", + "from plotly.graph_objs import FigureWidget\n", + "\n", + "# core\n", + "import io\n", + "import base64 \n", + "import time\n", + "\n", + "# pandas\n", + "import pandas as pd\n", + "\n", + "# numpy\n", + "import numpy as np\n", + "\n", + "# scikit learn\n", + "from sklearn import datasets\n", + "\n", + "# datashader\n", + "import datashader as ds\n", + "import datashader.transfer_functions as tf\n", + "from datashader.colors import inferno" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Generate dataset\n", + "We will create a large dataset by duplicating the Iris dataset many times with random noise" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + "
\n", + "\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
sepal_lengthsepal_widthpetal_lengthpetal_width
count1.050000e+061.050000e+061.050000e+061.050000e+06
mean5.843334e+003.054174e+003.758513e+001.198656e+00
std8.491408e-014.760660e-011.769797e+007.867412e-01
min3.570904e+001.288017e+001.595338e-01-7.130906e-01
25%5.156203e+002.740191e+001.637389e+003.925065e-01
50%5.801178e+003.033385e+004.307065e+001.316142e+00
75%6.443619e+003.346452e+005.142117e+001.827593e+00
max8.665589e+005.200911e+007.662023e+003.353820e+00
\n", + "
" + ], + "text/plain": [ + " sepal_length sepal_width petal_length petal_width\n", + "count 1.050000e+06 1.050000e+06 1.050000e+06 1.050000e+06\n", + "mean 5.843334e+00 3.054174e+00 3.758513e+00 1.198656e+00\n", + "std 8.491408e-01 4.760660e-01 1.769797e+00 7.867412e-01\n", + "min 3.570904e+00 1.288017e+00 1.595338e-01 -7.130906e-01\n", + "25% 5.156203e+00 2.740191e+00 1.637389e+00 3.925065e-01\n", + "50% 5.801178e+00 3.033385e+00 4.307065e+00 1.316142e+00\n", + "75% 6.443619e+00 3.346452e+00 5.142117e+00 1.827593e+00\n", + "max 8.665589e+00 5.200911e+00 7.662023e+00 3.353820e+00" + ] + }, + "execution_count": 2, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "num_copies = 7000 # 1,050,000 rows\n", + "\n", + "iris_data = datasets.load_iris()\n", + "feature_names = [name.replace(' (cm)', '').replace(' ', '_') for name in iris_data.feature_names]\n", + "iris_df_orig = pd.DataFrame(iris_data.data, columns=feature_names)\n", + "target_orig = iris_data.target + 1\n", + "\n", + "# frame of features\n", + "iris_df = pd.concat(\n", + " np.random.normal(scale=0.2, size=iris_df_orig.shape) + iris_df_orig for i in range(num_copies)\n", + ").reset_index(drop=True)\n", + "\n", + "# array of targets\n", + "target = [t for i in range(num_copies) for t in target_orig]\n", + "\n", + "# dataframe that includes target as categorical\n", + "iris_target_df = pd.concat([iris_df, pd.Series(target, name='target', dtype='category')], axis=1)\n", + "\n", + "iris_df.describe()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Define DataShader image generation function\n", + "Define a function that inputs an x/y ranges and the plot width/height and generates a DataShader image of the dataset. The image will be returned as a PIL image object" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "metadata": {}, + "outputs": [], + "source": [ + "def gen_ds_image(x_range, y_range, plot_width, plot_height):\n", + " if x_range is None or y_range is None or plot_width is None or plot_height is None:\n", + " return None\n", + " \n", + " cvs = ds.Canvas(x_range=x_range, y_range=y_range, plot_height=plot_height, plot_width=plot_width)\n", + " agg_scatter = cvs.points(iris_target_df, \n", + " 'sepal_length', 'sepal_width', \n", + " ds.count_cat('target'))\n", + " img = tf.shade(agg_scatter)\n", + " img = tf.dynspread(img, threshold=0.95, max_px=5, shape='circle')\n", + " \n", + " return img.to_pil()" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "collapsed": true + }, + "source": [ + "## Define initial ranges and plot size" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "metadata": {}, + "outputs": [], + "source": [ + "x_range=[3, 10]\n", + "y_range=[0, 6]\n", + "plot_height=500\n", + "plot_width=700" + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "metadata": {}, + "outputs": [], + "source": [ + "# Test image generation function and display the PIL image\n", + "initial_img = gen_ds_image(x_range, y_range, plot_width, plot_height)" + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "metadata": {}, + "outputs": [ + { + "data": { + "image/png": "iVBORw0KGgoAAAANSUhEUgAAArwAAAH0CAYAAADfWf7fAAEAAElEQVR4nOz9W4wkd5rlif0+83vcMy6ZEZmRSQZZLBZZ2ZyurpwmqjRV2prpFqYpETsNSBAkzT5osBgJkDDSu4QBJECA9CQ9LQQ9LDCCoAdptSWhgenBahq9aK66UTvsqe5qDrs4LFYWM4OZybzG3e929PD9/2bmHhF54TUz+T8gM9zN7ebm5ubHzv9854OEhISEhISEhISEhISEhISEhISEhISEhISEhISEhISEhISEhISEhISEhISEhISEhISEhISEhISEhISEhISEhISEhISEhISEhISEhISEhISEhISEhISEhISEhISEhISEhISEhISEhISEhISEhISEhISEhISEhISEhISEhISEhISEhISEhISEhISEhISEhISEhISEhISEhISEhISEhISEhISEhISEhISEhISEhISEhISEhISEhISEhISEhISEhISEhISEhISEhISEhISEhISEhISEhISEhISEhISEhISEhISEhISEhISEhISEhISEhISEhISEhISEhISEhISEhISEhISEhISEhISEhISEhISEhISEhISEhISEhISEhISEhISEhISEhISEhISEhISEhISEhISEhISEhISEhISEhISEhISEhISEhISEhISEhISEhISEhISEhISEhISEhISEhISEhISEhISEhISEhISEhISEhISEhISEhISEhISEhISEhISEhISEhISEhISEhISEhISEhISEhISEhISEhISEhISEhISEhISEhISEhISEhISEhISEhISEhISEhISEhISEhISEhISEhISEhISEhISEhISEhISEhISEhISEhISEhISEhISEhISEhISEhISEhISEhISEhISEhISEhISEhISEhISEhISEhISEhISEhISEhISEhISEhISEhISEhISEhISEhISEhISEhISEhISEhISEhISEhISEhISEhISEhISEhISEhISEhISEhISEhISEhISEhISEhISEhISEhISEhISEhISEhISEhISEhISEhISEhISEhISEhISEhISEhISEhISEhISEhISEhISEhISEhISEhISEhISEhISEhISEhISEhISEhISEhISEhISEhISEhISEhISEhISEhISEhISEhISEhISEhISEhIRnCvZ170BCQgJcP7/5nfj4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CCGEEEIIIYQQQgghhBBCCCGEEEIIIYQQQgghhBBCCCGEEEIIIYQQQgghhBBCCCGEEEIIIYQQQgghhBBCCCGEEEIIIYQQQgghhBBCCCGEEEIIIYQQQgghhBBCCCGEEEIIIYQQQgghhBBCCCGEEEIIIYQQQgghhBBCCCGEEEIIIYQQQgghhBBCCCGEEEIIIYQQQgghhBBCCCGEEEIIIYQQQgghhBBCCCGEEEIIIYQQQgghhBBCCCGEEEIIIYQQQgghhBBCCCGEEEIIIYQQQgghhBBCCCGEEEIIIYQQQgghhBBCCCGEEEIIIYQQQgghhBBCCCGEEEIIIYQQQgghhBBCCCGEEEIIIYQQQgghhBBCCCGEEEIIIYQQQgghhBBCCCGEEEIIIYQQQgghhBBCCCGEEEIIIYQQQgghhBBCCCGEEEIIIYQQQgghhBBCCCGEEEIIIYQQQgghhBBCCCGEEEIIIYQQQgghhBBCCCGEEEIIIYQQQgghhBBCCCGEEEIIIYQQQgghhBBCCCGEEEIIIYQQQgghhBBCCCGEEEIIIYQQQgghhBBCCCGEEEIIIYQQQgghhBBCCCGEEEIIIYQQQgghhBBCCCGEEEIIIYQQQgghhBBCCCGEEEIIIYQQQgghhBBCCCGEEB8b/3/9gWJJlRvQkAAAAABJRU5ErkJggg==\n", + "text/plain": [ + "" + ] + }, + "execution_count": 6, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "initial_img" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Create FigureWidget with background image" + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "metadata": { + "scrolled": false + }, + "outputs": [ + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "c31816a040ee41af8b9071ef55c79000", + "version_major": 2, + "version_minor": 0 + }, + "text/html": [ + "

Failed to display Jupyter Widget of type FigureWidget.

\n", + "

\n", + " If you're reading this message in the Jupyter Notebook or JupyterLab Notebook, it may mean\n", + " that the widgets JavaScript is still loading. If this message persists, it\n", + " likely means that the widgets JavaScript library is either not installed or\n", + " not enabled. See the Jupyter\n", + " Widgets Documentation for setup instructions.\n", + "

\n", + "

\n", + " If you're reading this message in another frontend (for example, a static\n", + " rendering on GitHub or NBViewer),\n", + " it may mean that your frontend doesn't currently support widgets.\n", + "

\n" + ], + "text/plain": [ + "FigureWidget()" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "f = FigureWidget(data=[{'x': x_range, \n", + " 'y': y_range, \n", + " 'mode': 'markers',\n", + " 'marker': {'opacity': 0}}], # invisible trace to init axes and to support autoresize\n", + " layout={'width': plot_width, 'height': plot_height})\n", + "f" + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "metadata": {}, + "outputs": [], + "source": [ + "# Set background image\n", + "f.layout.images = [dict(\n", + " source = initial_img, # plotly now performs auto conversion of PIL image to png data URI\n", + " xref = \"x\",\n", + " yref = \"y\",\n", + " x = x_range[0],\n", + " y = y_range[1],\n", + " sizex = x_range[1] - x_range[0],\n", + " sizey = y_range[1] - y_range[0],\n", + " sizing = \"stretch\",\n", + " layer = \"below\")]" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Install change callback to update image on zoom/resize" + ] + }, + { + "cell_type": "code", + "execution_count": 9, + "metadata": {}, + "outputs": [], + "source": [ + "def update_ds_image(layout, x_range, y_range, plot_width, plot_height):\n", + " img = f.layout.images[0]\n", + " \n", + " # Update with batch_update so all updates happen simultaneously\n", + " with f.batch_update():\n", + " img.x = x_range[0]\n", + " img.y = y_range[1]\n", + " img.sizex = x_range[1] - x_range[0]\n", + " img.sizey = y_range[1] - y_range[0]\n", + " img.source = gen_ds_image(x_range, y_range, plot_width, plot_height)\n", + "\n", + "# Install callback to run exactly once if one or more of the following properties changes\n", + "# - xaxis range\n", + "# - yaxis range\n", + "# - figure width\n", + "# - figure height\n", + "f.layout.on_change(update_ds_image, ('xaxis', 'range'), ('yaxis', 'range'), 'width', 'height')" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Image updates on drag zoom" + ] + }, + { + "cell_type": "code", + "execution_count": 10, + "metadata": {}, + "outputs": [ + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "c31816a040ee41af8b9071ef55c79000", + "version_major": 2, + "version_minor": 0 + }, + "text/html": [ + "

Failed to display Jupyter Widget of type FigureWidget.

\n", + "

\n", + " If you're reading this message in the Jupyter Notebook or JupyterLab Notebook, it may mean\n", + " that the widgets JavaScript is still loading. If this message persists, it\n", + " likely means that the widgets JavaScript library is either not installed or\n", + " not enabled. See the Jupyter\n", + " Widgets Documentation for setup instructions.\n", + "

\n", + "

\n", + " If you're reading this message in another frontend (for example, a static\n", + " rendering on GitHub or NBViewer),\n", + " it may mean that your frontend doesn't currently support widgets.\n", + "

\n" + ], + "text/plain": [ + "FigureWidget()" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "f.layout.dragmode = 'zoom'\n", + "f" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Image updates on change axis range" + ] + }, + { + "cell_type": "code", + "execution_count": 11, + "metadata": {}, + "outputs": [], + "source": [ + "f.layout.xaxis.range = [3.5, 9]" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Image updates on change figure dimensions" + ] + }, + { + "cell_type": "code", + "execution_count": 12, + "metadata": {}, + "outputs": [ + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "c31816a040ee41af8b9071ef55c79000", + "version_major": 2, + "version_minor": 0 + }, + "text/html": [ + "

Failed to display Jupyter Widget of type FigureWidget.

\n", + "

\n", + " If you're reading this message in the Jupyter Notebook or JupyterLab Notebook, it may mean\n", + " that the widgets JavaScript is still loading. If this message persists, it\n", + " likely means that the widgets JavaScript library is either not installed or\n", + " not enabled. See the Jupyter\n", + " Widgets Documentation for setup instructions.\n", + "

\n", + "

\n", + " If you're reading this message in another frontend (for example, a static\n", + " rendering on GitHub or NBViewer),\n", + " it may mean that your frontend doesn't currently support widgets.\n", + "

\n" + ], + "text/plain": [ + "FigureWidget()" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "f" + ] + }, + { + "cell_type": "code", + "execution_count": 20, + "metadata": {}, + "outputs": [], + "source": [ + "with f.batch_update():\n", + " f.layout.width = 1000\n", + " f.layout.height = 500 " + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python [default]", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.6.4" + } + }, + "nbformat": 4, + "nbformat_minor": 2 +} diff --git a/specs/ipyplotly_integration/Overview.ipynb b/specs/ipyplotly_integration/Overview.ipynb new file mode 100644 index 00000000000..155f0c8de21 --- /dev/null +++ b/specs/ipyplotly_integration/Overview.ipynb @@ -0,0 +1,909 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Overview\n", + "\n", + "This notebook introduces the ipyplotly enhancements to the plotly.py visualization library and demonstrates some of its features.\n", + "\n", + "\n", + "## New Features\n", + "\n", + " - Traces can be added and updated interactively by simply assigning to properties\n", + " - The full Traces and Layout API is generated from the plotly schema to provide a great experience for interactive use in the notebook\n", + " - Data validation covering the full API with clear, informative error messages\n", + " - Jupyter friendly docstrings on constructor params and properties\n", + " - Support for setting array properties as numpy arrays. When numpy arrays are used, ipywidgets binary serialization protocol is used to avoid converting these to JSON strings.\n", + " - Context manager API for animation\n", + " - Programmatic export of figures to static SVG images (and PNG and PDF with cairosvg installed)." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Imports" + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "metadata": {}, + "outputs": [], + "source": [ + "# ipyplotly\n", + "from plotly.graph_objs import FigureWidget\n", + "from plotly.callbacks import Points, InputState\n", + "\n", + "# pandas\n", + "import pandas as pd\n", + "\n", + "# numpy\n", + "import numpy as np\n", + "\n", + "# scikit learn\n", + "from sklearn import datasets\n", + "\n", + "# ipywidgets\n", + "from ipywidgets import HBox, VBox, Button\n", + "\n", + "# functools\n", + "from functools import partial" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + "
\n", + "\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
sepal_lengthsepal_widthpetal_lengthpetal_width
05.13.51.40.2
14.93.01.40.2
24.73.21.30.2
34.63.11.50.2
45.03.61.40.2
\n", + "
" + ], + "text/plain": [ + " sepal_length sepal_width petal_length petal_width\n", + "0 5.1 3.5 1.4 0.2\n", + "1 4.9 3.0 1.4 0.2\n", + "2 4.7 3.2 1.3 0.2\n", + "3 4.6 3.1 1.5 0.2\n", + "4 5.0 3.6 1.4 0.2" + ] + }, + "execution_count": 2, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# Load iris dataset\n", + "iris_data = datasets.load_iris()\n", + "feature_names = [name.replace(' (cm)', '').replace(' ', '_') for name in iris_data.feature_names]\n", + "iris_df = pd.DataFrame(iris_data.data, columns=feature_names)\n", + "iris_class = iris_data.target + 1\n", + "iris_df.head()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Create and display an empty FigureWidget\n", + "A FigureWidget behaves almost identically to a Figure but it is also an ipywidget that can be displayed directly in the notebook without calling `iplot`" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "metadata": {}, + "outputs": [ + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "1d5079ee9c1542cfa4ecc1f8e93abd1f", + "version_major": 2, + "version_minor": 0 + }, + "text/html": [ + "

Failed to display Jupyter Widget of type FigureWidget.

\n", + "

\n", + " If you're reading this message in the Jupyter Notebook or JupyterLab Notebook, it may mean\n", + " that the widgets JavaScript is still loading. If this message persists, it\n", + " likely means that the widgets JavaScript library is either not installed or\n", + " not enabled. See the Jupyter\n", + " Widgets Documentation for setup instructions.\n", + "

\n", + "

\n", + " If you're reading this message in another frontend (for example, a static\n", + " rendering on GitHub or NBViewer),\n", + " it may mean that your frontend doesn't currently support widgets.\n", + "

\n" + ], + "text/plain": [ + "FigureWidget()" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "f1 = FigureWidget()\n", + "f1" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Tab completion \n", + "Entering ``f1.add_`` displays add methods for all of the supported trace types" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# f1.add_" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Entering ``f1.add_scatter()`` displays the names of all of the top-level properties for the scatter trace type\n", + "\n", + "Entering ``f1.add_scatter()`` displays the signature pop-up. Expanding this pop-up reveals the method doc string which contains the descriptions of all of the top level properties" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# f1.add_scatter(" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Add scatter trace" + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "metadata": {}, + "outputs": [], + "source": [ + "scatt1 = f1.add_scatter(x=iris_df.sepal_length, y=iris_df.petal_width)" + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "metadata": {}, + "outputs": [ + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "1d5079ee9c1542cfa4ecc1f8e93abd1f", + "version_major": 2, + "version_minor": 0 + }, + "text/html": [ + "

Failed to display Jupyter Widget of type FigureWidget.

\n", + "

\n", + " If you're reading this message in the Jupyter Notebook or JupyterLab Notebook, it may mean\n", + " that the widgets JavaScript is still loading. If this message persists, it\n", + " likely means that the widgets JavaScript library is either not installed or\n", + " not enabled. See the Jupyter\n", + " Widgets Documentation for setup instructions.\n", + "

\n", + "

\n", + " If you're reading this message in another frontend (for example, a static\n", + " rendering on GitHub or NBViewer),\n", + " it may mean that your frontend doesn't currently support widgets.\n", + "

\n" + ], + "text/plain": [ + "FigureWidget()" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "f1" + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "metadata": {}, + "outputs": [], + "source": [ + "scatt1.mode?" + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "metadata": {}, + "outputs": [], + "source": [ + "# That's not what we wanted, change the mode to 'markers'\n", + "scatt1.mode = 'markers'" + ] + }, + { + "cell_type": "code", + "execution_count": 9, + "metadata": {}, + "outputs": [], + "source": [ + "# Set size to 8\n", + "scatt1.marker.size = 8" + ] + }, + { + "cell_type": "code", + "execution_count": 10, + "metadata": {}, + "outputs": [], + "source": [ + "# Color markers by iris class\n", + "scatt1.marker.color = iris_class" + ] + }, + { + "cell_type": "code", + "execution_count": 11, + "metadata": {}, + "outputs": [], + "source": [ + "# Change colorscale\n", + "scatt1.marker.cmin = 0.5\n", + "scatt1.marker.cmax = 3.5\n", + "scatt1.marker.colorscale = [[0, 'red'], [0.33, 'red'], \n", + " [0.33, 'green'], [0.67, 'green'], \n", + " [0.67, 'blue'], [1.0, 'blue']]\n", + "\n", + "scatt1.marker.showscale = True" + ] + }, + { + "cell_type": "code", + "execution_count": 12, + "metadata": {}, + "outputs": [], + "source": [ + "# Fix up colorscale ticks\n", + "scatt1.marker.colorbar.ticks = 'outside'\n", + "scatt1.marker.colorbar.tickvals = [1, 2, 3]\n", + "scatt1.marker.colorbar.ticktext = iris_data.target_names.tolist()" + ] + }, + { + "cell_type": "code", + "execution_count": 13, + "metadata": {}, + "outputs": [], + "source": [ + "# Set colorscale title\n", + "scatt1.marker.colorbar.title = 'Species'\n", + "scatt1.marker.colorbar.titlefont.size = 16\n", + "scatt1.marker.colorbar.titlefont.family = 'Rockwell'" + ] + }, + { + "cell_type": "code", + "execution_count": 14, + "metadata": {}, + "outputs": [], + "source": [ + "# Add axis labels\n", + "f1.layout.xaxis.title = 'sepal_length'\n", + "f1.layout.yaxis.title = 'petal_width'" + ] + }, + { + "cell_type": "code", + "execution_count": 15, + "metadata": {}, + "outputs": [ + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "1d5079ee9c1542cfa4ecc1f8e93abd1f", + "version_major": 2, + "version_minor": 0 + }, + "text/html": [ + "

Failed to display Jupyter Widget of type FigureWidget.

\n", + "

\n", + " If you're reading this message in the Jupyter Notebook or JupyterLab Notebook, it may mean\n", + " that the widgets JavaScript is still loading. If this message persists, it\n", + " likely means that the widgets JavaScript library is either not installed or\n", + " not enabled. See the Jupyter\n", + " Widgets Documentation for setup instructions.\n", + "

\n", + "

\n", + " If you're reading this message in another frontend (for example, a static\n", + " rendering on GitHub or NBViewer),\n", + " it may mean that your frontend doesn't currently support widgets.\n", + "

\n" + ], + "text/plain": [ + "FigureWidget()" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "f1" + ] + }, + { + "cell_type": "code", + "execution_count": 16, + "metadata": {}, + "outputs": [], + "source": [ + "# Hover info\n", + "scatt1.text = iris_data.target_names[iris_data.target]\n", + "scatt1.hoverinfo = 'text+x+y'\n", + "f1.layout.hovermode = 'closest'" + ] + }, + { + "cell_type": "code", + "execution_count": 17, + "metadata": {}, + "outputs": [ + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "1d5079ee9c1542cfa4ecc1f8e93abd1f", + "version_major": 2, + "version_minor": 0 + }, + "text/html": [ + "

Failed to display Jupyter Widget of type FigureWidget.

\n", + "

\n", + " If you're reading this message in the Jupyter Notebook or JupyterLab Notebook, it may mean\n", + " that the widgets JavaScript is still loading. If this message persists, it\n", + " likely means that the widgets JavaScript library is either not installed or\n", + " not enabled. See the Jupyter\n", + " Widgets Documentation for setup instructions.\n", + "

\n", + "

\n", + " If you're reading this message in another frontend (for example, a static\n", + " rendering on GitHub or NBViewer),\n", + " it may mean that your frontend doesn't currently support widgets.\n", + "

\n" + ], + "text/plain": [ + "FigureWidget()" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "f1" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Animate marker size change" + ] + }, + { + "cell_type": "code", + "execution_count": 18, + "metadata": {}, + "outputs": [], + "source": [ + "# Set marker size based on petal_length\n", + "with f1.batch_animate(duration=1000):\n", + " scatt1.marker.size = np.sqrt(iris_df.petal_length.values * 50)\n", + " " + ] + }, + { + "cell_type": "code", + "execution_count": 20, + "metadata": {}, + "outputs": [], + "source": [ + "# Restore constant marker size\n", + "with f1.batch_animate(duration=1000):\n", + " scatt1.marker.size = 8" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Set drag mode property callback\n", + "Make points more transparent when `dragmode` is `zoom`" + ] + }, + { + "cell_type": "code", + "execution_count": 23, + "metadata": {}, + "outputs": [], + "source": [ + "def set_opacity(marker, layout, dragmode):\n", + " if dragmode == 'zoom':\n", + " marker.opacity = 0.5\n", + " else:\n", + " marker.opacity = 1.0" + ] + }, + { + "cell_type": "code", + "execution_count": 24, + "metadata": {}, + "outputs": [], + "source": [ + "f1.layout.on_change(partial(set_opacity, scatt1.marker), 'dragmode')" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Configure colorscale for brushing" + ] + }, + { + "cell_type": "code", + "execution_count": 25, + "metadata": {}, + "outputs": [], + "source": [ + "scatt1.marker.colorbar = None\n", + "scatt1.marker.colorscale = [[0, 'lightgray'], [0.5, 'lightgray'], [0.5, 'red'], [1, 'red']]\n", + "scatt1.marker.cmin = -0.5\n", + "scatt1.marker.cmax = 1.5\n", + "scatt1.marker.colorbar.ticks = 'outside'\n", + "scatt1.marker.colorbar.tickvals = [0, 1]\n", + "scatt1.marker.colorbar.ticktext = ['unselected', 'selected']" + ] + }, + { + "cell_type": "code", + "execution_count": 26, + "metadata": {}, + "outputs": [], + "source": [ + "# Reset colors to zeros (unselected)\n", + "scatt1.marker.color = np.zeros(iris_class.size)\n", + "selected = np.zeros(iris_class.size)" + ] + }, + { + "cell_type": "code", + "execution_count": 27, + "metadata": {}, + "outputs": [ + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "1d5079ee9c1542cfa4ecc1f8e93abd1f", + "version_major": 2, + "version_minor": 0 + }, + "text/html": [ + "

Failed to display Jupyter Widget of type FigureWidget.

\n", + "

\n", + " If you're reading this message in the Jupyter Notebook or JupyterLab Notebook, it may mean\n", + " that the widgets JavaScript is still loading. If this message persists, it\n", + " likely means that the widgets JavaScript library is either not installed or\n", + " not enabled. See the Jupyter\n", + " Widgets Documentation for setup instructions.\n", + "

\n", + "

\n", + " If you're reading this message in another frontend (for example, a static\n", + " rendering on GitHub or NBViewer),\n", + " it may mean that your frontend doesn't currently support widgets.\n", + "

\n" + ], + "text/plain": [ + "FigureWidget()" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "f1" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Configure brushing callback" + ] + }, + { + "cell_type": "code", + "execution_count": 29, + "metadata": {}, + "outputs": [], + "source": [ + "# Assigning these variables here is not required. But doing so tricks Jupyter into \n", + "# providing property tab completion on the parameters to the brush function below\n", + "trace, points, state = scatt1, Points(), InputState()" + ] + }, + { + "cell_type": "code", + "execution_count": 30, + "metadata": {}, + "outputs": [], + "source": [ + "def brush(trace, points, state):\n", + " inds = np.array(points.point_inds)\n", + " if inds.size:\n", + " selected[inds] = 1\n", + " trace.marker.color = selected" + ] + }, + { + "cell_type": "code", + "execution_count": 31, + "metadata": {}, + "outputs": [], + "source": [ + "scatt1.on_selected(brush)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Now box or lasso select points on the figure and see them turn red" + ] + }, + { + "cell_type": "code", + "execution_count": 32, + "metadata": {}, + "outputs": [], + "source": [ + "# Reset brush\n", + "selected = np.zeros(iris_class.size)\n", + "scatt1.marker.color = selected" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Create second plot with different features" + ] + }, + { + "cell_type": "code", + "execution_count": 38, + "metadata": { + "scrolled": false + }, + "outputs": [ + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "e88d348677544c1ea2eca95ea8b30fdd", + "version_major": 2, + "version_minor": 0 + }, + "text/html": [ + "

Failed to display Jupyter Widget of type FigureWidget.

\n", + "

\n", + " If you're reading this message in the Jupyter Notebook or JupyterLab Notebook, it may mean\n", + " that the widgets JavaScript is still loading. If this message persists, it\n", + " likely means that the widgets JavaScript library is either not installed or\n", + " not enabled. See the Jupyter\n", + " Widgets Documentation for setup instructions.\n", + "

\n", + "

\n", + " If you're reading this message in another frontend (for example, a static\n", + " rendering on GitHub or NBViewer),\n", + " it may mean that your frontend doesn't currently support widgets.\n", + "

\n" + ], + "text/plain": [ + "FigureWidget()" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "f2 = FigureWidget(data=[{'type': 'scatter',\n", + " 'x': iris_df.petal_length, \n", + " 'y': iris_df.sepal_width,\n", + " 'mode': 'markers'}])\n", + "f2" + ] + }, + { + "cell_type": "code", + "execution_count": 39, + "metadata": {}, + "outputs": [], + "source": [ + "# Set axis titles\n", + "f2.layout.xaxis.title = 'petal_length'\n", + "f2.layout.yaxis.title = 'sepal_width'" + ] + }, + { + "cell_type": "code", + "execution_count": 40, + "metadata": {}, + "outputs": [], + "source": [ + "# Grab trace reference\n", + "scatt2 = f2.data[0]" + ] + }, + { + "cell_type": "code", + "execution_count": 41, + "metadata": { + "scrolled": false + }, + "outputs": [], + "source": [ + "# Set marker styles / colorbars to match between figures\n", + "scatt2.marker = scatt1.marker" + ] + }, + { + "cell_type": "code", + "execution_count": 42, + "metadata": {}, + "outputs": [], + "source": [ + "# Configure brush on both plots to update both plots\n", + "def brush(trace, points, state):\n", + " inds = np.array(points.point_inds)\n", + " if inds.size:\n", + " selected = scatt1.marker.color.copy()\n", + " selected[inds] = 1\n", + " scatt1.marker.color = selected\n", + " scatt2.marker.color = selected \n", + " \n", + "scatt1.on_selected(brush)\n", + "scatt2.on_selected(brush)" + ] + }, + { + "cell_type": "code", + "execution_count": 43, + "metadata": {}, + "outputs": [], + "source": [ + "f2.layout.on_change(partial(set_opacity, scatt2.marker), 'dragmode')" + ] + }, + { + "cell_type": "code", + "execution_count": 44, + "metadata": {}, + "outputs": [], + "source": [ + "# Reset brush\n", + "def reset_brush(btn):\n", + " selected = np.zeros(iris_class.size)\n", + " scatt1.marker.color = selected\n", + " scatt2.marker.color = selected" + ] + }, + { + "cell_type": "code", + "execution_count": 45, + "metadata": {}, + "outputs": [], + "source": [ + "# Create reset button\n", + "button = Button(description=\"clear\")\n", + "button.on_click(reset_brush)" + ] + }, + { + "cell_type": "code", + "execution_count": 46, + "metadata": {}, + "outputs": [], + "source": [ + "# Hide colorbar for figure 1\n", + "scatt1.marker.showscale = False" + ] + }, + { + "cell_type": "code", + "execution_count": 47, + "metadata": {}, + "outputs": [], + "source": [ + "# Set dragmode to lasso for both plots\n", + "f1.layout.dragmode = 'lasso'\n", + "f2.layout.dragmode = 'lasso'" + ] + }, + { + "cell_type": "code", + "execution_count": 50, + "metadata": {}, + "outputs": [], + "source": [ + "# Display two figures and the reset button\n", + "f1.layout.width = 500\n", + "f2.layout.width = 500" + ] + }, + { + "cell_type": "code", + "execution_count": 49, + "metadata": {}, + "outputs": [ + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "74f7b16952584919b650fbc442c21773", + "version_major": 2, + "version_minor": 0 + }, + "text/html": [ + "

Failed to display Jupyter Widget of type VBox.

\n", + "

\n", + " If you're reading this message in the Jupyter Notebook or JupyterLab Notebook, it may mean\n", + " that the widgets JavaScript is still loading. If this message persists, it\n", + " likely means that the widgets JavaScript library is either not installed or\n", + " not enabled. See the Jupyter\n", + " Widgets Documentation for setup instructions.\n", + "

\n", + "

\n", + " If you're reading this message in another frontend (for example, a static\n", + " rendering on GitHub or NBViewer),\n", + " it may mean that your frontend doesn't currently support widgets.\n", + "

\n" + ], + "text/plain": [ + "VBox(children=(HBox(children=(FigureWidget(), FigureWidget())), Button(description='clear', style=ButtonStyle())))" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "VBox([HBox([f1, f2]), button])" + ] + }, + { + "cell_type": "code", + "execution_count": 55, + "metadata": {}, + "outputs": [], + "source": [ + "# Save figure 2 to a svg image in the exports directory\n", + "f2.save_image('exports/f2.svg')" + ] + }, + { + "cell_type": "code", + "execution_count": 54, + "metadata": {}, + "outputs": [], + "source": [ + "# Save figure 1 to a pdf in the exports directory (requires cairosvg be installed)\n", + "# f1.save_image('exports/f1.pdf')" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python [default]", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.6.4" + } + }, + "nbformat": 4, + "nbformat_minor": 2 +} diff --git a/specs/ipyplotly_integration/Scatter GL Example.ipynb b/specs/ipyplotly_integration/Scatter GL Example.ipynb new file mode 100644 index 00000000000..6c580cf5449 --- /dev/null +++ b/specs/ipyplotly_integration/Scatter GL Example.ipynb @@ -0,0 +1,97 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## ScatterGL Example\n", + "Data is transfered to JS side using ipywidgets binary protocol without JSON serialization" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# plotly\n", + "from plotly.graph_objs import Figure, FigureWidget, Scattergl\n", + "\n", + "# numpy\n", + "import numpy as np\n", + "\n", + "# core\n", + "import datetime\n", + "import time" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "import plotly.offline as py\n", + "py.init_notebook_mode()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# Create a one-million points scattergl trace\n", + "N = 1000000\n", + "scatt = Scattergl(x = np.random.randn(N), \n", + " y = np.random.randn(N),\n", + " mode = 'markers',\n", + " marker={'opacity': 0.8, 'line': {'width': 1}})\n", + "\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# Creating and displaying takes ~4 seconds\n", + "fig = FigureWidget(data=[scatt])\n", + "f" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# Plotting using iplot takes ~25 seconds\n", + "fig = Figure(data=[scatt])\n", + "py.iplot(fig)" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python [default]", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.6.4" + } + }, + "nbformat": 4, + "nbformat_minor": 2 +} diff --git a/specs/ipyplotly_integration/exports/README.md b/specs/ipyplotly_integration/exports/README.md new file mode 100644 index 00000000000..4c2ab534249 --- /dev/null +++ b/specs/ipyplotly_integration/exports/README.md @@ -0,0 +1 @@ +This is a directory to save example images diff --git a/tox.ini b/tox.ini index 468f9b45801..43f1a7d910f 100644 --- a/tox.ini +++ b/tox.ini @@ -67,12 +67,6 @@ deps= optional: pyshp==1.2.10 ; CORE ENVIRONMENTS -[testenv:py27-core] -basepython={env:PLOTLY_TOX_PYTHON_27:} -commands= - python --version - nosetests {posargs} -x plotly/tests/test_core - [testenv:py33-core] basepython={env:PLOTLY_TOX_PYTHON_33:} commands= @@ -91,6 +85,12 @@ commands= python --version nosetests {posargs} -x plotly/tests/test_core +[testenv:py27-core] +basepython={env:PLOTLY_TOX_PYTHON_27:} +commands= + python --version + nosetests {posargs} -x plotly/tests/test_core + ; OPTIONAL ENVIRONMENTS [testenv:py27-optional] basepython={env:PLOTLY_TOX_PYTHON_27:} diff --git a/update_graph_objs.py b/update_graph_objs.py index 0414dd0c18e..0fd08820526 100644 --- a/update_graph_objs.py +++ b/update_graph_objs.py @@ -1,7 +1,7 @@ from __future__ import print_function from plotly.graph_objs import graph_objs_tools -from plotly.graph_reference import ARRAYS, CLASSES +from plotly.graph_reference import ARRAYS, CLASSES, TRACE_NAMES FLAG = '# AUTO-GENERATED BELOW. DO NOT EDIT! See makefile.' @@ -29,255 +29,24 @@ def get_non_generated_file_lines(): return lines_to_copy -def print_figure_patch(f): - """Print a patch to our Figure object into the given open file.""" - - print( - ''' - def __init__(self, *args, **kwargs): - super(Figure, self).__init__(*args, **kwargs) - if 'data' not in self: - self.data = Data(_parent=self, _parent_key='data') - - def get_data(self, flatten=False): - """ - Returns the JSON for the plot with non-data elements stripped. - - Flattening may increase the utility of the result. - - :param (bool) flatten: {'a': {'b': ''}} --> {'a.b': ''} - :returns: (dict|list) Depending on (flat|unflat) - - """ - return self.data.get_data(flatten=flatten) - - def to_dataframe(self): - """ - Create a dataframe with trace names and keys as column names. - - :return: (DataFrame) - - """ - data = self.get_data(flatten=True) - from pandas import DataFrame, Series - return DataFrame( - dict([(k, Series(v)) for k, v in data.items()])) - - def print_grid(self): - """ - Print a visual layout of the figure's axes arrangement. - - This is only valid for figures that are created - with plotly.tools.make_subplots. - - """ - try: - grid_str = self.__dict__['_grid_str'] - except AttributeError: - raise Exception("Use plotly.tools.make_subplots " - "to create a subplot grid.") - print(grid_str) - - def append_trace(self, trace, row, col): - """ - Add a trace to your figure bound to axes at the row, col index. - - The row, col index is generated from figures created with - plotly.tools.make_subplots and can be viewed with - Figure.print_grid. - - :param (dict) trace: The data trace to be bound. - :param (int) row: Subplot row index (see Figure.print_grid). - :param (int) col: Subplot column index (see Figure.print_grid). - - Example: - # stack two subplots vertically - fig = tools.make_subplots(rows=2) - - This is the format of your plot grid: - [ (1,1) x1,y1 ] - [ (2,1) x2,y2 ] - - fig.append_trace(Scatter(x=[1,2,3], y=[2,1,2]), 1, 1) - fig.append_trace(Scatter(x=[1,2,3], y=[2,1,2]), 2, 1) - - """ - try: - grid_ref = self._grid_ref - except AttributeError: - raise Exception("In order to use Figure.append_trace, " - "you must first use " - "plotly.tools.make_subplots " - "to create a subplot grid.") - if row <= 0: - raise Exception("Row value is out of range. " - "Note: the starting cell is (1, 1)") - if col <= 0: - raise Exception("Col value is out of range. " - "Note: the starting cell is (1, 1)") - try: - ref = grid_ref[row-1][col-1] - except IndexError: - raise Exception("The (row, col) pair sent is out of " - "range. Use Figure.print_grid to view the " - "subplot grid. ") - if 'scene' in ref[0]: - trace['scene'] = ref[0] - if ref[0] not in self['layout']: - raise Exception("Something went wrong. " - "The scene object for ({r},{c}) " - "subplot cell " - "got deleted.".format(r=row, c=col)) - else: - xaxis_key = "xaxis{ref}".format(ref=ref[0][1:]) - yaxis_key = "yaxis{ref}".format(ref=ref[1][1:]) - if (xaxis_key not in self['layout'] - or yaxis_key not in self['layout']): - raise Exception("Something went wrong. " - "An axis object for ({r},{c}) subplot " - "cell got deleted." - .format(r=row, c=col)) - trace['xaxis'] = ref[0] - trace['yaxis'] = ref[1] - self['data'] += [trace] -''', file=f, end='' - ) - - -def print_data_patch(f): - """Print a patch to our Data object into the given open file.""" - print( - ''' - def _value_to_graph_object(self, index, value, _raise=True): - - if not isinstance(value, dict): - if _raise: - notes = ['Entry should subclass dict.'] - path = self._get_path() + (index, ) - raise exceptions.PlotlyListEntryError(self, path, - notes=notes) - else: - return - - item = value.get('type', 'scatter') - if item not in graph_reference.ARRAYS['data']['items']: - if _raise: - path = self._get_path() + (0, ) - raise exceptions.PlotlyDataTypeError(self, path) - - return GraphObjectFactory.create(item, _raise=_raise, - _parent=self, - _parent_key=index, **value) - - def get_data(self, flatten=False): - """ - Returns the JSON for the plot with non-data elements stripped. - - :param (bool) flatten: {'a': {'b': ''}} --> {'a.b': ''} - :returns: (dict|list) Depending on (flat|unflat) - - """ - if flatten: - data = [v.get_data(flatten=flatten) for v in self] - d = {} - taken_names = [] - for i, trace in enumerate(data): - - # we want to give the traces helpful names - # however, we need to be sure they're unique too... - trace_name = trace.pop('name', 'trace_{0}'.format(i)) - if trace_name in taken_names: - j = 1 - new_trace_name = "{0}_{1}".format(trace_name, j) - while new_trace_name in taken_names: - new_trace_name = ( - "{0}_{1}".format(trace_name, j) - ) - j += 1 - trace_name = new_trace_name - taken_names.append(trace_name) - - # finish up the dot-concatenation - for k, v in trace.items(): - key = "{0}.{1}".format(trace_name, k) - d[key] = v - return d - else: - return super(Data, self).get_data(flatten=flatten) -''', file=f, end='' - ) - - -def print_frames_patch(f): - """Print a patch to our Frames object into the given open file.""" - print( - ''' - def _value_to_graph_object(self, index, value, _raise=True): - if isinstance(value, six.string_types): - return value - return super(Frames, self)._value_to_graph_object(index, value, - _raise=_raise) - - def to_string(self, level=0, indent=4, eol='\\n', - pretty=True, max_chars=80): - """Get formatted string by calling `to_string` on children items.""" - if not len(self): - return "{name}()".format(name=self._get_class_name()) - string = "{name}([{eol}{indent}".format( - name=self._get_class_name(), - eol=eol, - indent=' ' * indent * (level + 1)) - for index, entry in enumerate(self): - if isinstance(entry, six.string_types): - string += repr(entry) - else: - string += entry.to_string(level=level+1, - indent=indent, - eol=eol, - pretty=pretty, - max_chars=max_chars) - if index < len(self) - 1: - string += ",{eol}{indent}".format( - eol=eol, - indent=' ' * indent * (level + 1)) - string += ( - "{eol}{indent}])").format(eol=eol, indent=' ' * indent * level) - return string -''', file=f, end='' - ) - - def print_class(name, f): - class_dict = CLASSES[name] - print('\n', file=f) - object_name = class_dict['object_name'] - base_type = class_dict['base_type'] - - # This is for backwards compat (e.g., Trace) and future changes. - if object_name is None: - print('class {}({}):'.format(name, base_type.__name__), - file=f) - print(' pass', file=f) - return - - doc = graph_objs_tools.get_help(object_name) - if object_name in ARRAYS: - base_name = 'PlotlyList' - else: - base_name = 'PlotlyDict' - print('class {}({}):'.format(name, base_name), file=f) - doc_lines = doc.splitlines() - print(' """', file=f) - for doc_line in doc_lines: - print(' ' + doc_line, file=f) - print('\n """', file=f) - print(" _name = '{}'".format(object_name), file=f) if name == 'Figure': - print_figure_patch(f) - elif name == 'Data': - print_data_patch(f) - elif name == 'Frames': - print_frames_patch(f) + print('from plotly.datatypes import Figure', file=f, end='\n\n\n') + elif name == 'Layout': + print('from plotly.datatypes import Layout', file=f, end='\n\n\n') + else: + class_dict = CLASSES[name] + object_name = class_dict['object_name'] + + if object_name in TRACE_NAMES: + print('from plotly.datatypes.trace import {}'.format(name), file=f, end='\n\n\n') + elif object_name in ARRAYS: + print('class {}(list):'.format(name), file=f, end='\n') + print(' pass', file=f, end='\n\n\n') + else: + print('class {}(dict):'.format(name), file=f, end='\n') + print(' pass', file=f, end='\n\n\n') + copied_lines = get_non_generated_file_lines() with open('./plotly/graph_objs/graph_objs.py', 'w') as graph_objs_file: @@ -294,5 +63,5 @@ def print_class(name, f): print_class(class_name, graph_objs_file) # Finish off the file by only exporting plot-schema names. - print('\n__all__ = [cls for cls in graph_reference.CLASSES.keys() ' - 'if cls in globals()]', file=graph_objs_file) + print('__all__ = [cls for cls in graph_reference.CLASSES.keys() ' + 'if cls in globals()] + ["FigureWidget"]', file=graph_objs_file)