This commit is contained in:
2025-09-07 22:09:54 +02:00
parent e1b817252c
commit 2fc0d000b6
7796 changed files with 2159515 additions and 933 deletions

View File

@ -0,0 +1,194 @@
"""
https://plot.ly/python/
Plotly's Python API allows users to programmatically access Plotly's
server resources.
This package is organized as follows:
Subpackages:
- plotly: all functionality that requires access to Plotly's servers
- graph_objs: objects for designing figures and visualizing data
- matplotlylib: tools to convert matplotlib figures
Modules:
- tools: some helpful tools that do not require access to Plotly's servers
- utils: functions that you probably won't need, but that subpackages use
- version: holds the current API version
- exceptions: defines our custom exception classes
"""
from typing import TYPE_CHECKING
from _plotly_utils.importers import relative_import
import importlib.metadata
# This is the version of the plotly package
__version__ = importlib.metadata.version("plotly")
version = __version__
if TYPE_CHECKING:
from plotly import (
graph_objs,
tools,
utils,
offline,
colors,
io,
data,
)
from plotly.version import __version__
__all__ = [
"graph_objs",
"tools",
"utils",
"offline",
"colors",
"io",
"data",
"__version__",
]
# Set default template (for >= 3.7 this is done in ploty/io/__init__.py)
from plotly.io import templates
templates._default = "plotly"
else:
__all__, __getattr__, __dir__ = relative_import(
__name__,
[
".graph_objs",
".graph_objects",
".tools",
".utils",
".offline",
".colors",
".io",
".data",
],
[".version.__version__"],
)
def plot(data_frame, kind, **kwargs):
"""
Pandas plotting backend function, not meant to be called directly.
To activate, set pandas.options.plotting.backend="plotly"
See https://github.com/pandas-dev/pandas/blob/master/pandas/plotting/__init__.py
"""
from .express import (
scatter,
line,
area,
bar,
box,
histogram,
violin,
strip,
funnel,
density_contour,
density_heatmap,
imshow,
)
if kind == "scatter":
new_kwargs = {k: kwargs[k] for k in kwargs if k not in ["s", "c"]}
return scatter(data_frame, **new_kwargs)
if kind == "line":
return line(data_frame, **kwargs)
if kind == "area":
new_kwargs = {k: kwargs[k] for k in kwargs if k not in ["stacked"]}
return area(data_frame, **new_kwargs)
if kind == "bar":
return bar(data_frame, **kwargs)
if kind == "barh":
return bar(data_frame, orientation="h", **kwargs)
if kind == "box":
new_kwargs = {k: kwargs[k] for k in kwargs if k not in ["by"]}
return box(data_frame, **new_kwargs)
if kind in ["hist", "histogram"]:
new_kwargs = {k: kwargs[k] for k in kwargs if k not in ["by", "bins"]}
return histogram(data_frame, **new_kwargs)
if kind == "violin":
return violin(data_frame, **kwargs)
if kind == "strip":
return strip(data_frame, **kwargs)
if kind == "funnel":
return funnel(data_frame, **kwargs)
if kind == "density_contour":
return density_contour(data_frame, **kwargs)
if kind == "density_heatmap":
return density_heatmap(data_frame, **kwargs)
if kind == "imshow":
return imshow(data_frame, **kwargs)
if kind == "heatmap":
raise ValueError(
"kind='heatmap' not supported plotting.backend='plotly'. "
"Please use kind='imshow' or kind='density_heatmap'."
)
raise NotImplementedError(
"kind='%s' not yet supported for plotting.backend='plotly'" % kind
)
def boxplot_frame(data_frame, **kwargs):
"""
Pandas plotting backend function, not meant to be called directly.
To activate, set pandas.options.plotting.backend="plotly"
See https://github.com/pandas-dev/pandas/blob/master/pandas/plotting/__init__.py
"""
from .express import box
skip = ["by", "column", "ax", "fontsize", "rot", "grid", "figsize", "layout"]
skip += ["return_type"]
new_kwargs = {k: kwargs[k] for k in kwargs if k not in skip}
return box(data_frame, **new_kwargs)
def hist_frame(data_frame, **kwargs):
"""
Pandas plotting backend function, not meant to be called directly.
To activate, set pandas.options.plotting.backend="plotly"
See https://github.com/pandas-dev/pandas/blob/master/pandas/plotting/__init__.py
"""
from .express import histogram
skip = ["column", "by", "grid", "xlabelsize", "xrot", "ylabelsize", "yrot"]
skip += ["ax", "sharex", "sharey", "figsize", "layout", "bins", "legend"]
new_kwargs = {k: kwargs[k] for k in kwargs if k not in skip}
return histogram(data_frame, **new_kwargs)
def hist_series(data_frame, **kwargs):
"""
Pandas plotting backend function, not meant to be called directly.
To activate, set pandas.options.plotting.backend="plotly"
See https://github.com/pandas-dev/pandas/blob/master/pandas/plotting/__init__.py
"""
from .express import histogram
skip = ["by", "grid", "xlabelsize", "xrot", "ylabelsize", "yrot", "ax"]
skip += ["figsize", "bins", "legend"]
new_kwargs = {k: kwargs[k] for k in kwargs if k not in skip}
return histogram(data_frame, **new_kwargs)
def _jupyter_labextension_paths():
"""Called by Jupyter Lab Server to detect if it is a valid labextension and
to install the extension.
"""
return [
{
"src": "labextension/static",
"dest": "jupyterlab-plotly",
}
]

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,54 @@
from _plotly_utils.basevalidators import EnumeratedValidator, NumberValidator
class EasingValidator(EnumeratedValidator):
def __init__(self, plotly_name="easing", parent_name="batch_animate", **_):
super(EasingValidator, self).__init__(
plotly_name=plotly_name,
parent_name=parent_name,
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(DurationValidator, self).__init__(
plotly_name=plotly_name, parent_name="batch_animate", min=0
)

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,989 @@
from copy import deepcopy
import pathlib
from traitlets import List, Dict, observe, Integer
from plotly.io._renderers import display_jupyter_version_warnings
from .basedatatypes import BaseFigure, BasePlotlyType
from .callbacks import BoxSelector, LassoSelector, InputDeviceState, Points
from .serializers import custom_serializers
import anywidget
class BaseFigureWidget(BaseFigure, anywidget.AnyWidget):
"""
Base class for FigureWidget. The FigureWidget class is code-generated as a
subclass
"""
_esm = pathlib.Path(__file__).parent / "package_data" / "widgetbundle.js"
# ### _data and _layout ###
# These properties store the current state of the traces and
# layout as JSON-style dicts. These dicts do not store any subclasses of
# `BasePlotlyType`
#
# Note: These are only automatically synced with the frontend on full
# assignment, not on mutation. We use this fact to only directly sync
# them to the front-end on FigureWidget construction. All other updates
# are made using mutation, and they are manually synced to the frontend
# using the relayout/restyle/update/etc. messages.
_widget_layout = Dict().tag(sync=True, **custom_serializers)
_widget_data = List().tag(sync=True, **custom_serializers)
_config = Dict().tag(sync=True, **custom_serializers)
# ### Python -> JS message properties ###
# These properties are used to send messages from Python to the
# frontend. Messages are sent by assigning the message contents to the
# appropriate _py2js_* property and then immediatly assigning None to the
# property.
#
# See JSDoc comments in the FigureModel class in js/src/Figure.js for
# detailed descriptions of the messages.
_py2js_addTraces = Dict(allow_none=True).tag(sync=True, **custom_serializers)
_py2js_restyle = Dict(allow_none=True).tag(sync=True, **custom_serializers)
_py2js_relayout = Dict(allow_none=True).tag(sync=True, **custom_serializers)
_py2js_update = Dict(allow_none=True).tag(sync=True, **custom_serializers)
_py2js_animate = Dict(allow_none=True).tag(sync=True, **custom_serializers)
_py2js_deleteTraces = Dict(allow_none=True).tag(sync=True, **custom_serializers)
_py2js_moveTraces = Dict(allow_none=True).tag(sync=True, **custom_serializers)
_py2js_removeLayoutProps = Dict(allow_none=True).tag(
sync=True, **custom_serializers
)
_py2js_removeTraceProps = Dict(allow_none=True).tag(sync=True, **custom_serializers)
# ### JS -> Python message properties ###
# These properties are used to receive messages from the frontend.
# Messages are received by defining methods that observe changes to these
# properties. Receive methods are named `_handler_js2py_*` where '*' is
# the name of the corresponding message property. Receive methods are
# responsible for setting the message property to None after retreiving
# the message data.
#
# See JSDoc comments in the FigureModel class in js/src/Figure.js for
# detailed descriptions of the messages.
_js2py_traceDeltas = Dict(allow_none=True).tag(sync=True, **custom_serializers)
_js2py_layoutDelta = Dict(allow_none=True).tag(sync=True, **custom_serializers)
_js2py_restyle = Dict(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)
_js2py_pointsCallback = Dict(allow_none=True).tag(sync=True, **custom_serializers)
# ### Message tracking properties ###
# The _last_layout_edit_id and _last_trace_edit_id properties are used
# to keep track of the edit id of the message that most recently
# requested an update to the Figures layout or traces respectively.
#
# We track this information because we don't want to update the Figure's
# default layout/trace properties (_layout_defaults, _data_defaults)
# while edits are in process. This can lead to inconsistent property
# states.
_last_layout_edit_id = Integer(0).tag(sync=True)
_last_trace_edit_id = Integer(0).tag(sync=True)
_set_trace_uid = True
_allow_disable_validation = False
# Constructor
# -----------
def __init__(
self, data=None, layout=None, frames=None, skip_invalid=False, **kwargs
):
# Call superclass constructors
# ----------------------------
# Note: We rename layout to layout_plotly because to deconflict it
# with the `layout` constructor parameter of the `widgets.DOMWidget`
# ipywidgets class
super(BaseFigureWidget, self).__init__(
data=data,
layout_plotly=layout,
frames=frames,
skip_invalid=skip_invalid,
**kwargs,
)
# Validate Frames
# ---------------
# Frames are not supported by figure widget
if self._frame_objs:
BaseFigureWidget._display_frames_error()
# Message States
# --------------
# ### Layout ###
# _last_layout_edit_id is described above
self._last_layout_edit_id = 0
# _layout_edit_in_process is set to True if there are layout edit
# operations that have been sent to the frontend that haven't
# completed yet.
self._layout_edit_in_process = False
# _waiting_edit_callbacks is a list of callback functions that
# should be executed as soon as all pending edit operations are
# completed
self._waiting_edit_callbacks = []
# ### Trace ###
# _last_trace_edit_id: described above
self._last_trace_edit_id = 0
# _trace_edit_in_process is set to True if there are trace edit
# operations that have been sent to the frontend that haven't
# completed yet.
self._trace_edit_in_process = False
# View count
# ----------
# ipywidget property that stores the number of active frontend
# views of this widget
self._view_count = 0
# Initialize widget layout and data for third-party widget integration
# --------------------------------------------------------------------
self._widget_layout = deepcopy(self._layout_obj._props)
self._widget_data = deepcopy(self._data)
def show(self, *args, **kwargs):
return self
# Python -> JavaScript Messages
# -----------------------------
def _send_relayout_msg(self, layout_data, source_view_id=None):
"""
Send Plotly.relayout message to the frontend
Parameters
----------
layout_data : dict
Plotly.relayout layout data
source_view_id : str
UID of view that triggered this relayout operation
(e.g. By the user clicking 'zoom' in the toolbar). None if the
operation was not triggered by a frontend view
"""
# Increment layout edit messages IDs
# ----------------------------------
layout_edit_id = self._last_layout_edit_id + 1
self._last_layout_edit_id = layout_edit_id
self._layout_edit_in_process = True
# Build message
# -------------
msg_data = {
"relayout_data": layout_data,
"layout_edit_id": layout_edit_id,
"source_view_id": source_view_id,
}
# Send message
# ------------
self._py2js_relayout = msg_data
self._py2js_relayout = None
def _send_restyle_msg(self, restyle_data, trace_indexes=None, source_view_id=None):
"""
Send Plotly.restyle message to the frontend
Parameters
----------
restyle_data : dict
Plotly.restyle restyle data
trace_indexes : list[int]
List of trace indexes that the restyle operation
applies to
source_view_id : str
UID of view that triggered this restyle operation
(e.g. By the user clicking the legend to hide a trace).
None if the operation was not triggered by a frontend view
"""
# Validate / normalize inputs
# ---------------------------
trace_indexes = self._normalize_trace_indexes(trace_indexes)
# Increment layout/trace edit message IDs
# ---------------------------------------
layout_edit_id = self._last_layout_edit_id + 1
self._last_layout_edit_id = layout_edit_id
self._layout_edit_in_process = True
trace_edit_id = self._last_trace_edit_id + 1
self._last_trace_edit_id = trace_edit_id
self._trace_edit_in_process = True
# Build message
# -------------
restyle_msg = {
"restyle_data": restyle_data,
"restyle_traces": trace_indexes,
"trace_edit_id": trace_edit_id,
"layout_edit_id": layout_edit_id,
"source_view_id": source_view_id,
}
# Send message
# ------------
self._py2js_restyle = restyle_msg
self._py2js_restyle = None
def _send_addTraces_msg(self, new_traces_data):
"""
Send Plotly.addTraces message to the frontend
Parameters
----------
new_traces_data : list[dict]
List of trace data for new traces as accepted by Plotly.addTraces
"""
# Increment layout/trace edit message IDs
# ---------------------------------------
layout_edit_id = self._last_layout_edit_id + 1
self._last_layout_edit_id = layout_edit_id
self._layout_edit_in_process = True
trace_edit_id = self._last_trace_edit_id + 1
self._last_trace_edit_id = trace_edit_id
self._trace_edit_in_process = True
# Build message
# -------------
add_traces_msg = {
"trace_data": new_traces_data,
"trace_edit_id": trace_edit_id,
"layout_edit_id": layout_edit_id,
}
# Send message
# ------------
self._py2js_addTraces = add_traces_msg
self._py2js_addTraces = None
def _send_moveTraces_msg(self, current_inds, new_inds):
"""
Send Plotly.moveTraces message to the frontend
Parameters
----------
current_inds : list[int]
List of current trace indexes
new_inds : list[int]
List of new trace indexes
"""
# Build message
# -------------
move_msg = {"current_trace_inds": current_inds, "new_trace_inds": new_inds}
# Send message
# ------------
self._py2js_moveTraces = move_msg
self._py2js_moveTraces = None
def _send_update_msg(
self, restyle_data, relayout_data, trace_indexes=None, source_view_id=None
):
"""
Send Plotly.update message to the frontend
Parameters
----------
restyle_data : dict
Plotly.update restyle data
relayout_data : dict
Plotly.update relayout data
trace_indexes : list[int]
List of trace indexes that the update operation applies to
source_view_id : str
UID of view that triggered this update operation
(e.g. By the user clicking a button).
None if the operation was not triggered by a frontend view
"""
# Validate / normalize inputs
# ---------------------------
trace_indexes = self._normalize_trace_indexes(trace_indexes)
# Increment layout/trace edit message IDs
# ---------------------------------------
trace_edit_id = self._last_trace_edit_id + 1
self._last_trace_edit_id = trace_edit_id
self._trace_edit_in_process = True
layout_edit_id = self._last_layout_edit_id + 1
self._last_layout_edit_id = layout_edit_id
self._layout_edit_in_process = True
# Build message
# -------------
update_msg = {
"style_data": restyle_data,
"layout_data": relayout_data,
"style_traces": trace_indexes,
"trace_edit_id": trace_edit_id,
"layout_edit_id": layout_edit_id,
"source_view_id": source_view_id,
}
# Send message
# ------------
self._py2js_update = update_msg
self._py2js_update = None
def _send_animate_msg(
self, styles_data, relayout_data, trace_indexes, animation_opts
):
"""
Send Plotly.update message to the frontend
Note: there is no source_view_id parameter because animations
triggered by the fontend are not currently supported
Parameters
----------
styles_data : list[dict]
Plotly.animate styles data
relayout_data : dict
Plotly.animate relayout data
trace_indexes : list[int]
List of trace indexes that the animate operation applies to
"""
# Validate / normalize inputs
# ---------------------------
trace_indexes = self._normalize_trace_indexes(trace_indexes)
# Increment layout/trace edit message IDs
# ---------------------------------------
trace_edit_id = self._last_trace_edit_id + 1
self._last_trace_edit_id = trace_edit_id
self._trace_edit_in_process = True
layout_edit_id = self._last_layout_edit_id + 1
self._last_layout_edit_id = layout_edit_id
self._layout_edit_in_process = True
# Build message
# -------------
animate_msg = {
"style_data": styles_data,
"layout_data": relayout_data,
"style_traces": trace_indexes,
"animation_opts": animation_opts,
"trace_edit_id": trace_edit_id,
"layout_edit_id": layout_edit_id,
"source_view_id": None,
}
# Send message
# ------------
self._py2js_animate = animate_msg
self._py2js_animate = None
def _send_deleteTraces_msg(self, delete_inds):
"""
Send Plotly.deleteTraces message to the frontend
Parameters
----------
delete_inds : list[int]
List of trace indexes of traces to delete
"""
# Increment layout/trace edit message IDs
# ---------------------------------------
trace_edit_id = self._last_trace_edit_id + 1
self._last_trace_edit_id = trace_edit_id
self._trace_edit_in_process = True
layout_edit_id = self._last_layout_edit_id + 1
self._last_layout_edit_id = layout_edit_id
self._layout_edit_in_process = True
# Build message
# -------------
delete_msg = {
"delete_inds": delete_inds,
"layout_edit_id": layout_edit_id,
"trace_edit_id": trace_edit_id,
}
# Send message
# ------------
self._py2js_deleteTraces = delete_msg
self._py2js_deleteTraces = None
# JavaScript -> Python Messages
# -----------------------------
@observe("_js2py_traceDeltas")
def _handler_js2py_traceDeltas(self, change):
"""
Process trace deltas message from the frontend
"""
# Receive message
# ---------------
msg_data = change["new"]
if not msg_data:
self._js2py_traceDeltas = None
return
trace_deltas = msg_data["trace_deltas"]
trace_edit_id = msg_data["trace_edit_id"]
# Apply deltas
# ------------
# We only apply the deltas if this message corresponds to the most
# recent trace edit operation
if trace_edit_id == self._last_trace_edit_id:
# ### Loop over deltas ###
for delta in trace_deltas:
# #### Find existing trace for uid ###
trace_uid = delta["uid"]
trace_uids = [trace.uid for trace in self.data]
trace_index = trace_uids.index(trace_uid)
uid_trace = self.data[trace_index]
# #### Transform defaults to delta ####
delta_transform = BaseFigureWidget._transform_data(
uid_trace._prop_defaults, delta
)
# #### Remove overlapping properties ####
# If a property is present in both _props and _prop_defaults
# then we remove the copy from _props
remove_props = self._remove_overlapping_props(
uid_trace._props, uid_trace._prop_defaults
)
# #### Notify frontend model of property removal ####
if remove_props:
remove_trace_props_msg = {
"remove_trace": trace_index,
"remove_props": remove_props,
}
self._py2js_removeTraceProps = remove_trace_props_msg
self._py2js_removeTraceProps = None
# #### Dispatch change callbacks ####
self._dispatch_trace_change_callbacks(delta_transform, [trace_index])
# ### Trace edits no longer in process ###
self._trace_edit_in_process = False
# ### Call any waiting trace edit callbacks ###
if not self._layout_edit_in_process:
while self._waiting_edit_callbacks:
self._waiting_edit_callbacks.pop()()
self._js2py_traceDeltas = None
@observe("_js2py_layoutDelta")
def _handler_js2py_layoutDelta(self, change):
"""
Process layout delta message from the frontend
"""
# Receive message
# ---------------
msg_data = change["new"]
if not msg_data:
self._js2py_layoutDelta = None
return
layout_delta = msg_data["layout_delta"]
layout_edit_id = msg_data["layout_edit_id"]
# Apply delta
# -----------
# We only apply the delta if this message corresponds to the most
# recent layout edit operation
if layout_edit_id == self._last_layout_edit_id:
# ### Transform defaults to delta ###
delta_transform = BaseFigureWidget._transform_data(
self._layout_defaults, layout_delta
)
# ### Remove overlapping properties ###
# If a property is present in both _layout and _layout_defaults
# then we remove the copy from _layout
removed_props = self._remove_overlapping_props(
self._widget_layout, self._layout_defaults
)
# ### Notify frontend model of property removal ###
if removed_props:
remove_props_msg = {"remove_props": removed_props}
self._py2js_removeLayoutProps = remove_props_msg
self._py2js_removeLayoutProps = None
# ### Create axis objects ###
# For example, when a SPLOM trace is created the layout defaults
# may include axes that weren't explicitly defined by the user.
for proppath in delta_transform:
prop = proppath[0]
match = self.layout._subplot_re_match(prop)
if match and prop not in self.layout:
# We need to create a subplotid object
self.layout[prop] = {}
# ### Dispatch change callbacks ###
self._dispatch_layout_change_callbacks(delta_transform)
# ### Layout edits no longer in process ###
self._layout_edit_in_process = False
# ### Call any waiting layout edit callbacks ###
if not self._trace_edit_in_process:
while self._waiting_edit_callbacks:
self._waiting_edit_callbacks.pop()()
self._js2py_layoutDelta = None
@observe("_js2py_restyle")
def _handler_js2py_restyle(self, change):
"""
Process Plotly.restyle message from the frontend
"""
# Receive message
# ---------------
restyle_msg = change["new"]
if not restyle_msg:
self._js2py_restyle = None
return
style_data = restyle_msg["style_data"]
style_traces = restyle_msg["style_traces"]
source_view_id = restyle_msg["source_view_id"]
# Perform restyle
# ---------------
self.plotly_restyle(
restyle_data=style_data,
trace_indexes=style_traces,
source_view_id=source_view_id,
)
self._js2py_restyle = None
@observe("_js2py_update")
def _handler_js2py_update(self, change):
"""
Process Plotly.update message from the frontend
"""
# Receive message
# ---------------
update_msg = change["new"]
if not update_msg:
self._js2py_update = None
return
style = update_msg["style_data"]
trace_indexes = update_msg["style_traces"]
layout = update_msg["layout_data"]
source_view_id = update_msg["source_view_id"]
# Perform update
# --------------
self.plotly_update(
restyle_data=style,
relayout_data=layout,
trace_indexes=trace_indexes,
source_view_id=source_view_id,
)
self._js2py_update = None
@observe("_js2py_relayout")
def _handler_js2py_relayout(self, change):
"""
Process Plotly.relayout message from the frontend
"""
# Receive message
# ---------------
relayout_msg = change["new"]
if not relayout_msg:
self._js2py_relayout = None
return
relayout_data = relayout_msg["relayout_data"]
source_view_id = relayout_msg["source_view_id"]
if "lastInputTime" in relayout_data:
# Remove 'lastInputTime'. Seems to be an internal plotly
# property that is introduced for some plot types, but it is not
# actually a property in the schema
relayout_data.pop("lastInputTime")
# Perform relayout
# ----------------
self.plotly_relayout(relayout_data=relayout_data, source_view_id=source_view_id)
self._js2py_relayout = None
@observe("_js2py_pointsCallback")
def _handler_js2py_pointsCallback(self, change):
"""
Process points callback message from the frontend
"""
# Receive message
# ---------------
callback_data = change["new"]
if not callback_data:
self._js2py_pointsCallback = None
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"]
selector_state = selector_data["selector_state"]
if selector_type == "box":
selector = BoxSelector(**selector_state)
elif selector_type == "lasso":
selector = LassoSelector(**selector_state)
else:
raise ValueError("Unsupported selector type: %s" % selector_type)
else:
selector = None
# Build Input Device State Object
# -------------------------------
if callback_data.get("device_state", None):
device_state_data = callback_data["device_state"]
state = InputDeviceState(**device_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].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["point_indexes"],
points_data["trace_indexes"],
):
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]
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_selection(points, selector)
elif event_type == "plotly_deselect":
trace._dispatch_on_deselect(points)
self._js2py_pointsCallback = None
# Display
# -------
def _repr_html_(self):
"""
Customize html representation
"""
raise NotImplementedError # Prefer _repr_mimebundle_
def _repr_mimebundle_(self, include=None, exclude=None, validate=True, **kwargs):
"""
Return mimebundle corresponding to default renderer.
"""
display_jupyter_version_warnings()
# Widget layout and data need to be set here in case there are
# changes made to the figure after the widget is created but before
# the cell is run.
self._widget_layout = deepcopy(self._layout_obj._props)
self._widget_data = deepcopy(self._data)
return {
"application/vnd.jupyter.widget-view+json": {
"version_major": 2,
"version_minor": 0,
"model_id": self._model_id,
},
}
def _ipython_display_(self):
"""
Handle rich display of figures in ipython contexts
"""
raise NotImplementedError # Prefer _repr_mimebundle_
# Callbacks
# ---------
def on_edits_completed(self, fn):
"""
Register a function to be called after all pending trace and layout
edit operations have completed
If there are no pending edit operations then function is called
immediately
Parameters
----------
fn : callable
Function of zero arguments to be called when all pending edit
operations have completed
"""
if self._layout_edit_in_process or self._trace_edit_in_process:
self._waiting_edit_callbacks.append(fn)
else:
fn()
# Validate No Frames
# ------------------
@property
def frames(self):
# Note: This property getter is identical to that of the superclass,
# but it must be included here because we're overriding the setter
# below.
return self._frame_objs
@frames.setter
def frames(self, new_frames):
if new_frames:
BaseFigureWidget._display_frames_error()
@staticmethod
def _display_frames_error():
"""
Display an informative error when user attempts to set frames on a
FigureWidget
Raises
------
ValueError
always
"""
msg = """
Frames are not supported by the plotly.graph_objs.FigureWidget class.
Note: Frames are supported by the plotly.graph_objs.Figure class"""
raise ValueError(msg)
# Static Helpers
# --------------
@staticmethod
def _remove_overlapping_props(input_data, delta_data, prop_path=()):
"""
Remove properties in input_data that are also in delta_data, and do so
recursively.
Exception: Never remove 'uid' from input_data, this property is used
to align traces
Parameters
----------
input_data : dict|list
delta_data : dict|list
Returns
-------
list[tuple[str|int]]
List of removed property path tuples
"""
# Initialize removed
# ------------------
# This is the list of path tuples to the properties that were
# removed from input_data
removed = []
# Handle dict
# -----------
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_dict_list(delta_val):
if p in input_data:
# ### Recurse ###
input_val = input_data[p]
recur_prop_path = prop_path + (p,)
recur_removed = BaseFigureWidget._remove_overlapping_props(
input_val, delta_val, recur_prop_path
)
removed.extend(recur_removed)
# Check whether the last property in input_val
# has been removed. If so, remove it entirely
if not input_val:
input_data.pop(p)
removed.append(recur_prop_path)
elif p in input_data and p != "uid":
# ### Remove property ###
input_data.pop(p)
removed.append(prop_path + (p,))
# Handle list
# -----------
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_dict_list(delta_val)
):
# ### Recurse ###
recur_prop_path = prop_path + (i,)
recur_removed = BaseFigureWidget._remove_overlapping_props(
input_val, delta_val, recur_prop_path
)
removed.extend(recur_removed)
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 the transformation
Parameters
----------
to_data : dict|list
from_data : dict|list
Returns
-------
dict
relayout-style description of the transformation
"""
# Initialize relayout data
# ------------------------
relayout_data = {}
# Handle dict
# -----------
if isinstance(to_data, dict):
# ### Validate from_data ###
if not isinstance(from_data, dict):
raise ValueError(
"Mismatched data types: {to_dict} {from_data}".format(
to_dict=to_data, from_data=from_data
)
)
# ### Add/modify properties ###
# Loop over props/vals
for from_prop, from_val in from_data.items():
# #### Handle compound vals recursively ####
if isinstance(from_val, dict) or BaseFigure._is_dict_list(from_val):
# ##### Init property value if needed #####
if from_prop not in to_data:
to_data[from_prop] = {} if isinstance(from_val, dict) else []
# ##### Transform property val recursively #####
input_val = to_data[from_prop]
relayout_data.update(
BaseFigureWidget._transform_data(
input_val,
from_val,
should_remove=should_remove,
relayout_path=relayout_path + (from_prop,),
)
)
# #### Handle simple vals directly ####
else:
if from_prop not in to_data or not BasePlotlyType._vals_equal(
to_data[from_prop], from_val
):
to_data[from_prop] = from_val
relayout_path_prop = relayout_path + (from_prop,)
relayout_data[relayout_path_prop] = from_val
# ### Remove properties ###
if should_remove:
for remove_prop in set(to_data.keys()).difference(
set(from_data.keys())
):
to_data.pop(remove_prop)
# Handle list
# -----------
elif isinstance(to_data, list):
# ### Validate from_data ###
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
)
)
# ### Add/modify properties ###
# Loop over indexes / elements
for i, from_val in enumerate(from_data):
# #### Initialize element if needed ####
if i >= len(to_data):
to_data.append(None)
input_val = to_data[i]
# #### Handle compound element recursively ####
if input_val is not None and (
isinstance(from_val, dict) or BaseFigure._is_dict_list(from_val)
):
relayout_data.update(
BaseFigureWidget._transform_data(
input_val,
from_val,
should_remove=should_remove,
relayout_path=relayout_path + (i,),
)
)
# #### Handle simple elements directly ####
else:
if not BasePlotlyType._vals_equal(to_data[i], from_val):
to_data[i] = from_val
relayout_data[relayout_path + (i,)] = from_val
return relayout_data

View File

@ -0,0 +1,294 @@
from plotly.utils import _list_repr_elided
class InputDeviceState:
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 """\
InputDeviceState(
ctrl={ctrl},
alt={alt},
shift={shift},
meta={meta},
button={button},
buttons={buttons})""".format(
ctrl=repr(self.ctrl),
alt=repr(self.alt),
meta=repr(self.meta),
shift=repr(self.shift),
button=repr(self.button),
buttons=repr(self.buttons),
)
@property
def alt(self):
"""
Whether alt key pressed
Returns
-------
bool
"""
return self._alt
@property
def ctrl(self):
"""
Whether ctrl key pressed
Returns
-------
bool
"""
return self._ctrl
@property
def shift(self):
"""
Whether shift key pressed
Returns
-------
bool
"""
return self._shift
@property
def meta(self):
"""
Whether meta key pressed
Returns
-------
bool
"""
return self._meta
@property
def button(self):
"""
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):
"""
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=[], xs=[], ys=[], 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
def __repr__(self):
return """\
Points(point_inds={point_inds},
xs={xs},
ys={ys},
trace_name={trace_name},
trace_index={trace_index})""".format(
point_inds=_list_repr_elided(
self.point_inds, indent=len("Points(point_inds=")
),
xs=_list_repr_elided(self.xs, indent=len(" xs=")),
ys=_list_repr_elided(self.ys, indent=len(" ys=")),
trace_name=repr(self.trace_name),
trace_index=repr(self.trace_index),
)
@property
def point_inds(self):
"""
List of selected indexes into the trace's points
Returns
-------
list[int]
"""
return self._point_inds
@property
def xs(self):
"""
List of x-coordinates of selected points
Returns
-------
list[float]
"""
return self._xs
@property
def ys(self):
"""
List of y-coordinates of selected points
Returns
-------
list[float]
"""
return self._ys
@property
def trace_name(self):
"""
Name of the trace
Returns
-------
str
"""
return self._trace_name
@property
def trace_index(self):
"""
Index of the trace in the figure
Returns
-------
int
"""
return self._trace_index
class BoxSelector:
def __init__(self, xrange=None, yrange=None, **_):
self._type = "box"
self._xrange = xrange
self._yrange = yrange
def __repr__(self):
return """\
BoxSelector(xrange={xrange},
yrange={yrange})""".format(xrange=self.xrange, yrange=self.yrange)
@property
def type(self):
"""
The selector's type
Returns
-------
str
"""
return self._type
@property
def xrange(self):
"""
x-axis range extents of the box selection
Returns
-------
(float, float)
"""
return self._xrange
@property
def yrange(self):
"""
y-axis range extents of the box selection
Returns
-------
(float, float)
"""
return self._yrange
class LassoSelector:
def __init__(self, xs=None, ys=None, **_):
self._type = "lasso"
self._xs = xs
self._ys = ys
def __repr__(self):
return """\
LassoSelector(xs={xs},
ys={ys})""".format(
xs=_list_repr_elided(self.xs, indent=len("LassoSelector(xs=")),
ys=_list_repr_elided(self.ys, indent=len(" ys=")),
)
@property
def type(self):
"""
The selector's type
Returns
-------
str
"""
return self._type
@property
def xs(self):
"""
list of x-axis coordinates of each point in the lasso selection
boundary
Returns
-------
list[float]
"""
return self._xs
@property
def ys(self):
"""
list of y-axis coordinates of each point in the lasso selection
boundary
Returns
-------
list[float]
"""
return self._ys

View File

@ -0,0 +1,51 @@
# ruff: noqa: F405
"""For a list of colors available in `plotly.colors`, please see
* the `tutorial on discrete color sequences <https://plotly.com/python/discrete-color/#color-sequences-in-plotly-express>`_
* the `list of built-in continuous color scales <https://plotly.com/python/builtin-colorscales/>`_
* the `tutorial on continuous colors <https://plotly.com/python/colorscales/>`_
Color scales and sequences are available within the following namespaces
* cyclical
* diverging
* qualitative
* sequential
"""
from _plotly_utils.colors import * # noqa: F403
__all__ = [
"named_colorscales",
"cyclical",
"diverging",
"sequential",
"qualitative",
"colorbrewer",
"carto",
"cmocean",
"color_parser",
"colorscale_to_colors",
"colorscale_to_scale",
"convert_colors_to_same_type",
"convert_colorscale_to_rgb",
"convert_dict_colors_to_same_type",
"convert_to_RGB_255",
"find_intermediate_color",
"hex_to_rgb",
"label_rgb",
"make_colorscale",
"n_colors",
"sample_colorscale",
"unconvert_from_RGB_255",
"unlabel_rgb",
"validate_colors",
"validate_colors_dict",
"validate_colorscale",
"validate_scale_values",
"plotlyjs",
"DEFAULT_PLOTLY_COLORS",
"PLOTLY_SCALES",
"get_colorscale",
]

View File

@ -0,0 +1,24 @@
import os
def pytest_ignore_collect(path):
# Ignored files, most of them are raising a chart studio error
ignored_paths = [
"exploding_module.py",
"chunked_requests.py",
"v2.py",
"v1.py",
"presentation_objs.py",
"widgets.py",
"dashboard_objs.py",
"grid_objs.py",
"config.py",
"presentation_objs.py",
"session.py",
]
if (
os.path.basename(str(path)) in ignored_paths
or "plotly/plotly/plotly/__init__.py" in str(path)
or "plotly/api/utils.py" in str(path)
):
return True

View File

@ -0,0 +1,430 @@
"""
Built-in datasets for demonstration, educational and test purposes.
"""
import os
from importlib import import_module
import narwhals.stable.v1 as nw
AVAILABLE_BACKENDS = {"pandas", "polars", "pyarrow", "modin", "cudf"}
BACKENDS_WITH_INDEX_SUPPORT = {"pandas", "modin", "cudf"}
def gapminder(
datetimes=False,
centroids=False,
year=None,
pretty_names=False,
return_type="pandas",
):
"""
Each row represents a country on a given year.
https://www.gapminder.org/data/
Parameters
----------
datetimes: bool
Whether or not 'year' column will converted to datetime type
centroids: bool
If True, ['centroid_lat', 'centroid_lon'] columns are added
year: int | None
If provided, the dataset will be filtered for that year
pretty_names: bool
If True, prettifies the column names
return_type: {'pandas', 'polars', 'pyarrow', 'modin', 'cudf'}
Type of the resulting dataframe
Returns
-------
Dataframe of `return_type` type
Dataframe with 1704 rows and the following columns:
`['country', 'continent', 'year', 'lifeExp', 'pop', 'gdpPercap',
'iso_alpha', 'iso_num']`.
If `datetimes` is True, the 'year' column will be a datetime column
If `centroids` is True, two new columns are added: ['centroid_lat', 'centroid_lon']
If `year` is an integer, the dataset will be filtered for that year
"""
df = nw.from_native(
_get_dataset("gapminder", return_type=return_type), eager_only=True
)
if year:
df = df.filter(nw.col("year") == year)
if datetimes:
df = df.with_columns(
# Concatenate the year value with the literal "-01-01" so that it can be
# casted to datetime from "%Y-%m-%d" format
nw.concat_str(
[nw.col("year").cast(nw.String()), nw.lit("-01-01")]
).str.to_datetime(format="%Y-%m-%d")
)
if not centroids:
df = df.drop("centroid_lat", "centroid_lon")
if pretty_names:
df = df.rename(
dict(
country="Country",
continent="Continent",
year="Year",
lifeExp="Life Expectancy",
gdpPercap="GDP per Capita",
pop="Population",
iso_alpha="ISO Alpha Country Code",
iso_num="ISO Numeric Country Code",
centroid_lat="Centroid Latitude",
centroid_lon="Centroid Longitude",
)
)
return df.to_native()
def tips(pretty_names=False, return_type="pandas"):
"""
Each row represents a restaurant bill.
https://vincentarelbundock.github.io/Rdatasets/doc/reshape2/tips.html
Parameters
----------
pretty_names: bool
If True, prettifies the column names
return_type: {'pandas', 'polars', 'pyarrow', 'modin', 'cudf'}
Type of the resulting dataframe
Returns
-------
Dataframe of `return_type` type
Dataframe with 244 rows and the following columns:
`['total_bill', 'tip', 'sex', 'smoker', 'day', 'time', 'size']`.
"""
df = nw.from_native(_get_dataset("tips", return_type=return_type), eager_only=True)
if pretty_names:
df = df.rename(
dict(
total_bill="Total Bill",
tip="Tip",
sex="Payer Gender",
smoker="Smokers at Table",
day="Day of Week",
time="Meal",
size="Party Size",
)
)
return df.to_native()
def iris(return_type="pandas"):
"""
Each row represents a flower.
https://en.wikipedia.org/wiki/Iris_flower_data_set
Parameters
----------
return_type: {'pandas', 'polars', 'pyarrow', 'modin', 'cudf'}
Type of the resulting dataframe
Returns
-------
Dataframe of `return_type` type
Dataframe with 150 rows and the following columns:
`['sepal_length', 'sepal_width', 'petal_length', 'petal_width', 'species', 'species_id']`.
"""
return _get_dataset("iris", return_type=return_type)
def wind(return_type="pandas"):
"""
Each row represents a level of wind intensity in a cardinal direction, and its frequency.
Parameters
----------
return_type: {'pandas', 'polars', 'pyarrow', 'modin', 'cudf'}
Type of the resulting dataframe
Returns
-------
Dataframe of `return_type` type
Dataframe with 128 rows and the following columns:
`['direction', 'strength', 'frequency']`.
"""
return _get_dataset("wind", return_type=return_type)
def election(return_type="pandas"):
"""
Each row represents voting results for an electoral district in the 2013 Montreal
mayoral election.
Parameters
----------
return_type: {'pandas', 'polars', 'pyarrow', 'modin', 'cudf'}
Type of the resulting dataframe
Returns
-------
Dataframe of `return_type` type
Dataframe with 58 rows and the following columns:
`['district', 'Coderre', 'Bergeron', 'Joly', 'total', 'winner', 'result', 'district_id']`.
"""
return _get_dataset("election", return_type=return_type)
def election_geojson():
"""
Each feature represents an electoral district in the 2013 Montreal mayoral election.
Returns
-------
A GeoJSON-formatted `dict` with 58 polygon or multi-polygon features whose `id`
is an electoral district numerical ID and whose `district` property is the ID and
district name.
"""
import gzip
import json
import os
path = os.path.join(
os.path.dirname(os.path.dirname(__file__)),
"package_data",
"datasets",
"election.geojson.gz",
)
with gzip.GzipFile(path, "r") as f:
result = json.loads(f.read().decode("utf-8"))
return result
def carshare(return_type="pandas"):
"""
Each row represents the availability of car-sharing services near the centroid of a zone
in Montreal over a month-long period.
Parameters
----------
return_type: {'pandas', 'polars', 'pyarrow', 'modin', 'cudf'}
Type of the resulting dataframe
Returns
-------
Dataframe of `return_type` type
Dataframe` with 249 rows and the following columns:
`['centroid_lat', 'centroid_lon', 'car_hours', 'peak_hour']`.
"""
return _get_dataset("carshare", return_type=return_type)
def stocks(indexed=False, datetimes=False, return_type="pandas"):
"""
Each row in this wide dataset represents closing prices from 6 tech stocks in 2018/2019.
Parameters
----------
indexed: bool
Whether or not the 'date' column is used as the index and the column index
is named 'company'. Applicable only if `return_type='pandas'`
datetimes: bool
Whether or not the 'date' column will be of datetime type
return_type: {'pandas', 'polars', 'pyarrow', 'modin', 'cudf'}
Type of the resulting dataframe
Returns
-------
Dataframe of `return_type` type
Dataframe with 100 rows and the following columns:
`['date', 'GOOG', 'AAPL', 'AMZN', 'FB', 'NFLX', 'MSFT']`.
If `indexed` is True, the 'date' column is used as the index and the column index
is named 'company'
If `datetimes` is True, the 'date' column will be a datetime column
"""
if indexed and return_type not in BACKENDS_WITH_INDEX_SUPPORT:
msg = f"Backend '{return_type}' does not support setting index"
raise NotImplementedError(msg)
df = nw.from_native(
_get_dataset("stocks", return_type=return_type), eager_only=True
).with_columns(nw.col("date").cast(nw.String()))
if datetimes:
df = df.with_columns(nw.col("date").str.to_datetime())
if indexed: # then it must be pandas
df = df.to_native().set_index("date")
df.columns.name = "company"
return df
return df.to_native()
def experiment(indexed=False, return_type="pandas"):
"""
Each row in this wide dataset represents the results of 100 simulated participants
on three hypothetical experiments, along with their gender and control/treatment group.
Parameters
----------
indexed: bool
If True, then the index is named "participant".
Applicable only if `return_type='pandas'`
return_type: {'pandas', 'polars', 'pyarrow', 'modin', 'cudf'}
Type of the resulting dataframe
Returns
-------
Dataframe of `return_type` type
Dataframe with 100 rows and the following columns:
`['experiment_1', 'experiment_2', 'experiment_3', 'gender', 'group']`.
If `indexed` is True, the data frame index is named "participant"
"""
if indexed and return_type not in BACKENDS_WITH_INDEX_SUPPORT:
msg = f"Backend '{return_type}' does not support setting index"
raise NotImplementedError(msg)
df = nw.from_native(
_get_dataset("experiment", return_type=return_type), eager_only=True
)
if indexed: # then it must be pandas
df = df.to_native()
df.index.name = "participant"
return df
return df.to_native()
def medals_wide(indexed=False, return_type="pandas"):
"""
This dataset represents the medal table for Olympic Short Track Speed Skating for the
top three nations as of 2020.
Parameters
----------
indexed: bool
Whether or not the 'nation' column is used as the index and the column index
is named 'medal'. Applicable only if `return_type='pandas'`
return_type: {'pandas', 'polars', 'pyarrow', 'modin', 'cudf'}
Type of the resulting dataframe
Returns
-------
Dataframe of `return_type` type
Dataframe with 3 rows and the following columns:
`['nation', 'gold', 'silver', 'bronze']`.
If `indexed` is True, the 'nation' column is used as the index and the column index
is named 'medal'
"""
if indexed and return_type not in BACKENDS_WITH_INDEX_SUPPORT:
msg = f"Backend '{return_type}' does not support setting index"
raise NotImplementedError(msg)
df = nw.from_native(
_get_dataset("medals", return_type=return_type), eager_only=True
)
if indexed: # then it must be pandas
df = df.to_native().set_index("nation")
df.columns.name = "medal"
return df
return df.to_native()
def medals_long(indexed=False, return_type="pandas"):
"""
This dataset represents the medal table for Olympic Short Track Speed Skating for the
top three nations as of 2020.
Parameters
----------
indexed: bool
Whether or not the 'nation' column is used as the index.
Applicable only if `return_type='pandas'`
return_type: {'pandas', 'polars', 'pyarrow', 'modin', 'cudf'}
Type of the resulting dataframe
Returns
-------
Dataframe of `return_type` type
Dataframe with 9 rows and the following columns: `['nation', 'medal', 'count']`.
If `indexed` is True, the 'nation' column is used as the index.
"""
if indexed and return_type not in BACKENDS_WITH_INDEX_SUPPORT:
msg = f"Backend '{return_type}' does not support setting index"
raise NotImplementedError(msg)
df = nw.from_native(
_get_dataset("medals", return_type=return_type), eager_only=True
).unpivot(
index=["nation"],
value_name="count",
variable_name="medal",
)
if indexed:
df = nw.maybe_set_index(df, "nation")
return df.to_native()
def _get_dataset(d, return_type):
"""
Loads the dataset using the specified backend.
Notice that the available backends are 'pandas', 'polars', 'pyarrow' and they all have
a `read_csv` function (pyarrow has it via pyarrow.csv). Therefore we can dynamically
load the library using `importlib.import_module` and then call
`backend.read_csv(filepath)`.
Parameters
----------
d: str
Name of the dataset to load.
return_type: {'pandas', 'polars', 'pyarrow', 'modin', 'cudf'}
Type of the resulting dataframe
Returns
-------
Dataframe of `return_type` type
"""
filepath = os.path.join(
os.path.dirname(os.path.dirname(__file__)),
"package_data",
"datasets",
d + ".csv.gz",
)
if return_type not in AVAILABLE_BACKENDS:
msg = (
f"Unsupported return_type. Found {return_type}, expected one "
f"of {AVAILABLE_BACKENDS}"
)
raise NotImplementedError(msg)
try:
if return_type == "pyarrow":
module_to_load = "pyarrow.csv"
elif return_type == "modin":
module_to_load = "modin.pandas"
else:
module_to_load = return_type
backend = import_module(module_to_load)
except ModuleNotFoundError:
msg = f"return_type={return_type}, but {return_type} is not installed"
raise ModuleNotFoundError(msg)
try:
return backend.read_csv(filepath)
except Exception as e:
msg = f"Unable to read '{d}' dataset due to: {e}"
raise Exception(msg).with_traceback(e.__traceback__)

View File

@ -0,0 +1 @@
from _plotly_utils.exceptions import PlotlyError # noqa: F401

View File

@ -0,0 +1,132 @@
# ruff: noqa: E402
"""
`plotly.express` is a terse, consistent, high-level wrapper around `plotly.graph_objects`
for rapid data exploration and figure generation. Learn more at https://plotly.com/python/plotly-express/
"""
from plotly import optional_imports
np = optional_imports.get_module("numpy")
if np is None:
raise ImportError(
"""\
Plotly Express requires numpy to be installed. You can install numpy using pip with:
$ pip install numpy
Or install Plotly Express and its dependencies directly with:
$ pip install "plotly[express]"
You can also use Plotly Graph Objects to create a large number of charts without installing
numpy. See examples here: https://plotly.com/python/graph-objects/
"""
)
from ._imshow import imshow
from ._chart_types import ( # noqa: F401
scatter,
scatter_3d,
scatter_polar,
scatter_ternary,
scatter_map,
scatter_mapbox,
scatter_geo,
line,
line_3d,
line_polar,
line_ternary,
line_map,
line_mapbox,
line_geo,
area,
bar,
timeline,
bar_polar,
violin,
box,
strip,
histogram,
ecdf,
scatter_matrix,
parallel_coordinates,
parallel_categories,
choropleth,
density_contour,
density_heatmap,
pie,
sunburst,
treemap,
icicle,
funnel,
funnel_area,
choropleth_map,
choropleth_mapbox,
density_map,
density_mapbox,
)
from ._core import ( # noqa: F401
set_mapbox_access_token,
defaults,
get_trendline_results,
NO_COLOR,
)
from ._special_inputs import IdentityMap, Constant, Range # noqa: F401
from . import data, colors, trendline_functions # noqa: F401
__all__ = [
"scatter",
"scatter_3d",
"scatter_polar",
"scatter_ternary",
"scatter_map",
"scatter_mapbox",
"scatter_geo",
"scatter_matrix",
"density_contour",
"density_heatmap",
"density_map",
"density_mapbox",
"line",
"line_3d",
"line_polar",
"line_ternary",
"line_map",
"line_mapbox",
"line_geo",
"parallel_coordinates",
"parallel_categories",
"area",
"bar",
"timeline",
"bar_polar",
"violin",
"box",
"strip",
"histogram",
"ecdf",
"choropleth",
"choropleth_map",
"choropleth_mapbox",
"pie",
"sunburst",
"treemap",
"icicle",
"funnel",
"funnel_area",
"imshow",
"data",
"colors",
"trendline_functions",
"set_mapbox_access_token",
"get_trendline_results",
"IdentityMap",
"Constant",
"Range",
"NO_COLOR",
]

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,640 @@
import inspect
from textwrap import TextWrapper
try:
getfullargspec = inspect.getfullargspec
except AttributeError: # python 2
getfullargspec = inspect.getargspec
colref_type = "str or int or Series or array-like"
colref_desc = "Either a name of a column in `data_frame`, or a pandas Series or array_like object."
colref_list_type = "list of str or int, or Series or array-like"
colref_list_desc = (
"Either names of columns in `data_frame`, or pandas Series, or array_like objects"
)
docs = dict(
data_frame=[
"DataFrame or array-like or dict",
"This argument needs to be passed for column names (and not keyword names) to be used.",
"Array-like and dict are transformed internally to a pandas DataFrame.",
"Optional: if missing, a DataFrame gets constructed under the hood using the other arguments.",
],
x=[
colref_type,
colref_desc,
"Values from this column or array_like are used to position marks along the x axis in cartesian coordinates.",
],
y=[
colref_type,
colref_desc,
"Values from this column or array_like are used to position marks along the y axis in cartesian coordinates.",
],
z=[
colref_type,
colref_desc,
"Values from this column or array_like are used to position marks along the z axis in cartesian coordinates.",
],
x_start=[
colref_type,
colref_desc,
"(required)",
"Values from this column or array_like are used to position marks along the x axis in cartesian coordinates.",
],
x_end=[
colref_type,
colref_desc,
"(required)",
"Values from this column or array_like are used to position marks along the x axis in cartesian coordinates.",
],
a=[
colref_type,
colref_desc,
"Values from this column or array_like are used to position marks along the a axis in ternary coordinates.",
],
b=[
colref_type,
colref_desc,
"Values from this column or array_like are used to position marks along the b axis in ternary coordinates.",
],
c=[
colref_type,
colref_desc,
"Values from this column or array_like are used to position marks along the c axis in ternary coordinates.",
],
r=[
colref_type,
colref_desc,
"Values from this column or array_like are used to position marks along the radial axis in polar coordinates.",
],
theta=[
colref_type,
colref_desc,
"Values from this column or array_like are used to position marks along the angular axis in polar coordinates.",
],
values=[
colref_type,
colref_desc,
"Values from this column or array_like are used to set values associated to sectors.",
],
parents=[
colref_type,
colref_desc,
"Values from this column or array_like are used as parents in sunburst and treemap charts.",
],
ids=[
colref_type,
colref_desc,
"Values from this column or array_like are used to set ids of sectors",
],
path=[
colref_list_type,
colref_list_desc,
"List of columns names or columns of a rectangular dataframe defining the hierarchy of sectors, from root to leaves.",
"An error is raised if path AND ids or parents is passed",
],
lat=[
colref_type,
colref_desc,
"Values from this column or array_like are used to position marks according to latitude on a map.",
],
lon=[
colref_type,
colref_desc,
"Values from this column or array_like are used to position marks according to longitude on a map.",
],
locations=[
colref_type,
colref_desc,
"Values from this column or array_like are to be interpreted according to `locationmode` and mapped to longitude/latitude.",
],
base=[
colref_type,
colref_desc,
"Values from this column or array_like are used to position the base of the bar.",
],
dimensions=[
colref_list_type,
colref_list_desc,
"Values from these columns are used for multidimensional visualization.",
],
dimensions_max_cardinality=[
"int (default 50)",
"When `dimensions` is `None` and `data_frame` is provided, "
"columns with more than this number of unique values are excluded from the output.",
"Not used when `dimensions` is passed.",
],
error_x=[
colref_type,
colref_desc,
"Values from this column or array_like are used to size x-axis error bars.",
"If `error_x_minus` is `None`, error bars will be symmetrical, otherwise `error_x` is used for the positive direction only.",
],
error_x_minus=[
colref_type,
colref_desc,
"Values from this column or array_like are used to size x-axis error bars in the negative direction.",
"Ignored if `error_x` is `None`.",
],
error_y=[
colref_type,
colref_desc,
"Values from this column or array_like are used to size y-axis error bars.",
"If `error_y_minus` is `None`, error bars will be symmetrical, otherwise `error_y` is used for the positive direction only.",
],
error_y_minus=[
colref_type,
colref_desc,
"Values from this column or array_like are used to size y-axis error bars in the negative direction.",
"Ignored if `error_y` is `None`.",
],
error_z=[
colref_type,
colref_desc,
"Values from this column or array_like are used to size z-axis error bars.",
"If `error_z_minus` is `None`, error bars will be symmetrical, otherwise `error_z` is used for the positive direction only.",
],
error_z_minus=[
colref_type,
colref_desc,
"Values from this column or array_like are used to size z-axis error bars in the negative direction.",
"Ignored if `error_z` is `None`.",
],
color=[
colref_type,
colref_desc,
"Values from this column or array_like are used to assign color to marks.",
],
opacity=["float", "Value between 0 and 1. Sets the opacity for markers."],
line_dash=[
colref_type,
colref_desc,
"Values from this column or array_like are used to assign dash-patterns to lines.",
],
line_group=[
colref_type,
colref_desc,
"Values from this column or array_like are used to group rows of `data_frame` into lines.",
],
symbol=[
colref_type,
colref_desc,
"Values from this column or array_like are used to assign symbols to marks.",
],
pattern_shape=[
colref_type,
colref_desc,
"Values from this column or array_like are used to assign pattern shapes to marks.",
],
size=[
colref_type,
colref_desc,
"Values from this column or array_like are used to assign mark sizes.",
],
radius=["int (default is 30)", "Sets the radius of influence of each point."],
hover_name=[
colref_type,
colref_desc,
"Values from this column or array_like appear in bold in the hover tooltip.",
],
hover_data=[
"str, or list of str or int, or Series or array-like, or dict",
"Either a name or list of names of columns in `data_frame`, or pandas Series,",
"or array_like objects",
"or a dict with column names as keys, with values True (for default formatting)",
"False (in order to remove this column from hover information),",
"or a formatting string, for example ':.3f' or '|%a'",
"or list-like data to appear in the hover tooltip",
"or tuples with a bool or formatting string as first element,",
"and list-like data to appear in hover as second element",
"Values from these columns appear as extra data in the hover tooltip.",
],
custom_data=[
"str, or list of str or int, or Series or array-like",
"Either name or list of names of columns in `data_frame`, or pandas Series, or array_like objects",
"Values from these columns are extra data, to be used in widgets or Dash callbacks for example. This data is not user-visible but is included in events emitted by the figure (lasso selection etc.)",
],
text=[
colref_type,
colref_desc,
"Values from this column or array_like appear in the figure as text labels.",
],
names=[
colref_type,
colref_desc,
"Values from this column or array_like are used as labels for sectors.",
],
locationmode=[
"str",
"One of 'ISO-3', 'USA-states', or 'country names'",
"Determines the set of locations used to match entries in `locations` to regions on the map.",
],
facet_row=[
colref_type,
colref_desc,
"Values from this column or array_like are used to assign marks to facetted subplots in the vertical direction.",
],
facet_col=[
colref_type,
colref_desc,
"Values from this column or array_like are used to assign marks to facetted subplots in the horizontal direction.",
],
facet_col_wrap=[
"int",
"Maximum number of facet columns.",
"Wraps the column variable at this width, so that the column facets span multiple rows.",
"Ignored if 0, and forced to 0 if `facet_row` or a `marginal` is set.",
],
facet_row_spacing=[
"float between 0 and 1",
"Spacing between facet rows, in paper units. Default is 0.03 or 0.07 when facet_col_wrap is used.",
],
facet_col_spacing=[
"float between 0 and 1",
"Spacing between facet columns, in paper units Default is 0.02.",
],
animation_frame=[
colref_type,
colref_desc,
"Values from this column or array_like are used to assign marks to animation frames.",
],
animation_group=[
colref_type,
colref_desc,
"Values from this column or array_like are used to provide object-constancy across animation frames: rows with matching `animation_group`s will be treated as if they describe the same object in each frame.",
],
symbol_sequence=[
"list of str",
"Strings should define valid plotly.js symbols.",
"When `symbol` is set, values in that column are assigned symbols by cycling through `symbol_sequence` in the order described in `category_orders`, unless the value of `symbol` is a key in `symbol_map`.",
],
symbol_map=[
"dict with str keys and str values (default `{}`)",
"String values should define plotly.js symbols",
"Used to override `symbol_sequence` to assign a specific symbols to marks corresponding with specific values.",
"Keys in `symbol_map` should be values in the column denoted by `symbol`.",
"Alternatively, if the values of `symbol` are valid symbol names, the string `'identity'` may be passed to cause them to be used directly.",
],
line_dash_map=[
"dict with str keys and str values (default `{}`)",
"Strings values define plotly.js dash-patterns.",
"Used to override `line_dash_sequences` to assign a specific dash-patterns to lines corresponding with specific values.",
"Keys in `line_dash_map` should be values in the column denoted by `line_dash`.",
"Alternatively, if the values of `line_dash` are valid line-dash names, the string `'identity'` may be passed to cause them to be used directly.",
],
line_dash_sequence=[
"list of str",
"Strings should define valid plotly.js dash-patterns.",
"When `line_dash` is set, values in that column are assigned dash-patterns by cycling through `line_dash_sequence` in the order described in `category_orders`, unless the value of `line_dash` is a key in `line_dash_map`.",
],
pattern_shape_map=[
"dict with str keys and str values (default `{}`)",
"Strings values define plotly.js patterns-shapes.",
"Used to override `pattern_shape_sequences` to assign a specific patterns-shapes to lines corresponding with specific values.",
"Keys in `pattern_shape_map` should be values in the column denoted by `pattern_shape`.",
"Alternatively, if the values of `pattern_shape` are valid patterns-shapes names, the string `'identity'` may be passed to cause them to be used directly.",
],
pattern_shape_sequence=[
"list of str",
"Strings should define valid plotly.js patterns-shapes.",
"When `pattern_shape` is set, values in that column are assigned patterns-shapes by cycling through `pattern_shape_sequence` in the order described in `category_orders`, unless the value of `pattern_shape` is a key in `pattern_shape_map`.",
],
color_discrete_sequence=[
"list of str",
"Strings should define valid CSS-colors.",
"When `color` is set and the values in the corresponding column are not numeric, values in that column are assigned colors by cycling through `color_discrete_sequence` in the order described in `category_orders`, unless the value of `color` is a key in `color_discrete_map`.",
"Various useful color sequences are available in the `plotly.express.colors` submodules, specifically `plotly.express.colors.qualitative`.",
],
color_discrete_map=[
"dict with str keys and str values (default `{}`)",
"String values should define valid CSS-colors",
"Used to override `color_discrete_sequence` to assign a specific colors to marks corresponding with specific values.",
"Keys in `color_discrete_map` should be values in the column denoted by `color`.",
"Alternatively, if the values of `color` are valid colors, the string `'identity'` may be passed to cause them to be used directly.",
],
color_continuous_scale=[
"list of str",
"Strings should define valid CSS-colors",
"This list is used to build a continuous color scale when the column denoted by `color` contains numeric data.",
"Various useful color scales are available in the `plotly.express.colors` submodules, specifically `plotly.express.colors.sequential`, `plotly.express.colors.diverging` and `plotly.express.colors.cyclical`.",
],
color_continuous_midpoint=[
"number (default `None`)",
"If set, computes the bounds of the continuous color scale to have the desired midpoint.",
"Setting this value is recommended when using `plotly.express.colors.diverging` color scales as the inputs to `color_continuous_scale`.",
],
size_max=["int (default `20`)", "Set the maximum mark size when using `size`."],
markers=["boolean (default `False`)", "If `True`, markers are shown on lines."],
lines=[
"boolean (default `True`)",
"If `False`, lines are not drawn (forced to `True` if `markers` is `False`).",
],
log_x=[
"boolean (default `False`)",
"If `True`, the x-axis is log-scaled in cartesian coordinates.",
],
log_y=[
"boolean (default `False`)",
"If `True`, the y-axis is log-scaled in cartesian coordinates.",
],
log_z=[
"boolean (default `False`)",
"If `True`, the z-axis is log-scaled in cartesian coordinates.",
],
log_r=[
"boolean (default `False`)",
"If `True`, the radial axis is log-scaled in polar coordinates.",
],
range_x=[
"list of two numbers",
"If provided, overrides auto-scaling on the x-axis in cartesian coordinates.",
],
range_y=[
"list of two numbers",
"If provided, overrides auto-scaling on the y-axis in cartesian coordinates.",
],
range_z=[
"list of two numbers",
"If provided, overrides auto-scaling on the z-axis in cartesian coordinates.",
],
range_color=[
"list of two numbers",
"If provided, overrides auto-scaling on the continuous color scale.",
],
range_r=[
"list of two numbers",
"If provided, overrides auto-scaling on the radial axis in polar coordinates.",
],
range_theta=[
"list of two numbers",
"If provided, overrides auto-scaling on the angular axis in polar coordinates.",
],
title=["str", "The figure title."],
subtitle=["str", "The figure subtitle."],
template=[
"str or dict or plotly.graph_objects.layout.Template instance",
"The figure template name (must be a key in plotly.io.templates) or definition.",
],
width=["int (default `None`)", "The figure width in pixels."],
height=["int (default `None`)", "The figure height in pixels."],
labels=[
"dict with str keys and str values (default `{}`)",
"By default, column names are used in the figure for axis titles, legend entries and hovers.",
"This parameter allows this to be overridden.",
"The keys of this dict should correspond to column names, and the values should correspond to the desired label to be displayed.",
],
category_orders=[
"dict with str keys and list of str values (default `{}`)",
"By default, in Python 3.6+, the order of categorical values in axes, legends and facets depends on the order in which these values are first encountered in `data_frame` (and no order is guaranteed by default in Python below 3.6).",
"This parameter is used to force a specific ordering of values per column.",
"The keys of this dict should correspond to column names, and the values should be lists of strings corresponding to the specific display order desired.",
],
marginal=[
"str",
"One of `'rug'`, `'box'`, `'violin'`, or `'histogram'`.",
"If set, a subplot is drawn alongside the main plot, visualizing the distribution.",
],
marginal_x=[
"str",
"One of `'rug'`, `'box'`, `'violin'`, or `'histogram'`.",
"If set, a horizontal subplot is drawn above the main plot, visualizing the x-distribution.",
],
marginal_y=[
"str",
"One of `'rug'`, `'box'`, `'violin'`, or `'histogram'`.",
"If set, a vertical subplot is drawn to the right of the main plot, visualizing the y-distribution.",
],
trendline=[
"str",
"One of `'ols'`, `'lowess'`, `'rolling'`, `'expanding'` or `'ewm'`.",
"If `'ols'`, an Ordinary Least Squares regression line will be drawn for each discrete-color/symbol group.",
"If `'lowess`', a Locally Weighted Scatterplot Smoothing line will be drawn for each discrete-color/symbol group.",
"If `'rolling`', a Rolling (e.g. rolling average, rolling median) line will be drawn for each discrete-color/symbol group.",
"If `'expanding`', an Expanding (e.g. expanding average, expanding sum) line will be drawn for each discrete-color/symbol group.",
"If `'ewm`', an Exponentially Weighted Moment (e.g. exponentially-weighted moving average) line will be drawn for each discrete-color/symbol group.",
"See the docstrings for the functions in `plotly.express.trendline_functions` for more details on these functions and how",
"to configure them with the `trendline_options` argument.",
],
trendline_options=[
"dict",
"Options passed as the first argument to the function from `plotly.express.trendline_functions` ",
"named in the `trendline` argument.",
],
trendline_color_override=[
"str",
"Valid CSS color.",
"If provided, and if `trendline` is set, all trendlines will be drawn in this color rather than in the same color as the traces from which they draw their inputs.",
],
trendline_scope=[
"str (one of `'trace'` or `'overall'`, default `'trace'`)",
"If `'trace'`, then one trendline is drawn per trace (i.e. per color, symbol, facet, animation frame etc) and if `'overall'` then one trendline is computed for the entire dataset, and replicated across all facets.",
],
render_mode=[
"str",
"One of `'auto'`, `'svg'` or `'webgl'`, default `'auto'`",
"Controls the browser API used to draw marks.",
"`'svg'` is appropriate for figures of less than 1000 data points, and will allow for fully-vectorized output.",
"`'webgl'` is likely necessary for acceptable performance above 1000 points but rasterizes part of the output. ",
"`'auto'` uses heuristics to choose the mode.",
],
direction=[
"str",
"One of '`counterclockwise'` or `'clockwise'`. Default is `'clockwise'`",
"Sets the direction in which increasing values of the angular axis are drawn.",
],
start_angle=[
"int (default `90`)",
"Sets start angle for the angular axis, with 0 being due east and 90 being due north.",
],
histfunc=[
"str (default `'count'` if no arguments are provided, else `'sum'`)",
"One of `'count'`, `'sum'`, `'avg'`, `'min'`, or `'max'`.",
"Function used to aggregate values for summarization (note: can be normalized with `histnorm`).",
],
histnorm=[
"str (default `None`)",
"One of `'percent'`, `'probability'`, `'density'`, or `'probability density'`",
"If `None`, the output of `histfunc` is used as is.",
"If `'probability'`, the output of `histfunc` for a given bin is divided by the sum of the output of `histfunc` for all bins.",
"If `'percent'`, the output of `histfunc` for a given bin is divided by the sum of the output of `histfunc` for all bins and multiplied by 100.",
"If `'density'`, the output of `histfunc` for a given bin is divided by the size of the bin.",
"If `'probability density'`, the output of `histfunc` for a given bin is normalized such that it corresponds to the probability that a random event whose distribution is described by the output of `histfunc` will fall into that bin.",
],
barnorm=[
"str (default `None`)",
"One of `'fraction'` or `'percent'`.",
"If `'fraction'`, the value of each bar is divided by the sum of all values at that location coordinate.",
"`'percent'` is the same but multiplied by 100 to show percentages.",
"`None` will stack up all values at each location coordinate.",
],
groupnorm=[
"str (default `None`)",
"One of `'fraction'` or `'percent'`.",
"If `'fraction'`, the value of each point is divided by the sum of all values at that location coordinate.",
"`'percent'` is the same but multiplied by 100 to show percentages.",
"`None` will stack up all values at each location coordinate.",
],
barmode=[
"str (default `'relative'`)",
"One of `'group'`, `'overlay'` or `'relative'`",
"In `'relative'` mode, bars are stacked above zero for positive values and below zero for negative values.",
"In `'overlay'` mode, bars are drawn on top of one another.",
"In `'group'` mode, bars are placed beside each other.",
],
boxmode=[
"str (default `'group'`)",
"One of `'group'` or `'overlay'`",
"In `'overlay'` mode, boxes are on drawn top of one another.",
"In `'group'` mode, boxes are placed beside each other.",
],
violinmode=[
"str (default `'group'`)",
"One of `'group'` or `'overlay'`",
"In `'overlay'` mode, violins are on drawn top of one another.",
"In `'group'` mode, violins are placed beside each other.",
],
stripmode=[
"str (default `'group'`)",
"One of `'group'` or `'overlay'`",
"In `'overlay'` mode, strips are on drawn top of one another.",
"In `'group'` mode, strips are placed beside each other.",
],
zoom=["int (default `8`)", "Between 0 and 20.", "Sets map zoom level."],
orientation=[
"str, one of `'h'` for horizontal or `'v'` for vertical. ",
"(default `'v'` if `x` and `y` are provided and both continuous or both categorical, ",
"otherwise `'v'`(`'h'`) if `x`(`y`) is categorical and `y`(`x`) is continuous, ",
"otherwise `'v'`(`'h'`) if only `x`(`y`) is provided) ",
],
line_close=[
"boolean (default `False`)",
"If `True`, an extra line segment is drawn between the first and last point.",
],
line_shape=[
"str (default `'linear'`)",
"One of `'linear'`, `'spline'`, `'hv'`, `'vh'`, `'hvh'`, or `'vhv'`",
],
fitbounds=["str (default `False`).", "One of `False`, `locations` or `geojson`."],
basemap_visible=["bool", "Force the basemap visibility."],
scope=[
"str (default `'world'`).",
"One of `'world'`, `'usa'`, `'europe'`, `'asia'`, `'africa'`, `'north america'`, or `'south america'`"
"Default is `'world'` unless `projection` is set to `'albers usa'`, which forces `'usa'`.",
],
projection=[
"str ",
"One of `'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'`, or `'sinusoidal'`"
"Default depends on `scope`.",
],
center=[
"dict",
"Dict keys are `'lat'` and `'lon'`",
"Sets the center point of the map.",
],
map_style=[
"str (default `'basic'`)",
"Identifier of base map style.",
"Allowed values are `'basic'`, `'carto-darkmatter'`, `'carto-darkmatter-nolabels'`, `'carto-positron'`, `'carto-positron-nolabels'`, `'carto-voyager'`, `'carto-voyager-nolabels'`, `'dark'`, `'light'`, `'open-street-map'`, `'outdoors'`, `'satellite'`, `'satellite-streets'`, `'streets'`, `'white-bg'`.",
],
mapbox_style=[
"str (default `'basic'`, needs Mapbox API token)",
"Identifier of base map style, some of which require a Mapbox or Stadia Maps API token to be set using `plotly.express.set_mapbox_access_token()`.",
"Allowed values which do not require a token are `'open-street-map'`, `'white-bg'`, `'carto-positron'`, `'carto-darkmatter'`.",
"Allowed values which require a Mapbox API token are `'basic'`, `'streets'`, `'outdoors'`, `'light'`, `'dark'`, `'satellite'`, `'satellite-streets'`.",
"Allowed values which require a Stadia Maps API token are `'stamen-terrain'`, `'stamen-toner'`, `'stamen-watercolor'`.",
],
points=[
"str or boolean (default `'outliers'`)",
"One of `'outliers'`, `'suspectedoutliers'`, `'all'`, or `False`.",
"If `'outliers'`, only the sample points lying outside the whiskers are shown.",
"If `'suspectedoutliers'`, all outlier points are shown and those less than 4*Q1-3*Q3 or greater than 4*Q3-3*Q1 are highlighted with the marker's `'outliercolor'`.",
"If `'outliers'`, only the sample points lying outside the whiskers are shown.",
"If `'all'`, all sample points are shown.",
"If `False`, no sample points are shown and the whiskers extend to the full range of the sample.",
],
box=["boolean (default `False`)", "If `True`, boxes are drawn inside the violins."],
notched=["boolean (default `False`)", "If `True`, boxes are drawn with notches."],
geojson=[
"GeoJSON-formatted dict",
"Must contain a Polygon feature collection, with IDs, which are references from `locations`.",
],
featureidkey=[
"str (default: `'id'`)",
"Path to field in GeoJSON feature object with which to match the values passed in to `locations`."
"The most common alternative to the default is of the form `'properties.<key>`.",
],
cumulative=[
"boolean (default `False`)",
"If `True`, histogram values are cumulative.",
],
nbins=["int", "Positive integer.", "Sets the number of bins."],
nbinsx=["int", "Positive integer.", "Sets the number of bins along the x axis."],
nbinsy=["int", "Positive integer.", "Sets the number of bins along the y axis."],
branchvalues=[
"str",
"'total' or 'remainder'",
"Determines how the items in `values` are summed. When"
"set to 'total', items in `values` are taken to be value"
"of all its descendants. When set to 'remainder', items"
"in `values` corresponding to the root and the branches"
":sectors are taken to be the extra part not part of the"
"sum of the values at their leaves.",
],
maxdepth=[
"int",
"Positive integer",
"Sets the number of rendered sectors from any given `level`. Set `maxdepth` to -1 to render all the"
"levels in the hierarchy.",
],
ecdfnorm=[
"string or `None` (default `'probability'`)",
"One of `'probability'` or `'percent'`",
"If `None`, values will be raw counts or sums.",
"If `'probability', values will be probabilities normalized from 0 to 1.",
"If `'percent', values will be percentages normalized from 0 to 100.",
],
ecdfmode=[
"string (default `'standard'`)",
"One of `'standard'`, `'complementary'` or `'reversed'`",
"If `'standard'`, the ECDF is plotted such that values represent data at or below the point.",
"If `'complementary'`, the CCDF is plotted such that values represent data above the point.",
"If `'reversed'`, a variant of the CCDF is plotted such that values represent data at or above the point.",
],
text_auto=[
"bool or string (default `False`)",
"If `True` or a string, the x or y or z values will be displayed as text, depending on the orientation",
"A string like `'.2f'` will be interpreted as a `texttemplate` numeric formatting directive.",
],
)
def make_docstring(fn, override_dict=None, append_dict=None):
override_dict = {} if override_dict is None else override_dict
append_dict = {} if append_dict is None else append_dict
tw = TextWrapper(
width=75,
initial_indent=" ",
subsequent_indent=" ",
break_on_hyphens=False,
)
result = (fn.__doc__ or "") + "\nParameters\n----------\n"
for param in getfullargspec(fn)[0]:
if override_dict.get(param):
param_doc = list(override_dict[param])
else:
param_doc = list(docs[param])
if append_dict.get(param):
param_doc += append_dict[param]
param_desc_list = param_doc[1:]
param_desc = (
tw.fill(" ".join(param_desc_list or ""))
if param in docs or param in override_dict
else "(documentation missing from map)"
)
param_type = param_doc[0]
result += "%s: %s\n%s\n" % (param, param_type, param_desc)
result += "\nReturns\n-------\n"
result += " plotly.graph_objects.Figure"
return result

View File

@ -0,0 +1,605 @@
import plotly.graph_objs as go
from _plotly_utils.basevalidators import ColorscaleValidator
from ._core import apply_default_cascade, init_figure, configure_animation_controls
from .imshow_utils import rescale_intensity, _integer_ranges, _integer_types
import narwhals.stable.v1 as nw
import numpy as np
import itertools
from plotly.utils import image_array_to_data_uri
try:
import xarray
xarray_imported = True
except ImportError:
xarray_imported = False
_float_types = []
def _vectorize_zvalue(z, mode="max"):
alpha = 255 if mode == "max" else 0
if z is None:
return z
elif np.isscalar(z):
return [z] * 3 + [alpha]
elif len(z) == 1:
return list(z) * 3 + [alpha]
elif len(z) == 3:
return list(z) + [alpha]
elif len(z) == 4:
return z
else:
raise ValueError(
"zmax can be a scalar, or an iterable of length 1, 3 or 4. "
"A value of %s was passed for zmax." % str(z)
)
def _infer_zmax_from_type(img):
dt = img.dtype.type
rtol = 1.05
if dt in _integer_types:
return _integer_ranges[dt][1]
else:
im_max = img[np.isfinite(img)].max()
if im_max <= 1 * rtol:
return 1
elif im_max <= 255 * rtol:
return 255
elif im_max <= 65535 * rtol:
return 65535
else:
return 2**32
def imshow(
img,
zmin=None,
zmax=None,
origin=None,
labels={},
x=None,
y=None,
animation_frame=None,
facet_col=None,
facet_col_wrap=None,
facet_col_spacing=None,
facet_row_spacing=None,
color_continuous_scale=None,
color_continuous_midpoint=None,
range_color=None,
title=None,
template=None,
width=None,
height=None,
aspect=None,
contrast_rescaling=None,
binary_string=None,
binary_backend="auto",
binary_compression_level=4,
binary_format="png",
text_auto=False,
) -> go.Figure:
"""
Display an image, i.e. data on a 2D regular raster.
Parameters
----------
img: array-like image, or xarray
The image data. Supported array shapes are
- (M, N): an image with scalar data. The data is visualized
using a colormap.
- (M, N, 3): an image with RGB values.
- (M, N, 4): an image with RGBA values, i.e. including transparency.
zmin, zmax : scalar or iterable, optional
zmin and zmax define the scalar range that the colormap covers. By default,
zmin and zmax correspond to the min and max values of the datatype for integer
datatypes (ie [0-255] for uint8 images, [0, 65535] for uint16 images, etc.). For
a multichannel image of floats, the max of the image is computed and zmax is the
smallest power of 256 (1, 255, 65535) greater than this max value,
with a 5% tolerance. For a single-channel image, the max of the image is used.
Overridden by range_color.
origin : str, 'upper' or 'lower' (default 'upper')
position of the [0, 0] pixel of the image array, in the upper left or lower left
corner. The convention 'upper' is typically used for matrices and images.
labels : dict with str keys and str values (default `{}`)
Sets names used in the figure for axis titles (keys ``x`` and ``y``),
colorbar title and hoverlabel (key ``color``). The values should correspond
to the desired label to be displayed. If ``img`` is an xarray, dimension
names are used for axis titles, and long name for the colorbar title
(unless overridden in ``labels``). Possible keys are: x, y, and color.
x, y: list-like, optional
x and y are used to label the axes of single-channel heatmap visualizations and
their lengths must match the lengths of the second and first dimensions of the
img argument. They are auto-populated if the input is an xarray.
animation_frame: int or str, optional (default None)
axis number along which the image array is sliced to create an animation plot.
If `img` is an xarray, `animation_frame` can be the name of one the dimensions.
facet_col: int or str, optional (default None)
axis number along which the image array is sliced to create a facetted plot.
If `img` is an xarray, `facet_col` can be the name of one the dimensions.
facet_col_wrap: int
Maximum number of facet columns. Wraps the column variable at this width,
so that the column facets span multiple rows.
Ignored if `facet_col` is None.
facet_col_spacing: float between 0 and 1
Spacing between facet columns, in paper units. Default is 0.02.
facet_row_spacing: float between 0 and 1
Spacing between facet rows created when ``facet_col_wrap`` is used, in
paper units. Default is 0.0.7.
color_continuous_scale : str or list of str
colormap used to map scalar data to colors (for a 2D image). This parameter is
not used for RGB or RGBA images. If a string is provided, it should be the name
of a known color scale, and if a list is provided, it should be a list of CSS-
compatible colors.
color_continuous_midpoint : number
If set, computes the bounds of the continuous color scale to have the desired
midpoint. Overridden by range_color or zmin and zmax.
range_color : list of two numbers
If provided, overrides auto-scaling on the continuous color scale, including
overriding `color_continuous_midpoint`. Also overrides zmin and zmax. Used only
for single-channel images.
title : str
The figure title.
template : str or dict or plotly.graph_objects.layout.Template instance
The figure template name or definition.
width : number
The figure width in pixels.
height: number
The figure height in pixels.
aspect: 'equal', 'auto', or None
- 'equal': Ensures an aspect ratio of 1 or pixels (square pixels)
- 'auto': The axes is kept fixed and the aspect ratio of pixels is
adjusted so that the data fit in the axes. In general, this will
result in non-square pixels.
- if None, 'equal' is used for numpy arrays and 'auto' for xarrays
(which have typically heterogeneous coordinates)
contrast_rescaling: 'minmax', 'infer', or None
how to determine data values corresponding to the bounds of the color
range, when zmin or zmax are not passed. If `minmax`, the min and max
values of the image are used. If `infer`, a heuristic based on the image
data type is used.
binary_string: bool, default None
if True, the image data are first rescaled and encoded as uint8 and
then passed to plotly.js as a b64 PNG string. If False, data are passed
unchanged as a numerical array. Setting to True may lead to performance
gains, at the cost of a loss of precision depending on the original data
type. If None, use_binary_string is set to True for multichannel (eg) RGB
arrays, and to False for single-channel (2D) arrays. 2D arrays are
represented as grayscale and with no colorbar if use_binary_string is
True.
binary_backend: str, 'auto' (default), 'pil' or 'pypng'
Third-party package for the transformation of numpy arrays to
png b64 strings. If 'auto', Pillow is used if installed, otherwise
pypng.
binary_compression_level: int, between 0 and 9 (default 4)
png compression level to be passed to the backend when transforming an
array to a png b64 string. Increasing `binary_compression` decreases the
size of the png string, but the compression step takes more time. For most
images it is not worth using levels greater than 5, but it's possible to
test `len(fig.data[0].source)` and to time the execution of `imshow` to
tune the level of compression. 0 means no compression (not recommended).
binary_format: str, 'png' (default) or 'jpg'
compression format used to generate b64 string. 'png' is recommended
since it uses lossless compression, but 'jpg' (lossy) compression can
result if smaller binary strings for natural images.
text_auto: bool or str (default `False`)
If `True` or a string, single-channel `img` values will be displayed as text.
A string like `'.2f'` will be interpreted as a `texttemplate` numeric formatting directive.
Returns
-------
fig : graph_objects.Figure containing the displayed image
See also
--------
plotly.graph_objects.Image : image trace
plotly.graph_objects.Heatmap : heatmap trace
Notes
-----
In order to update and customize the returned figure, use
`go.Figure.update_traces` or `go.Figure.update_layout`.
If an xarray is passed, dimensions names and coordinates are used for
axes labels and ticks.
"""
args = locals()
apply_default_cascade(args)
labels = labels.copy()
nslices_facet = 1
if facet_col is not None:
if isinstance(facet_col, str):
facet_col = img.dims.index(facet_col)
nslices_facet = img.shape[facet_col]
facet_slices = range(nslices_facet)
ncols = int(facet_col_wrap) if facet_col_wrap is not None else nslices_facet
nrows = (
nslices_facet // ncols + 1
if nslices_facet % ncols
else nslices_facet // ncols
)
else:
nrows = 1
ncols = 1
if animation_frame is not None:
if isinstance(animation_frame, str):
animation_frame = img.dims.index(animation_frame)
nslices_animation = img.shape[animation_frame]
animation_slices = range(nslices_animation)
slice_dimensions = (facet_col is not None) + (
animation_frame is not None
) # 0, 1, or 2
facet_label = None
animation_label = None
img_is_xarray = False
# ----- Define x and y, set labels if img is an xarray -------------------
if xarray_imported and isinstance(img, xarray.DataArray):
dims = list(img.dims)
img_is_xarray = True
pop_indexes = []
if facet_col is not None:
facet_slices = img.coords[img.dims[facet_col]].values
pop_indexes.append(facet_col)
facet_label = img.dims[facet_col]
if animation_frame is not None:
animation_slices = img.coords[img.dims[animation_frame]].values
pop_indexes.append(animation_frame)
animation_label = img.dims[animation_frame]
# Remove indices in sorted order.
for index in sorted(pop_indexes, reverse=True):
_ = dims.pop(index)
y_label, x_label = dims[0], dims[1]
# np.datetime64 is not handled correctly by go.Heatmap
for ax in [x_label, y_label]:
if np.issubdtype(img.coords[ax].dtype, np.datetime64):
img.coords[ax] = img.coords[ax].astype(str)
if x is None:
x = img.coords[x_label].values
if y is None:
y = img.coords[y_label].values
if aspect is None:
aspect = "auto"
if labels.get("x", None) is None:
labels["x"] = x_label
if labels.get("y", None) is None:
labels["y"] = y_label
if labels.get("animation_frame", None) is None:
labels["animation_frame"] = animation_label
if labels.get("facet_col", None) is None:
labels["facet_col"] = facet_label
if labels.get("color", None) is None:
labels["color"] = xarray.plot.utils.label_from_attrs(img)
labels["color"] = labels["color"].replace("\n", "<br>")
else:
if hasattr(img, "columns") and hasattr(img.columns, "__len__"):
if x is None:
x = img.columns
if labels.get("x", None) is None and hasattr(img.columns, "name"):
labels["x"] = img.columns.name or ""
if hasattr(img, "index") and hasattr(img.index, "__len__"):
if y is None:
y = img.index
if labels.get("y", None) is None and hasattr(img.index, "name"):
labels["y"] = img.index.name or ""
if labels.get("x", None) is None:
labels["x"] = ""
if labels.get("y", None) is None:
labels["y"] = ""
if labels.get("color", None) is None:
labels["color"] = ""
if aspect is None:
aspect = "equal"
# --- Set the value of binary_string (forbidden for pandas)
img = nw.from_native(img, pass_through=True)
if isinstance(img, nw.DataFrame):
if binary_string:
raise ValueError("Binary strings cannot be used with pandas arrays")
is_dataframe = True
else:
is_dataframe = False
# --------------- Starting from here img is always a numpy array --------
img = np.asanyarray(img)
# Reshape array so that animation dimension comes first, then facets, then images
if facet_col is not None:
img = np.moveaxis(img, facet_col, 0)
if animation_frame is not None and animation_frame < facet_col:
animation_frame += 1
facet_col = True
if animation_frame is not None:
img = np.moveaxis(img, animation_frame, 0)
animation_frame = True
args["animation_frame"] = (
"animation_frame"
if labels.get("animation_frame") is None
else labels["animation_frame"]
)
iterables = ()
if animation_frame is not None:
iterables += (range(nslices_animation),)
if facet_col is not None:
iterables += (range(nslices_facet),)
# Default behaviour of binary_string: True for RGB images, False for 2D
if binary_string is None:
binary_string = img.ndim >= (3 + slice_dimensions) and not is_dataframe
# Cast bools to uint8 (also one byte)
if img.dtype == bool:
img = 255 * img.astype(np.uint8)
if range_color is not None:
zmin = range_color[0]
zmax = range_color[1]
# -------- Contrast rescaling: either minmax or infer ------------------
if contrast_rescaling is None:
contrast_rescaling = "minmax" if img.ndim == (2 + slice_dimensions) else "infer"
# We try to set zmin and zmax only if necessary, because traces have good defaults
if contrast_rescaling == "minmax":
# When using binary_string and minmax we need to set zmin and zmax to rescale the image
if (zmin is not None or binary_string) and zmax is None:
zmax = img.max()
if (zmax is not None or binary_string) and zmin is None:
zmin = img.min()
else:
# For uint8 data and infer we let zmin and zmax to be None if passed as None
if zmax is None and img.dtype != np.uint8:
zmax = _infer_zmax_from_type(img)
if zmin is None and zmax is not None:
zmin = 0
# For 2d data, use Heatmap trace, unless binary_string is True
if img.ndim == 2 + slice_dimensions and not binary_string:
y_index = slice_dimensions
if y is not None and img.shape[y_index] != len(y):
raise ValueError(
"The length of the y vector must match the length of the first "
+ "dimension of the img matrix."
)
x_index = slice_dimensions + 1
if x is not None and img.shape[x_index] != len(x):
raise ValueError(
"The length of the x vector must match the length of the second "
+ "dimension of the img matrix."
)
texttemplate = None
if text_auto is True:
texttemplate = "%{z}"
elif text_auto is not False:
texttemplate = "%{z:" + text_auto + "}"
traces = [
go.Heatmap(
x=x,
y=y,
z=img[index_tup],
coloraxis="coloraxis1",
name=str(i),
texttemplate=texttemplate,
)
for i, index_tup in enumerate(itertools.product(*iterables))
]
autorange = True if origin == "lower" else "reversed"
layout = dict(yaxis=dict(autorange=autorange))
if aspect == "equal":
layout["xaxis"] = dict(scaleanchor="y", constrain="domain")
layout["yaxis"]["constrain"] = "domain"
colorscale_validator = ColorscaleValidator("colorscale", "imshow")
layout["coloraxis1"] = dict(
colorscale=colorscale_validator.validate_coerce(
args["color_continuous_scale"]
),
cmid=color_continuous_midpoint,
cmin=zmin,
cmax=zmax,
)
if labels["color"]:
layout["coloraxis1"]["colorbar"] = dict(title_text=labels["color"])
# For 2D+RGB data, use Image trace
elif (
img.ndim >= 3
and (img.shape[-1] in [3, 4] or slice_dimensions and binary_string)
) or (img.ndim == 2 and binary_string):
rescale_image = True # to check whether image has been modified
if zmin is not None and zmax is not None:
zmin, zmax = (
_vectorize_zvalue(zmin, mode="min"),
_vectorize_zvalue(zmax, mode="max"),
)
x0, y0, dx, dy = (None,) * 4
error_msg_xarray = (
"Non-numerical coordinates were passed with xarray `img`, but "
"the Image trace cannot handle it. Please use `binary_string=False` "
"for 2D data or pass instead the numpy array `img.values` to `px.imshow`."
)
if x is not None:
x = np.asanyarray(x)
if np.issubdtype(x.dtype, np.number):
x0 = x[0]
dx = x[1] - x[0]
else:
error_msg = (
error_msg_xarray
if img_is_xarray
else (
"Only numerical values are accepted for the `x` parameter "
"when an Image trace is used."
)
)
raise ValueError(error_msg)
if y is not None:
y = np.asanyarray(y)
if np.issubdtype(y.dtype, np.number):
y0 = y[0]
dy = y[1] - y[0]
else:
error_msg = (
error_msg_xarray
if img_is_xarray
else (
"Only numerical values are accepted for the `y` parameter "
"when an Image trace is used."
)
)
raise ValueError(error_msg)
if binary_string:
if zmin is None and zmax is None: # no rescaling, faster
img_rescaled = img
rescale_image = False
elif img.ndim == 2 + slice_dimensions: # single-channel image
img_rescaled = rescale_intensity(
img, in_range=(zmin[0], zmax[0]), out_range=np.uint8
)
else:
img_rescaled = np.stack(
[
rescale_intensity(
img[..., ch],
in_range=(zmin[ch], zmax[ch]),
out_range=np.uint8,
)
for ch in range(img.shape[-1])
],
axis=-1,
)
img_str = [
image_array_to_data_uri(
img_rescaled[index_tup],
backend=binary_backend,
compression=binary_compression_level,
ext=binary_format,
)
for index_tup in itertools.product(*iterables)
]
traces = [
go.Image(source=img_str_slice, name=str(i), x0=x0, y0=y0, dx=dx, dy=dy)
for i, img_str_slice in enumerate(img_str)
]
else:
colormodel = "rgb" if img.shape[-1] == 3 else "rgba256"
traces = [
go.Image(
z=img[index_tup],
zmin=zmin,
zmax=zmax,
colormodel=colormodel,
x0=x0,
y0=y0,
dx=dx,
dy=dy,
)
for index_tup in itertools.product(*iterables)
]
layout = {}
if origin == "lower" or (dy is not None and dy < 0):
layout["yaxis"] = dict(autorange=True)
if dx is not None and dx < 0:
layout["xaxis"] = dict(autorange="reversed")
else:
raise ValueError(
"px.imshow only accepts 2D single-channel, RGB or RGBA images. "
"An image of shape %s was provided. "
"Alternatively, 3- or 4-D single or multichannel datasets can be "
"visualized using the `facet_col` or/and `animation_frame` arguments."
% str(img.shape)
)
# Now build figure
col_labels = []
if facet_col is not None:
slice_label = (
"facet_col" if labels.get("facet_col") is None else labels["facet_col"]
)
col_labels = [f"{slice_label}={i}" for i in facet_slices]
fig = init_figure(args, "xy", [], nrows, ncols, col_labels, [])
for attr_name in ["height", "width"]:
if args[attr_name]:
layout[attr_name] = args[attr_name]
if args["title"]:
layout["title_text"] = args["title"]
elif args["template"].layout.margin.t is None:
layout["margin"] = {"t": 60}
frame_list = []
for index, trace in enumerate(traces):
if (facet_col and index < nrows * ncols) or index == 0:
fig.add_trace(trace, row=nrows - index // ncols, col=index % ncols + 1)
if animation_frame is not None:
for i, index in zip(range(nslices_animation), animation_slices):
frame_list.append(
dict(
data=traces[nslices_facet * i : nslices_facet * (i + 1)],
layout=layout,
name=str(index),
)
)
if animation_frame:
fig.frames = frame_list
fig.update_layout(layout)
# Hover name, z or color
if binary_string and rescale_image and not np.all(img == img_rescaled):
# we rescaled the image, hence z is not displayed in hover since it does
# not correspond to img values
hovertemplate = "%s: %%{x}<br>%s: %%{y}<extra></extra>" % (
labels["x"] or "x",
labels["y"] or "y",
)
else:
if trace["type"] == "heatmap":
hover_name = "%{z}"
elif img.ndim == 2:
hover_name = "%{z[0]}"
elif img.ndim == 3 and img.shape[-1] == 3:
hover_name = "[%{z[0]}, %{z[1]}, %{z[2]}]"
else:
hover_name = "%{z}"
hovertemplate = "%s: %%{x}<br>%s: %%{y}<br>%s: %s<extra></extra>" % (
labels["x"] or "x",
labels["y"] or "y",
labels["color"] or "color",
hover_name,
)
fig.update_traces(hovertemplate=hovertemplate)
if labels["x"]:
fig.update_xaxes(title_text=labels["x"], row=1)
if labels["y"]:
fig.update_yaxes(title_text=labels["y"], col=1)
configure_animation_controls(args, go.Image, fig)
fig.update_layout(template=args["template"], overwrite=True)
return fig

View File

@ -0,0 +1,40 @@
class IdentityMap(object):
"""
`dict`-like object which acts as if the value for any key is the key itself. Objects
of this class can be passed in to arguments like `color_discrete_map` to
use the provided data values as colors, rather than mapping them to colors cycled
from `color_discrete_sequence`. This works for any `_map` argument to Plotly Express
functions, such as `line_dash_map` and `symbol_map`.
"""
def __getitem__(self, key):
return key
def __contains__(self, key):
return True
def copy(self):
return self
class Constant(object):
"""
Objects of this class can be passed to Plotly Express functions that expect column
identifiers or list-like objects to indicate that this attribute should take on a
constant value. An optional label can be provided.
"""
def __init__(self, value, label=None):
self.value = value
self.label = label
class Range(object):
"""
Objects of this class can be passed to Plotly Express functions that expect column
identifiers or list-like objects to indicate that this attribute should be mapped
onto integers starting at 0. An optional label can be provided.
"""
def __init__(self, label=None):
self.label = label

View File

@ -0,0 +1,52 @@
# ruff: noqa: F405
"""For a list of colors available in `plotly.express.colors`, please see
* the `tutorial on discrete color sequences <https://plotly.com/python/discrete-color/#color-sequences-in-plotly-express>`_
* the `list of built-in continuous color scales <https://plotly.com/python/builtin-colorscales/>`_
* the `tutorial on continuous colors <https://plotly.com/python/colorscales/>`_
Color scales are available within the following namespaces
* cyclical
* diverging
* qualitative
* sequential
"""
from plotly.colors import * # noqa: F403
__all__ = [
"named_colorscales",
"cyclical",
"diverging",
"sequential",
"qualitative",
"colorbrewer",
"colorbrewer",
"carto",
"cmocean",
"color_parser",
"colorscale_to_colors",
"colorscale_to_scale",
"convert_colors_to_same_type",
"convert_colorscale_to_rgb",
"convert_dict_colors_to_same_type",
"convert_to_RGB_255",
"find_intermediate_color",
"hex_to_rgb",
"label_rgb",
"make_colorscale",
"n_colors",
"unconvert_from_RGB_255",
"unlabel_rgb",
"validate_colors",
"validate_colors_dict",
"validate_colorscale",
"validate_scale_values",
"plotlyjs",
"DEFAULT_PLOTLY_COLORS",
"PLOTLY_SCALES",
"get_colorscale",
"sample_colorscale",
]

View File

@ -0,0 +1,18 @@
# ruff: noqa: F405
"""Built-in datasets for demonstration, educational and test purposes."""
from plotly.data import * # noqa: F403
__all__ = [
"carshare",
"election",
"election_geojson",
"experiment",
"gapminder",
"iris",
"medals_wide",
"medals_long",
"stocks",
"tips",
"wind",
]

View File

@ -0,0 +1,247 @@
"""Vendored code from scikit-image in order to limit the number of dependencies
Extracted from scikit-image/skimage/exposure/exposure.py
"""
import numpy as np
from warnings import warn
_integer_types = (
np.byte,
np.ubyte, # 8 bits
np.short,
np.ushort, # 16 bits
np.intc,
np.uintc, # 16 or 32 or 64 bits
np.int_,
np.uint, # 32 or 64 bits
np.longlong,
np.ulonglong,
) # 64 bits
_integer_ranges = {t: (np.iinfo(t).min, np.iinfo(t).max) for t in _integer_types}
dtype_range = {
np.bool_: (False, True),
np.float16: (-1, 1),
np.float32: (-1, 1),
np.float64: (-1, 1),
}
dtype_range.update(_integer_ranges)
DTYPE_RANGE = dtype_range.copy()
DTYPE_RANGE.update((d.__name__, limits) for d, limits in dtype_range.items())
DTYPE_RANGE.update(
{
"uint10": (0, 2**10 - 1),
"uint12": (0, 2**12 - 1),
"uint14": (0, 2**14 - 1),
"bool": dtype_range[np.bool_],
"float": dtype_range[np.float64],
}
)
def intensity_range(image, range_values="image", clip_negative=False):
"""Return image intensity range (min, max) based on desired value type.
Parameters
----------
image : array
Input image.
range_values : str or 2-tuple, optional
The image intensity range is configured by this parameter.
The possible values for this parameter are enumerated below.
'image'
Return image min/max as the range.
'dtype'
Return min/max of the image's dtype as the range.
dtype-name
Return intensity range based on desired `dtype`. Must be valid key
in `DTYPE_RANGE`. Note: `image` is ignored for this range type.
2-tuple
Return `range_values` as min/max intensities. Note that there's no
reason to use this function if you just want to specify the
intensity range explicitly. This option is included for functions
that use `intensity_range` to support all desired range types.
clip_negative : bool, optional
If True, clip the negative range (i.e. return 0 for min intensity)
even if the image dtype allows negative values.
"""
if range_values == "dtype":
range_values = image.dtype.type
if range_values == "image":
i_min = np.min(image)
i_max = np.max(image)
elif range_values in DTYPE_RANGE:
i_min, i_max = DTYPE_RANGE[range_values]
if clip_negative:
i_min = 0
else:
i_min, i_max = range_values
return i_min, i_max
def _output_dtype(dtype_or_range):
"""Determine the output dtype for rescale_intensity.
The dtype is determined according to the following rules:
- if ``dtype_or_range`` is a dtype, that is the output dtype.
- if ``dtype_or_range`` is a dtype string, that is the dtype used, unless
it is not a NumPy data type (e.g. 'uint12' for 12-bit unsigned integers),
in which case the data type that can contain it will be used
(e.g. uint16 in this case).
- if ``dtype_or_range`` is a pair of values, the output data type will be
float.
Parameters
----------
dtype_or_range : type, string, or 2-tuple of int/float
The desired range for the output, expressed as either a NumPy dtype or
as a (min, max) pair of numbers.
Returns
-------
out_dtype : type
The data type appropriate for the desired output.
"""
if type(dtype_or_range) in [list, tuple, np.ndarray]:
# pair of values: always return float.
return np.float_
if isinstance(dtype_or_range, type):
# already a type: return it
return dtype_or_range
if dtype_or_range in DTYPE_RANGE:
# string key in DTYPE_RANGE dictionary
try:
# if it's a canonical numpy dtype, convert
return np.dtype(dtype_or_range).type
except TypeError: # uint10, uint12, uint14
# otherwise, return uint16
return np.uint16
else:
raise ValueError(
"Incorrect value for out_range, should be a valid image data "
"type or a pair of values, got %s." % str(dtype_or_range)
)
def rescale_intensity(image, in_range="image", out_range="dtype"):
"""Return image after stretching or shrinking its intensity levels.
The desired intensity range of the input and output, `in_range` and
`out_range` respectively, are used to stretch or shrink the intensity range
of the input image. See examples below.
Parameters
----------
image : array
Image array.
in_range, out_range : str or 2-tuple, optional
Min and max intensity values of input and output image.
The possible values for this parameter are enumerated below.
'image'
Use image min/max as the intensity range.
'dtype'
Use min/max of the image's dtype as the intensity range.
dtype-name
Use intensity range based on desired `dtype`. Must be valid key
in `DTYPE_RANGE`.
2-tuple
Use `range_values` as explicit min/max intensities.
Returns
-------
out : array
Image array after rescaling its intensity. This image is the same dtype
as the input image.
Notes
-----
.. versionchanged:: 0.17
The dtype of the output array has changed to match the output dtype, or
float if the output range is specified by a pair of floats.
See Also
--------
equalize_hist
Examples
--------
By default, the min/max intensities of the input image are stretched to
the limits allowed by the image's dtype, since `in_range` defaults to
'image' and `out_range` defaults to 'dtype':
>>> image = np.array([51, 102, 153], dtype=np.uint8)
>>> rescale_intensity(image)
array([ 0, 127, 255], dtype=uint8)
It's easy to accidentally convert an image dtype from uint8 to float:
>>> 1.0 * image
array([ 51., 102., 153.])
Use `rescale_intensity` to rescale to the proper range for float dtypes:
>>> image_float = 1.0 * image
>>> rescale_intensity(image_float)
array([0. , 0.5, 1. ])
To maintain the low contrast of the original, use the `in_range` parameter:
>>> rescale_intensity(image_float, in_range=(0, 255))
array([0.2, 0.4, 0.6])
If the min/max value of `in_range` is more/less than the min/max image
intensity, then the intensity levels are clipped:
>>> rescale_intensity(image_float, in_range=(0, 102))
array([0.5, 1. , 1. ])
If you have an image with signed integers but want to rescale the image to
just the positive range, use the `out_range` parameter. In that case, the
output dtype will be float:
>>> image = np.array([-10, 0, 10], dtype=np.int8)
>>> rescale_intensity(image, out_range=(0, 127))
array([ 0. , 63.5, 127. ])
To get the desired range with a specific dtype, use ``.astype()``:
>>> rescale_intensity(image, out_range=(0, 127)).astype(np.int8)
array([ 0, 63, 127], dtype=int8)
If the input image is constant, the output will be clipped directly to the
output range:
>>> image = np.array([130, 130, 130], dtype=np.int32)
>>> rescale_intensity(image, out_range=(0, 127)).astype(np.int32)
array([127, 127, 127], dtype=int32)
"""
if out_range in ["dtype", "image"]:
out_dtype = _output_dtype(image.dtype.type)
else:
out_dtype = _output_dtype(out_range)
imin, imax = map(float, intensity_range(image, in_range))
omin, omax = map(
float, intensity_range(image, out_range, clip_negative=(imin >= 0))
)
if np.any(np.isnan([imin, imax, omin, omax])):
warn(
"One or more intensity levels are NaN. Rescaling will broadcast "
"NaN to the full image. Provide intensity levels yourself to "
"avoid this. E.g. with np.nanmin(image), np.nanmax(image).",
stacklevel=2,
)
image = np.clip(image, imin, imax)
if imin != imax:
image = (image - imin) / (imax - imin)
return np.asarray(image * (omax - omin) + omin, dtype=out_dtype)
else:
return np.clip(image, omin, omax).astype(out_dtype)

View File

@ -0,0 +1,170 @@
"""
The `trendline_functions` module contains functions which are called by Plotly Express
when the `trendline` argument is used. Valid values for `trendline` are the names of the
functions in this module, and the value of the `trendline_options` argument to PX
functions is passed in as the first argument to these functions when called.
Note that the functions in this module are not meant to be called directly, and are
exposed as part of the public API for documentation purposes.
"""
__all__ = ["ols", "lowess", "rolling", "ewm", "expanding"]
def ols(trendline_options, x_raw, x, y, x_label, y_label, non_missing):
"""Ordinary Least Squares (OLS) trendline function
Requires `statsmodels` to be installed.
This trendline function causes fit results to be stored within the figure,
accessible via the `plotly.express.get_trendline_results` function. The fit results
are the output of the `statsmodels.api.OLS` function.
Valid keys for the `trendline_options` dict are:
- `add_constant` (`bool`, default `True`): if `False`, the trendline passes through
the origin but if `True` a y-intercept is fitted.
- `log_x` and `log_y` (`bool`, default `False`): if `True` the OLS is computed with
respect to the base 10 logarithm of the input. Note that this means no zeros can
be present in the input.
"""
import numpy as np
valid_options = ["add_constant", "log_x", "log_y"]
for k in trendline_options.keys():
if k not in valid_options:
raise ValueError(
"OLS trendline_options keys must be one of [%s] but got '%s'"
% (", ".join(valid_options), k)
)
import statsmodels.api as sm
add_constant = trendline_options.get("add_constant", True)
log_x = trendline_options.get("log_x", False)
log_y = trendline_options.get("log_y", False)
if log_y:
if np.any(y <= 0):
raise ValueError(
"Can't do OLS trendline with `log_y=True` when `y` contains non-positive values."
)
y = np.log10(y)
y_label = "log10(%s)" % y_label
if log_x:
if np.any(x <= 0):
raise ValueError(
"Can't do OLS trendline with `log_x=True` when `x` contains non-positive values."
)
x = np.log10(x)
x_label = "log10(%s)" % x_label
if add_constant:
x = sm.add_constant(x)
fit_results = sm.OLS(y, x, missing="drop").fit()
y_out = fit_results.predict()
if log_y:
y_out = np.power(10, y_out)
hover_header = "<b>OLS trendline</b><br>"
if len(fit_results.params) == 2:
hover_header += "%s = %g * %s + %g<br>" % (
y_label,
fit_results.params[1],
x_label,
fit_results.params[0],
)
elif not add_constant:
hover_header += "%s = %g * %s<br>" % (y_label, fit_results.params[0], x_label)
else:
hover_header += "%s = %g<br>" % (y_label, fit_results.params[0])
hover_header += "R<sup>2</sup>=%f<br><br>" % fit_results.rsquared
return y_out, hover_header, fit_results
def lowess(trendline_options, x_raw, x, y, x_label, y_label, non_missing):
"""LOcally WEighted Scatterplot Smoothing (LOWESS) trendline function
Requires `statsmodels` to be installed.
Valid keys for the `trendline_options` dict are:
- `frac` (`float`, default `0.6666666`): the `frac` parameter from the
`statsmodels.api.nonparametric.lowess` function
"""
valid_options = ["frac"]
for k in trendline_options.keys():
if k not in valid_options:
raise ValueError(
"LOWESS trendline_options keys must be one of [%s] but got '%s'"
% (", ".join(valid_options), k)
)
import statsmodels.api as sm
frac = trendline_options.get("frac", 0.6666666)
y_out = sm.nonparametric.lowess(y, x, missing="drop", frac=frac)[:, 1]
hover_header = "<b>LOWESS trendline</b><br><br>"
return y_out, hover_header, None
def _pandas(mode, trendline_options, x_raw, y, non_missing):
import numpy as np
try:
import pandas as pd
except ImportError:
msg = "Trendline requires pandas to be installed"
raise ImportError(msg)
modes = dict(rolling="Rolling", ewm="Exponentially Weighted", expanding="Expanding")
trendline_options = trendline_options.copy()
function_name = trendline_options.pop("function", "mean")
function_args = trendline_options.pop("function_args", dict())
series = pd.Series(np.copy(y), index=x_raw.to_pandas())
# TODO: Narwhals Series/DataFrame do not support rolling, ewm nor expanding, therefore
# it fallbacks to pandas Series independently of the original type.
# Plotly issue: https://github.com/plotly/plotly.py/issues/4834
# Narwhals issue: https://github.com/narwhals-dev/narwhals/issues/1254
agg = getattr(series, mode) # e.g. series.rolling
agg_obj = agg(**trendline_options) # e.g. series.rolling(**opts)
function = getattr(agg_obj, function_name) # e.g. series.rolling(**opts).mean
y_out = function(**function_args) # e.g. series.rolling(**opts).mean(**opts)
y_out = y_out[non_missing]
hover_header = "<b>%s %s trendline</b><br><br>" % (modes[mode], function_name)
return y_out, hover_header, None
def rolling(trendline_options, x_raw, x, y, x_label, y_label, non_missing):
"""Rolling trendline function
The value of the `function` key of the `trendline_options` dict is the function to
use (defaults to `mean`) and the value of the `function_args` key are taken to be
its arguments as a dict. The remainder of the `trendline_options` dict is passed as
keyword arguments into the `pandas.Series.rolling` function.
"""
return _pandas("rolling", trendline_options, x_raw, y, non_missing)
def expanding(trendline_options, x_raw, x, y, x_label, y_label, non_missing):
"""Expanding trendline function
The value of the `function` key of the `trendline_options` dict is the function to
use (defaults to `mean`) and the value of the `function_args` key are taken to be
its arguments as a dict. The remainder of the `trendline_options` dict is passed as
keyword arguments into the `pandas.Series.expanding` function.
"""
return _pandas("expanding", trendline_options, x_raw, y, non_missing)
def ewm(trendline_options, x_raw, x, y, x_label, y_label, non_missing):
"""Exponentially Weighted Moment (EWM) trendline function
The value of the `function` key of the `trendline_options` dict is the function to
use (defaults to `mean`) and the value of the `function_args` key are taken to be
its arguments as a dict. The remainder of the `trendline_options` dict is passed as
keyword arguments into the `pandas.Series.ewm` function.
"""
return _pandas("ewm", trendline_options, x_raw, y, non_missing)

View File

@ -0,0 +1,155 @@
from numbers import Number
import plotly.exceptions
import plotly.colors as clrs
from plotly.graph_objs import graph_objs
def make_linear_colorscale(colors):
"""
Makes a list of colors into a colorscale-acceptable form
For documentation regarding to the form of the output, see
https://plot.ly/python/reference/#mesh3d-colorscale
"""
scale = 1.0 / (len(colors) - 1)
return [[i * scale, color] for i, color in enumerate(colors)]
def create_2d_density(
x,
y,
colorscale="Earth",
ncontours=20,
hist_color=(0, 0, 0.5),
point_color=(0, 0, 0.5),
point_size=2,
title="2D Density Plot",
height=600,
width=600,
):
"""
**deprecated**, use instead
:func:`plotly.express.density_heatmap`.
:param (list|array) x: x-axis data for plot generation
:param (list|array) y: y-axis data for plot generation
:param (str|tuple|list) colorscale: either a plotly scale name, an rgb
or hex color, a color tuple or a list or tuple of colors. An rgb
color is of the form 'rgb(x, y, z)' where x, y, z belong to the
interval [0, 255] and a color tuple is a tuple of the form
(a, b, c) where a, b and c belong to [0, 1]. If colormap is a
list, it must contain the valid color types aforementioned as its
members.
:param (int) ncontours: the number of 2D contours to draw on the plot
:param (str) hist_color: the color of the plotted histograms
:param (str) point_color: the color of the scatter points
:param (str) point_size: the color of the scatter points
:param (str) title: set the title for the plot
:param (float) height: the height of the chart
:param (float) width: the width of the chart
Examples
--------
Example 1: Simple 2D Density Plot
>>> from plotly.figure_factory import create_2d_density
>>> import numpy as np
>>> # Make data points
>>> t = np.linspace(-1,1.2,2000)
>>> x = (t**3)+(0.3*np.random.randn(2000))
>>> y = (t**6)+(0.3*np.random.randn(2000))
>>> # Create a figure
>>> fig = create_2d_density(x, y)
>>> # Plot the data
>>> fig.show()
Example 2: Using Parameters
>>> from plotly.figure_factory import create_2d_density
>>> import numpy as np
>>> # Make data points
>>> t = np.linspace(-1,1.2,2000)
>>> x = (t**3)+(0.3*np.random.randn(2000))
>>> y = (t**6)+(0.3*np.random.randn(2000))
>>> # Create custom colorscale
>>> colorscale = ['#7A4579', '#D56073', 'rgb(236,158,105)',
... (1, 1, 0.2), (0.98,0.98,0.98)]
>>> # Create a figure
>>> fig = create_2d_density(x, y, colorscale=colorscale,
... hist_color='rgb(255, 237, 222)', point_size=3)
>>> # Plot the data
>>> fig.show()
"""
# validate x and y are filled with numbers only
for array in [x, y]:
if not all(isinstance(element, Number) for element in array):
raise plotly.exceptions.PlotlyError(
"All elements of your 'x' and 'y' lists must be numbers."
)
# validate x and y are the same length
if len(x) != len(y):
raise plotly.exceptions.PlotlyError(
"Both lists 'x' and 'y' must be the same length."
)
colorscale = clrs.validate_colors(colorscale, "rgb")
colorscale = make_linear_colorscale(colorscale)
# validate hist_color and point_color
hist_color = clrs.validate_colors(hist_color, "rgb")
point_color = clrs.validate_colors(point_color, "rgb")
trace1 = graph_objs.Scatter(
x=x,
y=y,
mode="markers",
name="points",
marker=dict(color=point_color[0], size=point_size, opacity=0.4),
)
trace2 = graph_objs.Histogram2dContour(
x=x,
y=y,
name="density",
ncontours=ncontours,
colorscale=colorscale,
reversescale=True,
showscale=False,
)
trace3 = graph_objs.Histogram(
x=x, name="x density", marker=dict(color=hist_color[0]), yaxis="y2"
)
trace4 = graph_objs.Histogram(
y=y, name="y density", marker=dict(color=hist_color[0]), xaxis="x2"
)
data = [trace1, trace2, trace3, trace4]
layout = graph_objs.Layout(
showlegend=False,
autosize=False,
title=title,
height=height,
width=width,
xaxis=dict(domain=[0, 0.85], showgrid=False, zeroline=False),
yaxis=dict(domain=[0, 0.85], showgrid=False, zeroline=False),
margin=dict(t=50),
hovermode="closest",
bargap=0,
xaxis2=dict(domain=[0.85, 1], showgrid=False, zeroline=False),
yaxis2=dict(domain=[0.85, 1], showgrid=False, zeroline=False),
)
fig = graph_objs.Figure(data=data, layout=layout)
return fig

View File

@ -0,0 +1,69 @@
# ruff: noqa: E402
from plotly import optional_imports
# Require that numpy exists for figure_factory
np = optional_imports.get_module("numpy")
if np is None:
raise ImportError(
"""\
The figure factory module requires the numpy package"""
)
from plotly.figure_factory._2d_density import create_2d_density
from plotly.figure_factory._annotated_heatmap import create_annotated_heatmap
from plotly.figure_factory._bullet import create_bullet
from plotly.figure_factory._candlestick import create_candlestick
from plotly.figure_factory._dendrogram import create_dendrogram
from plotly.figure_factory._distplot import create_distplot
from plotly.figure_factory._facet_grid import create_facet_grid
from plotly.figure_factory._gantt import create_gantt
from plotly.figure_factory._ohlc import create_ohlc
from plotly.figure_factory._quiver import create_quiver
from plotly.figure_factory._scatterplot import create_scatterplotmatrix
from plotly.figure_factory._streamline import create_streamline
from plotly.figure_factory._table import create_table
from plotly.figure_factory._trisurf import create_trisurf
from plotly.figure_factory._violin import create_violin
if optional_imports.get_module("pandas") is not None:
from plotly.figure_factory._county_choropleth import create_choropleth
from plotly.figure_factory._hexbin_mapbox import create_hexbin_mapbox
else:
def create_choropleth(*args, **kwargs):
raise ImportError("Please install pandas to use `create_choropleth`")
def create_hexbin_mapbox(*args, **kwargs):
raise ImportError("Please install pandas to use `create_hexbin_mapbox`")
if optional_imports.get_module("skimage") is not None:
from plotly.figure_factory._ternary_contour import create_ternary_contour
else:
def create_ternary_contour(*args, **kwargs):
raise ImportError("Please install scikit-image to use `create_ternary_contour`")
__all__ = [
"create_2d_density",
"create_annotated_heatmap",
"create_bullet",
"create_candlestick",
"create_choropleth",
"create_dendrogram",
"create_distplot",
"create_facet_grid",
"create_gantt",
"create_hexbin_mapbox",
"create_ohlc",
"create_quiver",
"create_scatterplotmatrix",
"create_streamline",
"create_table",
"create_ternary_contour",
"create_trisurf",
"create_violin",
]

View File

@ -0,0 +1,307 @@
import plotly.colors as clrs
from plotly import exceptions, optional_imports
from plotly.figure_factory import utils
from plotly.graph_objs import graph_objs
from plotly.validator_cache import ValidatorCache
# Optional imports, may be None for users that only use our core functionality.
np = optional_imports.get_module("numpy")
def validate_annotated_heatmap(z, x, y, annotation_text):
"""
Annotated-heatmap-specific validations
Check that if a text matrix is supplied, it has the same
dimensions as the z matrix.
See FigureFactory.create_annotated_heatmap() for params
:raises: (PlotlyError) If z and text matrices do not have the same
dimensions.
"""
if annotation_text is not None and isinstance(annotation_text, list):
utils.validate_equal_length(z, annotation_text)
for lst in range(len(z)):
if len(z[lst]) != len(annotation_text[lst]):
raise exceptions.PlotlyError(
"z and text should have the same dimensions"
)
if x:
if len(x) != len(z[0]):
raise exceptions.PlotlyError(
"oops, the x list that you "
"provided does not match the "
"width of your z matrix "
)
if y:
if len(y) != len(z):
raise exceptions.PlotlyError(
"oops, the y list that you "
"provided does not match the "
"length of your z matrix "
)
def create_annotated_heatmap(
z,
x=None,
y=None,
annotation_text=None,
colorscale="Plasma",
font_colors=None,
showscale=False,
reversescale=False,
**kwargs,
):
"""
**deprecated**, use instead
:func:`plotly.express.imshow`.
Function that creates annotated heatmaps
This function adds annotations to each cell of the heatmap.
:param (list[list]|ndarray) z: z matrix to create heatmap.
:param (list) x: x axis labels.
:param (list) y: y axis labels.
:param (list[list]|ndarray) annotation_text: Text strings for
annotations. Should have the same dimensions as the z matrix. If no
text is added, the values of the z matrix are annotated. Default =
z matrix values.
:param (list|str) colorscale: heatmap colorscale.
:param (list) font_colors: List of two color strings: [min_text_color,
max_text_color] where min_text_color is applied to annotations for
heatmap values < (max_value - min_value)/2. If font_colors is not
defined, the colors are defined logically as black or white
depending on the heatmap's colorscale.
:param (bool) showscale: Display colorscale. Default = False
:param (bool) reversescale: Reverse colorscale. Default = False
:param kwargs: kwargs passed through plotly.graph_objs.Heatmap.
These kwargs describe other attributes about the annotated Heatmap
trace such as the colorscale. For more information on valid kwargs
call help(plotly.graph_objs.Heatmap)
Example 1: Simple annotated heatmap with default configuration
>>> import plotly.figure_factory as ff
>>> z = [[0.300000, 0.00000, 0.65, 0.300000],
... [1, 0.100005, 0.45, 0.4300],
... [0.300000, 0.00000, 0.65, 0.300000],
... [1, 0.100005, 0.45, 0.00000]]
>>> fig = ff.create_annotated_heatmap(z)
>>> fig.show()
"""
# Avoiding mutables in the call signature
font_colors = font_colors if font_colors is not None else []
validate_annotated_heatmap(z, x, y, annotation_text)
# validate colorscale
colorscale_validator = ValidatorCache.get_validator("heatmap", "colorscale")
colorscale = colorscale_validator.validate_coerce(colorscale)
annotations = _AnnotatedHeatmap(
z, x, y, annotation_text, colorscale, font_colors, reversescale, **kwargs
).make_annotations()
if x or y:
trace = dict(
type="heatmap",
z=z,
x=x,
y=y,
colorscale=colorscale,
showscale=showscale,
reversescale=reversescale,
**kwargs,
)
layout = dict(
annotations=annotations,
xaxis=dict(ticks="", dtick=1, side="top", gridcolor="rgb(0, 0, 0)"),
yaxis=dict(ticks="", dtick=1, ticksuffix=" "),
)
else:
trace = dict(
type="heatmap",
z=z,
colorscale=colorscale,
showscale=showscale,
reversescale=reversescale,
**kwargs,
)
layout = dict(
annotations=annotations,
xaxis=dict(
ticks="", side="top", gridcolor="rgb(0, 0, 0)", showticklabels=False
),
yaxis=dict(ticks="", ticksuffix=" ", showticklabels=False),
)
data = [trace]
return graph_objs.Figure(data=data, layout=layout)
def to_rgb_color_list(color_str, default):
color_str = color_str.strip()
if color_str.startswith("rgb"):
return [int(v) for v in color_str.strip("rgba()").split(",")]
elif color_str.startswith("#"):
return clrs.hex_to_rgb(color_str)
else:
return default
def should_use_black_text(background_color):
return (
background_color[0] * 0.299
+ background_color[1] * 0.587
+ background_color[2] * 0.114
) > 186
class _AnnotatedHeatmap(object):
"""
Refer to TraceFactory.create_annotated_heatmap() for docstring
"""
def __init__(
self, z, x, y, annotation_text, colorscale, font_colors, reversescale, **kwargs
):
self.z = z
if x:
self.x = x
else:
self.x = range(len(z[0]))
if y:
self.y = y
else:
self.y = range(len(z))
if annotation_text is not None:
self.annotation_text = annotation_text
else:
self.annotation_text = self.z
self.colorscale = colorscale
self.reversescale = reversescale
self.font_colors = font_colors
if np and isinstance(self.z, np.ndarray):
self.zmin = np.amin(self.z)
self.zmax = np.amax(self.z)
else:
self.zmin = min([v for row in self.z for v in row])
self.zmax = max([v for row in self.z for v in row])
if kwargs.get("zmin", None) is not None:
self.zmin = kwargs["zmin"]
if kwargs.get("zmax", None) is not None:
self.zmax = kwargs["zmax"]
self.zmid = (self.zmax + self.zmin) / 2
if kwargs.get("zmid", None) is not None:
self.zmid = kwargs["zmid"]
def get_text_color(self):
"""
Get font color for annotations.
The annotated heatmap can feature two text colors: min_text_color and
max_text_color. The min_text_color is applied to annotations for
heatmap values < (max_value - min_value)/2. The user can define these
two colors. Otherwise the colors are defined logically as black or
white depending on the heatmap's colorscale.
:rtype (string, string) min_text_color, max_text_color: text
color for annotations for heatmap values <
(max_value - min_value)/2 and text color for annotations for
heatmap values >= (max_value - min_value)/2
"""
# Plotly colorscales ranging from a lighter shade to a darker shade
colorscales = [
"Greys",
"Greens",
"Blues",
"YIGnBu",
"YIOrRd",
"RdBu",
"Picnic",
"Jet",
"Hot",
"Blackbody",
"Earth",
"Electric",
"Viridis",
"Cividis",
]
# Plotly colorscales ranging from a darker shade to a lighter shade
colorscales_reverse = ["Reds"]
white = "#FFFFFF"
black = "#000000"
if self.font_colors:
min_text_color = self.font_colors[0]
max_text_color = self.font_colors[-1]
elif self.colorscale in colorscales and self.reversescale:
min_text_color = black
max_text_color = white
elif self.colorscale in colorscales:
min_text_color = white
max_text_color = black
elif self.colorscale in colorscales_reverse and self.reversescale:
min_text_color = white
max_text_color = black
elif self.colorscale in colorscales_reverse:
min_text_color = black
max_text_color = white
elif isinstance(self.colorscale, list):
min_col = to_rgb_color_list(self.colorscale[0][1], [255, 255, 255])
max_col = to_rgb_color_list(self.colorscale[-1][1], [255, 255, 255])
# swap min/max colors if reverse scale
if self.reversescale:
min_col, max_col = max_col, min_col
if should_use_black_text(min_col):
min_text_color = black
else:
min_text_color = white
if should_use_black_text(max_col):
max_text_color = black
else:
max_text_color = white
else:
min_text_color = black
max_text_color = black
return min_text_color, max_text_color
def make_annotations(self):
"""
Get annotations for each cell of the heatmap with graph_objs.Annotation
:rtype (list[dict]) annotations: list of annotations for each cell of
the heatmap
"""
min_text_color, max_text_color = _AnnotatedHeatmap.get_text_color(self)
annotations = []
for n, row in enumerate(self.z):
for m, val in enumerate(row):
font_color = min_text_color if val < self.zmid else max_text_color
annotations.append(
graph_objs.layout.Annotation(
text=str(self.annotation_text[n][m]),
x=self.x[m],
y=self.y[n],
xref="x1",
yref="y1",
font=dict(color=font_color),
showarrow=False,
)
)
return annotations

View File

@ -0,0 +1,366 @@
import math
from plotly import exceptions, optional_imports
import plotly.colors as clrs
from plotly.figure_factory import utils
import plotly
import plotly.graph_objs as go
pd = optional_imports.get_module("pandas")
def _bullet(
df,
markers,
measures,
ranges,
subtitles,
titles,
orientation,
range_colors,
measure_colors,
horizontal_spacing,
vertical_spacing,
scatter_options,
layout_options,
):
num_of_lanes = len(df)
num_of_rows = num_of_lanes if orientation == "h" else 1
num_of_cols = 1 if orientation == "h" else num_of_lanes
if not horizontal_spacing:
horizontal_spacing = 1.0 / num_of_lanes
if not vertical_spacing:
vertical_spacing = 1.0 / num_of_lanes
fig = plotly.subplots.make_subplots(
num_of_rows,
num_of_cols,
print_grid=False,
horizontal_spacing=horizontal_spacing,
vertical_spacing=vertical_spacing,
)
# layout
fig["layout"].update(
dict(shapes=[]),
title="Bullet Chart",
height=600,
width=1000,
showlegend=False,
barmode="stack",
annotations=[],
margin=dict(l=120 if orientation == "h" else 80),
)
# update layout
fig["layout"].update(layout_options)
if orientation == "h":
width_axis = "yaxis"
length_axis = "xaxis"
else:
width_axis = "xaxis"
length_axis = "yaxis"
for key in fig["layout"]:
if "xaxis" in key or "yaxis" in key:
fig["layout"][key]["showgrid"] = False
fig["layout"][key]["zeroline"] = False
if length_axis in key:
fig["layout"][key]["tickwidth"] = 1
if width_axis in key:
fig["layout"][key]["showticklabels"] = False
fig["layout"][key]["range"] = [0, 1]
# narrow domain if 1 bar
if num_of_lanes <= 1:
fig["layout"][width_axis + "1"]["domain"] = [0.4, 0.6]
if not range_colors:
range_colors = ["rgb(200, 200, 200)", "rgb(245, 245, 245)"]
if not measure_colors:
measure_colors = ["rgb(31, 119, 180)", "rgb(176, 196, 221)"]
for row in range(num_of_lanes):
# ranges bars
for idx in range(len(df.iloc[row]["ranges"])):
inter_colors = clrs.n_colors(
range_colors[0], range_colors[1], len(df.iloc[row]["ranges"]), "rgb"
)
x = (
[sorted(df.iloc[row]["ranges"])[-1 - idx]]
if orientation == "h"
else [0]
)
y = (
[0]
if orientation == "h"
else [sorted(df.iloc[row]["ranges"])[-1 - idx]]
)
bar = go.Bar(
x=x,
y=y,
marker=dict(color=inter_colors[-1 - idx]),
name="ranges",
hoverinfo="x" if orientation == "h" else "y",
orientation=orientation,
width=2,
base=0,
xaxis="x{}".format(row + 1),
yaxis="y{}".format(row + 1),
)
fig.add_trace(bar)
# measures bars
for idx in range(len(df.iloc[row]["measures"])):
inter_colors = clrs.n_colors(
measure_colors[0],
measure_colors[1],
len(df.iloc[row]["measures"]),
"rgb",
)
x = (
[sorted(df.iloc[row]["measures"])[-1 - idx]]
if orientation == "h"
else [0.5]
)
y = (
[0.5]
if orientation == "h"
else [sorted(df.iloc[row]["measures"])[-1 - idx]]
)
bar = go.Bar(
x=x,
y=y,
marker=dict(color=inter_colors[-1 - idx]),
name="measures",
hoverinfo="x" if orientation == "h" else "y",
orientation=orientation,
width=0.4,
base=0,
xaxis="x{}".format(row + 1),
yaxis="y{}".format(row + 1),
)
fig.add_trace(bar)
# markers
x = df.iloc[row]["markers"] if orientation == "h" else [0.5]
y = [0.5] if orientation == "h" else df.iloc[row]["markers"]
markers = go.Scatter(
x=x,
y=y,
name="markers",
hoverinfo="x" if orientation == "h" else "y",
xaxis="x{}".format(row + 1),
yaxis="y{}".format(row + 1),
**scatter_options,
)
fig.add_trace(markers)
# titles and subtitles
title = df.iloc[row]["titles"]
if "subtitles" in df:
subtitle = "<br>{}".format(df.iloc[row]["subtitles"])
else:
subtitle = ""
label = "<b>{}</b>".format(title) + subtitle
annot = utils.annotation_dict_for_label(
label,
(num_of_lanes - row if orientation == "h" else row + 1),
num_of_lanes,
vertical_spacing if orientation == "h" else horizontal_spacing,
"row" if orientation == "h" else "col",
True if orientation == "h" else False,
False,
)
fig["layout"]["annotations"] += (annot,)
return fig
def create_bullet(
data,
markers=None,
measures=None,
ranges=None,
subtitles=None,
titles=None,
orientation="h",
range_colors=("rgb(200, 200, 200)", "rgb(245, 245, 245)"),
measure_colors=("rgb(31, 119, 180)", "rgb(176, 196, 221)"),
horizontal_spacing=None,
vertical_spacing=None,
scatter_options={},
**layout_options,
):
"""
**deprecated**, use instead the plotly.graph_objects trace
:class:`plotly.graph_objects.Indicator`.
:param (pd.DataFrame | list | tuple) data: either a list/tuple of
dictionaries or a pandas DataFrame.
:param (str) markers: the column name or dictionary key for the markers in
each subplot.
:param (str) measures: the column name or dictionary key for the measure
bars in each subplot. This bar usually represents the quantitative
measure of performance, usually a list of two values [a, b] and are
the blue bars in the foreground of each subplot by default.
:param (str) ranges: the column name or dictionary key for the qualitative
ranges of performance, usually a 3-item list [bad, okay, good]. They
correspond to the grey bars in the background of each chart.
:param (str) subtitles: the column name or dictionary key for the subtitle
of each subplot chart. The subplots are displayed right underneath
each title.
:param (str) titles: the column name or dictionary key for the main label
of each subplot chart.
:param (bool) orientation: if 'h', the bars are placed horizontally as
rows. If 'v' the bars are placed vertically in the chart.
:param (list) range_colors: a tuple of two colors between which all
the rectangles for the range are drawn. These rectangles are meant to
be qualitative indicators against which the marker and measure bars
are compared.
Default=('rgb(200, 200, 200)', 'rgb(245, 245, 245)')
:param (list) measure_colors: a tuple of two colors which is used to color
the thin quantitative bars in the bullet chart.
Default=('rgb(31, 119, 180)', 'rgb(176, 196, 221)')
:param (float) horizontal_spacing: see the 'horizontal_spacing' param in
plotly.tools.make_subplots. Ranges between 0 and 1.
:param (float) vertical_spacing: see the 'vertical_spacing' param in
plotly.tools.make_subplots. Ranges between 0 and 1.
:param (dict) scatter_options: describes attributes for the scatter trace
in each subplot such as name and marker size. Call
help(plotly.graph_objs.Scatter) for more information on valid params.
:param layout_options: describes attributes for the layout of the figure
such as title, height and width. Call help(plotly.graph_objs.Layout)
for more information on valid params.
Example 1: Use a Dictionary
>>> import plotly.figure_factory as ff
>>> data = [
... {"label": "revenue", "sublabel": "us$, in thousands",
... "range": [150, 225, 300], "performance": [220,270], "point": [250]},
... {"label": "Profit", "sublabel": "%", "range": [20, 25, 30],
... "performance": [21, 23], "point": [26]},
... {"label": "Order Size", "sublabel":"US$, average","range": [350, 500, 600],
... "performance": [100,320],"point": [550]},
... {"label": "New Customers", "sublabel": "count", "range": [1400, 2000, 2500],
... "performance": [1000, 1650],"point": [2100]},
... {"label": "Satisfaction", "sublabel": "out of 5","range": [3.5, 4.25, 5],
... "performance": [3.2, 4.7], "point": [4.4]}
... ]
>>> fig = ff.create_bullet(
... data, titles='label', subtitles='sublabel', markers='point',
... measures='performance', ranges='range', orientation='h',
... title='my simple bullet chart'
... )
>>> fig.show()
Example 2: Use a DataFrame with Custom Colors
>>> import plotly.figure_factory as ff
>>> import pandas as pd
>>> data = pd.read_json('https://cdn.rawgit.com/plotly/datasets/master/BulletData.json')
>>> fig = ff.create_bullet(
... data, titles='title', markers='markers', measures='measures',
... orientation='v', measure_colors=['rgb(14, 52, 75)', 'rgb(31, 141, 127)'],
... scatter_options={'marker': {'symbol': 'circle'}}, width=700)
>>> fig.show()
"""
# validate df
if not pd:
raise ImportError("'pandas' must be installed for this figure factory.")
if utils.is_sequence(data):
if not all(isinstance(item, dict) for item in data):
raise exceptions.PlotlyError(
"Every entry of the data argument list, tuple, etc must "
"be a dictionary."
)
elif not isinstance(data, pd.DataFrame):
raise exceptions.PlotlyError(
"You must input a pandas DataFrame, or a list of dictionaries."
)
# make DataFrame from data with correct column headers
col_names = ["titles", "subtitle", "markers", "measures", "ranges"]
if utils.is_sequence(data):
df = pd.DataFrame(
[
[d[titles] for d in data] if titles else [""] * len(data),
[d[subtitles] for d in data] if subtitles else [""] * len(data),
[d[markers] for d in data] if markers else [[]] * len(data),
[d[measures] for d in data] if measures else [[]] * len(data),
[d[ranges] for d in data] if ranges else [[]] * len(data),
],
index=col_names,
)
elif isinstance(data, pd.DataFrame):
df = pd.DataFrame(
[
data[titles].tolist() if titles else [""] * len(data),
data[subtitles].tolist() if subtitles else [""] * len(data),
data[markers].tolist() if markers else [[]] * len(data),
data[measures].tolist() if measures else [[]] * len(data),
data[ranges].tolist() if ranges else [[]] * len(data),
],
index=col_names,
)
df = pd.DataFrame.transpose(df)
# make sure ranges, measures, 'markers' are not NAN or NONE
for needed_key in ["ranges", "measures", "markers"]:
for idx, r in enumerate(df[needed_key]):
try:
r_is_nan = math.isnan(r)
if r_is_nan or r is None:
df[needed_key][idx] = []
except TypeError:
pass
# validate custom colors
for colors_list in [range_colors, measure_colors]:
if colors_list:
if len(colors_list) != 2:
raise exceptions.PlotlyError(
"Both 'range_colors' or 'measure_colors' must be a list "
"of two valid colors."
)
clrs.validate_colors(colors_list)
colors_list = clrs.convert_colors_to_same_type(colors_list, "rgb")[0]
# default scatter options
default_scatter = {
"marker": {"size": 12, "symbol": "diamond-tall", "color": "rgb(0, 0, 0)"}
}
if scatter_options == {}:
scatter_options.update(default_scatter)
else:
# add default options to scatter_options if they are not present
for k in default_scatter["marker"]:
if k not in scatter_options["marker"]:
scatter_options["marker"][k] = default_scatter["marker"][k]
fig = _bullet(
df,
markers,
measures,
ranges,
subtitles,
titles,
orientation,
range_colors,
measure_colors,
horizontal_spacing,
vertical_spacing,
scatter_options,
layout_options,
)
return fig

View File

@ -0,0 +1,277 @@
from plotly.figure_factory import utils
from plotly.figure_factory._ohlc import (
_DEFAULT_INCREASING_COLOR,
_DEFAULT_DECREASING_COLOR,
validate_ohlc,
)
from plotly.graph_objs import graph_objs
def make_increasing_candle(open, high, low, close, dates, **kwargs):
"""
Makes boxplot trace for increasing candlesticks
_make_increasing_candle() and _make_decreasing_candle separate the
increasing traces from the decreasing traces so kwargs (such as
color) can be passed separately to increasing or decreasing traces
when direction is set to 'increasing' or 'decreasing' in
FigureFactory.create_candlestick()
:param (list) open: opening values
:param (list) high: high values
:param (list) low: low values
:param (list) close: closing values
:param (list) dates: list of datetime objects. Default: None
:param kwargs: kwargs to be passed to increasing trace via
plotly.graph_objs.Scatter.
:rtype (list) candle_incr_data: list of the box trace for
increasing candlesticks.
"""
increase_x, increase_y = _Candlestick(
open, high, low, close, dates, **kwargs
).get_candle_increase()
if "line" in kwargs:
kwargs.setdefault("fillcolor", kwargs["line"]["color"])
else:
kwargs.setdefault("fillcolor", _DEFAULT_INCREASING_COLOR)
if "name" in kwargs:
kwargs.setdefault("showlegend", True)
else:
kwargs.setdefault("showlegend", False)
kwargs.setdefault("name", "Increasing")
kwargs.setdefault("line", dict(color=_DEFAULT_INCREASING_COLOR))
candle_incr_data = dict(
type="box",
x=increase_x,
y=increase_y,
whiskerwidth=0,
boxpoints=False,
**kwargs,
)
return [candle_incr_data]
def make_decreasing_candle(open, high, low, close, dates, **kwargs):
"""
Makes boxplot trace for decreasing candlesticks
:param (list) open: opening values
:param (list) high: high values
:param (list) low: low values
:param (list) close: closing values
:param (list) dates: list of datetime objects. Default: None
:param kwargs: kwargs to be passed to decreasing trace via
plotly.graph_objs.Scatter.
:rtype (list) candle_decr_data: list of the box trace for
decreasing candlesticks.
"""
decrease_x, decrease_y = _Candlestick(
open, high, low, close, dates, **kwargs
).get_candle_decrease()
if "line" in kwargs:
kwargs.setdefault("fillcolor", kwargs["line"]["color"])
else:
kwargs.setdefault("fillcolor", _DEFAULT_DECREASING_COLOR)
kwargs.setdefault("showlegend", False)
kwargs.setdefault("line", dict(color=_DEFAULT_DECREASING_COLOR))
kwargs.setdefault("name", "Decreasing")
candle_decr_data = dict(
type="box",
x=decrease_x,
y=decrease_y,
whiskerwidth=0,
boxpoints=False,
**kwargs,
)
return [candle_decr_data]
def create_candlestick(open, high, low, close, dates=None, direction="both", **kwargs):
"""
**deprecated**, use instead the plotly.graph_objects trace
:class:`plotly.graph_objects.Candlestick`
:param (list) open: opening values
:param (list) high: high values
:param (list) low: low values
:param (list) close: closing values
:param (list) dates: list of datetime objects. Default: None
:param (string) direction: direction can be 'increasing', 'decreasing',
or 'both'. When the direction is 'increasing', the returned figure
consists of all candlesticks where the close value is greater than
the corresponding open value, and when the direction is
'decreasing', the returned figure consists of all candlesticks
where the close value is less than or equal to the corresponding
open value. When the direction is 'both', both increasing and
decreasing candlesticks are returned. Default: 'both'
:param kwargs: kwargs passed through plotly.graph_objs.Scatter.
These kwargs describe other attributes about the ohlc Scatter trace
such as the color or the legend name. For more information on valid
kwargs call help(plotly.graph_objs.Scatter)
:rtype (dict): returns a representation of candlestick chart figure.
Example 1: Simple candlestick chart from a Pandas DataFrame
>>> from plotly.figure_factory import create_candlestick
>>> from datetime import datetime
>>> import pandas as pd
>>> df = pd.read_csv('https://raw.githubusercontent.com/plotly/datasets/master/finance-charts-apple.csv')
>>> fig = create_candlestick(df['AAPL.Open'], df['AAPL.High'], df['AAPL.Low'], df['AAPL.Close'],
... dates=df.index)
>>> fig.show()
Example 2: Customize the candlestick colors
>>> from plotly.figure_factory import create_candlestick
>>> from plotly.graph_objs import Line, Marker
>>> from datetime import datetime
>>> import pandas as pd
>>> df = pd.read_csv('https://raw.githubusercontent.com/plotly/datasets/master/finance-charts-apple.csv')
>>> # Make increasing candlesticks and customize their color and name
>>> fig_increasing = create_candlestick(df['AAPL.Open'], df['AAPL.High'], df['AAPL.Low'], df['AAPL.Close'],
... dates=df.index,
... direction='increasing', name='AAPL',
... marker=Marker(color='rgb(150, 200, 250)'),
... line=Line(color='rgb(150, 200, 250)'))
>>> # Make decreasing candlesticks and customize their color and name
>>> fig_decreasing = create_candlestick(df['AAPL.Open'], df['AAPL.High'], df['AAPL.Low'], df['AAPL.Close'],
... dates=df.index,
... direction='decreasing',
... marker=Marker(color='rgb(128, 128, 128)'),
... line=Line(color='rgb(128, 128, 128)'))
>>> # Initialize the figure
>>> fig = fig_increasing
>>> # Add decreasing data with .extend()
>>> fig.add_trace(fig_decreasing['data']) # doctest: +SKIP
>>> fig.show()
Example 3: Candlestick chart with datetime objects
>>> from plotly.figure_factory import create_candlestick
>>> from datetime import datetime
>>> # Add data
>>> open_data = [33.0, 33.3, 33.5, 33.0, 34.1]
>>> high_data = [33.1, 33.3, 33.6, 33.2, 34.8]
>>> low_data = [32.7, 32.7, 32.8, 32.6, 32.8]
>>> close_data = [33.0, 32.9, 33.3, 33.1, 33.1]
>>> dates = [datetime(year=2013, month=10, day=10),
... datetime(year=2013, month=11, day=10),
... datetime(year=2013, month=12, day=10),
... datetime(year=2014, month=1, day=10),
... datetime(year=2014, month=2, day=10)]
>>> # Create ohlc
>>> fig = create_candlestick(open_data, high_data,
... low_data, close_data, dates=dates)
>>> fig.show()
"""
if dates is not None:
utils.validate_equal_length(open, high, low, close, dates)
else:
utils.validate_equal_length(open, high, low, close)
validate_ohlc(open, high, low, close, direction, **kwargs)
if direction == "increasing":
candle_incr_data = make_increasing_candle(
open, high, low, close, dates, **kwargs
)
data = candle_incr_data
elif direction == "decreasing":
candle_decr_data = make_decreasing_candle(
open, high, low, close, dates, **kwargs
)
data = candle_decr_data
else:
candle_incr_data = make_increasing_candle(
open, high, low, close, dates, **kwargs
)
candle_decr_data = make_decreasing_candle(
open, high, low, close, dates, **kwargs
)
data = candle_incr_data + candle_decr_data
layout = graph_objs.Layout()
return graph_objs.Figure(data=data, layout=layout)
class _Candlestick(object):
"""
Refer to FigureFactory.create_candlestick() for docstring.
"""
def __init__(self, open, high, low, close, dates, **kwargs):
self.open = open
self.high = high
self.low = low
self.close = close
if dates is not None:
self.x = dates
else:
self.x = [x for x in range(len(self.open))]
self.get_candle_increase()
def get_candle_increase(self):
"""
Separate increasing data from decreasing data.
The data is increasing when close value > open value
and decreasing when the close value <= open value.
"""
increase_y = []
increase_x = []
for index in range(len(self.open)):
if self.close[index] > self.open[index]:
increase_y.append(self.low[index])
increase_y.append(self.open[index])
increase_y.append(self.close[index])
increase_y.append(self.close[index])
increase_y.append(self.close[index])
increase_y.append(self.high[index])
increase_x.append(self.x[index])
increase_x = [[x, x, x, x, x, x] for x in increase_x]
increase_x = utils.flatten(increase_x)
return increase_x, increase_y
def get_candle_decrease(self):
"""
Separate increasing data from decreasing data.
The data is increasing when close value > open value
and decreasing when the close value <= open value.
"""
decrease_y = []
decrease_x = []
for index in range(len(self.open)):
if self.close[index] <= self.open[index]:
decrease_y.append(self.low[index])
decrease_y.append(self.open[index])
decrease_y.append(self.close[index])
decrease_y.append(self.close[index])
decrease_y.append(self.close[index])
decrease_y.append(self.high[index])
decrease_x.append(self.x[index])
decrease_x = [[x, x, x, x, x, x] for x in decrease_x]
decrease_x = utils.flatten(decrease_x)
return decrease_x, decrease_y

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,395 @@
from collections import OrderedDict
from plotly import exceptions, optional_imports
from plotly.graph_objs import graph_objs
# Optional imports, may be None for users that only use our core functionality.
np = optional_imports.get_module("numpy")
scp = optional_imports.get_module("scipy")
sch = optional_imports.get_module("scipy.cluster.hierarchy")
scs = optional_imports.get_module("scipy.spatial")
def create_dendrogram(
X,
orientation="bottom",
labels=None,
colorscale=None,
distfun=None,
linkagefun=lambda x: sch.linkage(x, "complete"),
hovertext=None,
color_threshold=None,
):
"""
Function that returns a dendrogram Plotly figure object. This is a thin
wrapper around scipy.cluster.hierarchy.dendrogram.
See also https://dash.plot.ly/dash-bio/clustergram.
:param (ndarray) X: Matrix of observations as array of arrays
:param (str) orientation: 'top', 'right', 'bottom', or 'left'
:param (list) labels: List of axis category labels(observation labels)
:param (list) colorscale: Optional colorscale for the dendrogram tree.
Requires 8 colors to be specified, the 7th of
which is ignored. With scipy>=1.5.0, the 2nd, 3rd
and 6th are used twice as often as the others.
Given a shorter list, the missing values are
replaced with defaults and with a longer list the
extra values are ignored.
:param (function) distfun: Function to compute the pairwise distance from
the observations
:param (function) linkagefun: Function to compute the linkage matrix from
the pairwise distances
:param (list[list]) hovertext: List of hovertext for constituent traces of dendrogram
clusters
:param (double) color_threshold: Value at which the separation of clusters will be made
Example 1: Simple bottom oriented dendrogram
>>> from plotly.figure_factory import create_dendrogram
>>> import numpy as np
>>> X = np.random.rand(10,10)
>>> fig = create_dendrogram(X)
>>> fig.show()
Example 2: Dendrogram to put on the left of the heatmap
>>> from plotly.figure_factory import create_dendrogram
>>> import numpy as np
>>> X = np.random.rand(5,5)
>>> names = ['Jack', 'Oxana', 'John', 'Chelsea', 'Mark']
>>> dendro = create_dendrogram(X, orientation='right', labels=names)
>>> dendro.update_layout({'width':700, 'height':500}) # doctest: +SKIP
>>> dendro.show()
Example 3: Dendrogram with Pandas
>>> from plotly.figure_factory import create_dendrogram
>>> import numpy as np
>>> import pandas as pd
>>> Index= ['A','B','C','D','E','F','G','H','I','J']
>>> df = pd.DataFrame(abs(np.random.randn(10, 10)), index=Index)
>>> fig = create_dendrogram(df, labels=Index)
>>> fig.show()
"""
if not scp or not scs or not sch:
raise ImportError(
"FigureFactory.create_dendrogram requires scipy, \
scipy.spatial and scipy.hierarchy"
)
s = X.shape
if len(s) != 2:
exceptions.PlotlyError("X should be 2-dimensional array.")
if distfun is None:
distfun = scs.distance.pdist
dendrogram = _Dendrogram(
X,
orientation,
labels,
colorscale,
distfun=distfun,
linkagefun=linkagefun,
hovertext=hovertext,
color_threshold=color_threshold,
)
return graph_objs.Figure(data=dendrogram.data, layout=dendrogram.layout)
class _Dendrogram(object):
"""Refer to FigureFactory.create_dendrogram() for docstring."""
def __init__(
self,
X,
orientation="bottom",
labels=None,
colorscale=None,
width=np.inf,
height=np.inf,
xaxis="xaxis",
yaxis="yaxis",
distfun=None,
linkagefun=lambda x: sch.linkage(x, "complete"),
hovertext=None,
color_threshold=None,
):
self.orientation = orientation
self.labels = labels
self.xaxis = xaxis
self.yaxis = yaxis
self.data = []
self.leaves = []
self.sign = {self.xaxis: 1, self.yaxis: 1}
self.layout = {self.xaxis: {}, self.yaxis: {}}
if self.orientation in ["left", "bottom"]:
self.sign[self.xaxis] = 1
else:
self.sign[self.xaxis] = -1
if self.orientation in ["right", "bottom"]:
self.sign[self.yaxis] = 1
else:
self.sign[self.yaxis] = -1
if distfun is None:
distfun = scs.distance.pdist
(dd_traces, xvals, yvals, ordered_labels, leaves) = self.get_dendrogram_traces(
X, colorscale, distfun, linkagefun, hovertext, color_threshold
)
self.labels = ordered_labels
self.leaves = leaves
yvals_flat = yvals.flatten()
xvals_flat = xvals.flatten()
self.zero_vals = []
for i in range(len(yvals_flat)):
if yvals_flat[i] == 0.0 and xvals_flat[i] not in self.zero_vals:
self.zero_vals.append(xvals_flat[i])
if len(self.zero_vals) > len(yvals) + 1:
# If the length of zero_vals is larger than the length of yvals,
# it means that there are wrong vals because of the identicial samples.
# Three and more identicial samples will make the yvals of spliting
# center into 0 and it will accidentally take it as leaves.
l_border = int(min(self.zero_vals))
r_border = int(max(self.zero_vals))
correct_leaves_pos = range(
l_border, r_border + 1, int((r_border - l_border) / len(yvals))
)
# Regenerating the leaves pos from the self.zero_vals with equally intervals.
self.zero_vals = [v for v in correct_leaves_pos]
self.zero_vals.sort()
self.layout = self.set_figure_layout(width, height)
self.data = dd_traces
def get_color_dict(self, colorscale):
"""
Returns colorscale used for dendrogram tree clusters.
:param (list) colorscale: Colors to use for the plot in rgb format.
:rtype (dict): A dict of default colors mapped to the user colorscale.
"""
# These are the color codes returned for dendrograms
# We're replacing them with nicer colors
# This list is the colors that can be used by dendrogram, which were
# determined as the combination of the default above_threshold_color and
# the default color palette (see scipy/cluster/hierarchy.py)
d = {
"r": "red",
"g": "green",
"b": "blue",
"c": "cyan",
"m": "magenta",
"y": "yellow",
"k": "black",
# TODO: 'w' doesn't seem to be in the default color
# palette in scipy/cluster/hierarchy.py
"w": "white",
}
default_colors = OrderedDict(sorted(d.items(), key=lambda t: t[0]))
if colorscale is None:
rgb_colorscale = [
"rgb(0,116,217)", # blue
"rgb(35,205,205)", # cyan
"rgb(61,153,112)", # green
"rgb(40,35,35)", # black
"rgb(133,20,75)", # magenta
"rgb(255,65,54)", # red
"rgb(255,255,255)", # white
"rgb(255,220,0)", # yellow
]
else:
rgb_colorscale = colorscale
for i in range(len(default_colors.keys())):
k = list(default_colors.keys())[i] # PY3 won't index keys
if i < len(rgb_colorscale):
default_colors[k] = rgb_colorscale[i]
# add support for cyclic format colors as introduced in scipy===1.5.0
# before this, the colors were named 'r', 'b', 'y' etc., now they are
# named 'C0', 'C1', etc. To keep the colors consistent regardless of the
# scipy version, we try as much as possible to map the new colors to the
# old colors
# this mapping was found by inpecting scipy/cluster/hierarchy.py (see
# comment above).
new_old_color_map = [
("C0", "b"),
("C1", "g"),
("C2", "r"),
("C3", "c"),
("C4", "m"),
("C5", "y"),
("C6", "k"),
("C7", "g"),
("C8", "r"),
("C9", "c"),
]
for nc, oc in new_old_color_map:
try:
default_colors[nc] = default_colors[oc]
except KeyError:
# it could happen that the old color isn't found (if a custom
# colorscale was specified), in this case we set it to an
# arbitrary default.
default_colors[nc] = "rgb(0,116,217)"
return default_colors
def set_axis_layout(self, axis_key):
"""
Sets and returns default axis object for dendrogram figure.
:param (str) axis_key: E.g., 'xaxis', 'xaxis1', 'yaxis', yaxis1', etc.
:rtype (dict): An axis_key dictionary with set parameters.
"""
axis_defaults = {
"type": "linear",
"ticks": "outside",
"mirror": "allticks",
"rangemode": "tozero",
"showticklabels": True,
"zeroline": False,
"showgrid": False,
"showline": True,
}
if len(self.labels) != 0:
axis_key_labels = self.xaxis
if self.orientation in ["left", "right"]:
axis_key_labels = self.yaxis
if axis_key_labels not in self.layout:
self.layout[axis_key_labels] = {}
self.layout[axis_key_labels]["tickvals"] = [
zv * self.sign[axis_key] for zv in self.zero_vals
]
self.layout[axis_key_labels]["ticktext"] = self.labels
self.layout[axis_key_labels]["tickmode"] = "array"
self.layout[axis_key].update(axis_defaults)
return self.layout[axis_key]
def set_figure_layout(self, width, height):
"""
Sets and returns default layout object for dendrogram figure.
"""
self.layout.update(
{
"showlegend": False,
"autosize": False,
"hovermode": "closest",
"width": width,
"height": height,
}
)
self.set_axis_layout(self.xaxis)
self.set_axis_layout(self.yaxis)
return self.layout
def get_dendrogram_traces(
self, X, colorscale, distfun, linkagefun, hovertext, color_threshold
):
"""
Calculates all the elements needed for plotting a dendrogram.
:param (ndarray) X: Matrix of observations as array of arrays
:param (list) colorscale: Color scale for dendrogram tree clusters
:param (function) distfun: Function to compute the pairwise distance
from the observations
:param (function) linkagefun: Function to compute the linkage matrix
from the pairwise distances
:param (list) hovertext: List of hovertext for constituent traces of dendrogram
:rtype (tuple): Contains all the traces in the following order:
(a) trace_list: List of Plotly trace objects for dendrogram tree
(b) icoord: All X points of the dendrogram tree as array of arrays
with length 4
(c) dcoord: All Y points of the dendrogram tree as array of arrays
with length 4
(d) ordered_labels: leaf labels in the order they are going to
appear on the plot
(e) P['leaves']: left-to-right traversal of the leaves
"""
d = distfun(X)
Z = linkagefun(d)
P = sch.dendrogram(
Z,
orientation=self.orientation,
labels=self.labels,
no_plot=True,
color_threshold=color_threshold,
)
icoord = np.array(P["icoord"])
dcoord = np.array(P["dcoord"])
ordered_labels = np.array(P["ivl"])
color_list = np.array(P["color_list"])
colors = self.get_color_dict(colorscale)
trace_list = []
for i in range(len(icoord)):
# xs and ys are arrays of 4 points that make up the '∩' shapes
# of the dendrogram tree
if self.orientation in ["top", "bottom"]:
xs = icoord[i]
else:
xs = dcoord[i]
if self.orientation in ["top", "bottom"]:
ys = dcoord[i]
else:
ys = icoord[i]
color_key = color_list[i]
hovertext_label = None
if hovertext:
hovertext_label = hovertext[i]
trace = dict(
type="scatter",
x=np.multiply(self.sign[self.xaxis], xs),
y=np.multiply(self.sign[self.yaxis], ys),
mode="lines",
marker=dict(color=colors[color_key]),
text=hovertext_label,
hoverinfo="text",
)
try:
x_index = int(self.xaxis[-1])
except ValueError:
x_index = ""
try:
y_index = int(self.yaxis[-1])
except ValueError:
y_index = ""
trace["xaxis"] = f"x{x_index}"
trace["yaxis"] = f"y{y_index}"
trace_list.append(trace)
return trace_list, icoord, dcoord, ordered_labels, P["leaves"]

View File

@ -0,0 +1,441 @@
from plotly import exceptions, optional_imports
from plotly.figure_factory import utils
from plotly.graph_objs import graph_objs
# Optional imports, may be None for users that only use our core functionality.
np = optional_imports.get_module("numpy")
pd = optional_imports.get_module("pandas")
scipy = optional_imports.get_module("scipy")
scipy_stats = optional_imports.get_module("scipy.stats")
DEFAULT_HISTNORM = "probability density"
ALTERNATIVE_HISTNORM = "probability"
def validate_distplot(hist_data, curve_type):
"""
Distplot-specific validations
:raises: (PlotlyError) If hist_data is not a list of lists
:raises: (PlotlyError) If curve_type is not valid (i.e. not 'kde' or
'normal').
"""
hist_data_types = (list,)
if np:
hist_data_types += (np.ndarray,)
if pd:
hist_data_types += (pd.core.series.Series,)
if not isinstance(hist_data[0], hist_data_types):
raise exceptions.PlotlyError(
"Oops, this function was written "
"to handle multiple datasets, if "
"you want to plot just one, make "
"sure your hist_data variable is "
"still a list of lists, i.e. x = "
"[1, 2, 3] -> x = [[1, 2, 3]]"
)
curve_opts = ("kde", "normal")
if curve_type not in curve_opts:
raise exceptions.PlotlyError("curve_type must be defined as 'kde' or 'normal'")
if not scipy:
raise ImportError("FigureFactory.create_distplot requires scipy")
def create_distplot(
hist_data,
group_labels,
bin_size=1.0,
curve_type="kde",
colors=None,
rug_text=None,
histnorm=DEFAULT_HISTNORM,
show_hist=True,
show_curve=True,
show_rug=True,
):
"""
Function that creates a distplot similar to seaborn.distplot;
**this function is deprecated**, use instead :mod:`plotly.express`
functions, for example
>>> import plotly.express as px
>>> tips = px.data.tips()
>>> fig = px.histogram(tips, x="total_bill", y="tip", color="sex", marginal="rug",
... hover_data=tips.columns)
>>> fig.show()
The distplot can be composed of all or any combination of the following
3 components: (1) histogram, (2) curve: (a) kernel density estimation
or (b) normal curve, and (3) rug plot. Additionally, multiple distplots
(from multiple datasets) can be created in the same plot.
:param (list[list]) hist_data: Use list of lists to plot multiple data
sets on the same plot.
:param (list[str]) group_labels: Names for each data set.
:param (list[float]|float) bin_size: Size of histogram bins.
Default = 1.
:param (str) curve_type: 'kde' or 'normal'. Default = 'kde'
:param (str) histnorm: 'probability density' or 'probability'
Default = 'probability density'
:param (bool) show_hist: Add histogram to distplot? Default = True
:param (bool) show_curve: Add curve to distplot? Default = True
:param (bool) show_rug: Add rug to distplot? Default = True
:param (list[str]) colors: Colors for traces.
:param (list[list]) rug_text: Hovertext values for rug_plot,
:return (dict): Representation of a distplot figure.
Example 1: Simple distplot of 1 data set
>>> from plotly.figure_factory import create_distplot
>>> hist_data = [[1.1, 1.1, 2.5, 3.0, 3.5,
... 3.5, 4.1, 4.4, 4.5, 4.5,
... 5.0, 5.0, 5.2, 5.5, 5.5,
... 5.5, 5.5, 5.5, 6.1, 7.0]]
>>> group_labels = ['distplot example']
>>> fig = create_distplot(hist_data, group_labels)
>>> fig.show()
Example 2: Two data sets and added rug text
>>> from plotly.figure_factory import create_distplot
>>> # Add histogram data
>>> hist1_x = [0.8, 1.2, 0.2, 0.6, 1.6,
... -0.9, -0.07, 1.95, 0.9, -0.2,
... -0.5, 0.3, 0.4, -0.37, 0.6]
>>> hist2_x = [0.8, 1.5, 1.5, 0.6, 0.59,
... 1.0, 0.8, 1.7, 0.5, 0.8,
... -0.3, 1.2, 0.56, 0.3, 2.2]
>>> # Group data together
>>> hist_data = [hist1_x, hist2_x]
>>> group_labels = ['2012', '2013']
>>> # Add text
>>> rug_text_1 = ['a1', 'b1', 'c1', 'd1', 'e1',
... 'f1', 'g1', 'h1', 'i1', 'j1',
... 'k1', 'l1', 'm1', 'n1', 'o1']
>>> rug_text_2 = ['a2', 'b2', 'c2', 'd2', 'e2',
... 'f2', 'g2', 'h2', 'i2', 'j2',
... 'k2', 'l2', 'm2', 'n2', 'o2']
>>> # Group text together
>>> rug_text_all = [rug_text_1, rug_text_2]
>>> # Create distplot
>>> fig = create_distplot(
... hist_data, group_labels, rug_text=rug_text_all, bin_size=.2)
>>> # Add title
>>> fig.update_layout(title='Dist Plot') # doctest: +SKIP
>>> fig.show()
Example 3: Plot with normal curve and hide rug plot
>>> from plotly.figure_factory import create_distplot
>>> import numpy as np
>>> x1 = np.random.randn(190)
>>> x2 = np.random.randn(200)+1
>>> x3 = np.random.randn(200)-1
>>> x4 = np.random.randn(210)+2
>>> hist_data = [x1, x2, x3, x4]
>>> group_labels = ['2012', '2013', '2014', '2015']
>>> fig = create_distplot(
... hist_data, group_labels, curve_type='normal',
... show_rug=False, bin_size=.4)
Example 4: Distplot with Pandas
>>> from plotly.figure_factory import create_distplot
>>> import numpy as np
>>> import pandas as pd
>>> df = pd.DataFrame({'2012': np.random.randn(200),
... '2013': np.random.randn(200)+1})
>>> fig = create_distplot([df[c] for c in df.columns], df.columns)
>>> fig.show()
"""
if colors is None:
colors = []
if rug_text is None:
rug_text = []
validate_distplot(hist_data, curve_type)
utils.validate_equal_length(hist_data, group_labels)
if isinstance(bin_size, (float, int)):
bin_size = [bin_size] * len(hist_data)
data = []
if show_hist:
hist = _Distplot(
hist_data,
histnorm,
group_labels,
bin_size,
curve_type,
colors,
rug_text,
show_hist,
show_curve,
).make_hist()
data.append(hist)
if show_curve:
if curve_type == "normal":
curve = _Distplot(
hist_data,
histnorm,
group_labels,
bin_size,
curve_type,
colors,
rug_text,
show_hist,
show_curve,
).make_normal()
else:
curve = _Distplot(
hist_data,
histnorm,
group_labels,
bin_size,
curve_type,
colors,
rug_text,
show_hist,
show_curve,
).make_kde()
data.append(curve)
if show_rug:
rug = _Distplot(
hist_data,
histnorm,
group_labels,
bin_size,
curve_type,
colors,
rug_text,
show_hist,
show_curve,
).make_rug()
data.append(rug)
layout = graph_objs.Layout(
barmode="overlay",
hovermode="closest",
legend=dict(traceorder="reversed"),
xaxis1=dict(domain=[0.0, 1.0], anchor="y2", zeroline=False),
yaxis1=dict(domain=[0.35, 1], anchor="free", position=0.0),
yaxis2=dict(domain=[0, 0.25], anchor="x1", dtick=1, showticklabels=False),
)
else:
layout = graph_objs.Layout(
barmode="overlay",
hovermode="closest",
legend=dict(traceorder="reversed"),
xaxis1=dict(domain=[0.0, 1.0], anchor="y2", zeroline=False),
yaxis1=dict(domain=[0.0, 1], anchor="free", position=0.0),
)
data = sum(data, [])
return graph_objs.Figure(data=data, layout=layout)
class _Distplot(object):
"""
Refer to TraceFactory.create_distplot() for docstring
"""
def __init__(
self,
hist_data,
histnorm,
group_labels,
bin_size,
curve_type,
colors,
rug_text,
show_hist,
show_curve,
):
self.hist_data = hist_data
self.histnorm = histnorm
self.group_labels = group_labels
self.bin_size = bin_size
self.show_hist = show_hist
self.show_curve = show_curve
self.trace_number = len(hist_data)
if rug_text:
self.rug_text = rug_text
else:
self.rug_text = [None] * self.trace_number
self.start = []
self.end = []
if colors:
self.colors = colors
else:
self.colors = [
"rgb(31, 119, 180)",
"rgb(255, 127, 14)",
"rgb(44, 160, 44)",
"rgb(214, 39, 40)",
"rgb(148, 103, 189)",
"rgb(140, 86, 75)",
"rgb(227, 119, 194)",
"rgb(127, 127, 127)",
"rgb(188, 189, 34)",
"rgb(23, 190, 207)",
]
self.curve_x = [None] * self.trace_number
self.curve_y = [None] * self.trace_number
for trace in self.hist_data:
self.start.append(min(trace) * 1.0)
self.end.append(max(trace) * 1.0)
def make_hist(self):
"""
Makes the histogram(s) for FigureFactory.create_distplot().
:rtype (list) hist: list of histogram representations
"""
hist = [None] * self.trace_number
for index in range(self.trace_number):
hist[index] = dict(
type="histogram",
x=self.hist_data[index],
xaxis="x1",
yaxis="y1",
histnorm=self.histnorm,
name=self.group_labels[index],
legendgroup=self.group_labels[index],
marker=dict(color=self.colors[index % len(self.colors)]),
autobinx=False,
xbins=dict(
start=self.start[index],
end=self.end[index],
size=self.bin_size[index],
),
opacity=0.7,
)
return hist
def make_kde(self):
"""
Makes the kernel density estimation(s) for create_distplot().
This is called when curve_type = 'kde' in create_distplot().
:rtype (list) curve: list of kde representations
"""
curve = [None] * self.trace_number
for index in range(self.trace_number):
self.curve_x[index] = [
self.start[index] + x * (self.end[index] - self.start[index]) / 500
for x in range(500)
]
self.curve_y[index] = scipy_stats.gaussian_kde(self.hist_data[index])(
self.curve_x[index]
)
if self.histnorm == ALTERNATIVE_HISTNORM:
self.curve_y[index] *= self.bin_size[index]
for index in range(self.trace_number):
curve[index] = dict(
type="scatter",
x=self.curve_x[index],
y=self.curve_y[index],
xaxis="x1",
yaxis="y1",
mode="lines",
name=self.group_labels[index],
legendgroup=self.group_labels[index],
showlegend=False if self.show_hist else True,
marker=dict(color=self.colors[index % len(self.colors)]),
)
return curve
def make_normal(self):
"""
Makes the normal curve(s) for create_distplot().
This is called when curve_type = 'normal' in create_distplot().
:rtype (list) curve: list of normal curve representations
"""
curve = [None] * self.trace_number
mean = [None] * self.trace_number
sd = [None] * self.trace_number
for index in range(self.trace_number):
mean[index], sd[index] = scipy_stats.norm.fit(self.hist_data[index])
self.curve_x[index] = [
self.start[index] + x * (self.end[index] - self.start[index]) / 500
for x in range(500)
]
self.curve_y[index] = scipy_stats.norm.pdf(
self.curve_x[index], loc=mean[index], scale=sd[index]
)
if self.histnorm == ALTERNATIVE_HISTNORM:
self.curve_y[index] *= self.bin_size[index]
for index in range(self.trace_number):
curve[index] = dict(
type="scatter",
x=self.curve_x[index],
y=self.curve_y[index],
xaxis="x1",
yaxis="y1",
mode="lines",
name=self.group_labels[index],
legendgroup=self.group_labels[index],
showlegend=False if self.show_hist else True,
marker=dict(color=self.colors[index % len(self.colors)]),
)
return curve
def make_rug(self):
"""
Makes the rug plot(s) for create_distplot().
:rtype (list) rug: list of rug plot representations
"""
rug = [None] * self.trace_number
for index in range(self.trace_number):
rug[index] = dict(
type="scatter",
x=self.hist_data[index],
y=([self.group_labels[index]] * len(self.hist_data[index])),
xaxis="x1",
yaxis="y2",
mode="markers",
name=self.group_labels[index],
legendgroup=self.group_labels[index],
showlegend=(False if self.show_hist or self.show_curve else True),
text=self.rug_text[index],
marker=dict(
color=self.colors[index % len(self.colors)], symbol="line-ns-open"
),
)
return rug

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,526 @@
from plotly.express._core import build_dataframe
from plotly.express._doc import make_docstring
from plotly.express._chart_types import choropleth_mapbox, scatter_mapbox
import narwhals.stable.v1 as nw
import numpy as np
def _project_latlon_to_wgs84(lat, lon):
"""
Projects lat and lon to WGS84, used to get regular hexagons on a mapbox map
"""
x = lon * np.pi / 180
y = np.arctanh(np.sin(lat * np.pi / 180))
return x, y
def _project_wgs84_to_latlon(x, y):
"""
Projects WGS84 to lat and lon, used to get regular hexagons on a mapbox map
"""
lon = x * 180 / np.pi
lat = (2 * np.arctan(np.exp(y)) - np.pi / 2) * 180 / np.pi
return lat, lon
def _getBoundsZoomLevel(lon_min, lon_max, lat_min, lat_max, mapDim):
"""
Get the mapbox zoom level given bounds and a figure dimension
Source: https://stackoverflow.com/questions/6048975/google-maps-v3-how-to-calculate-the-zoom-level-for-a-given-bounds
"""
scale = (
2 # adjustment to reflect MapBox base tiles are 512x512 vs. Google's 256x256
)
WORLD_DIM = {"height": 256 * scale, "width": 256 * scale}
ZOOM_MAX = 18
def latRad(lat):
sin = np.sin(lat * np.pi / 180)
radX2 = np.log((1 + sin) / (1 - sin)) / 2
return max(min(radX2, np.pi), -np.pi) / 2
def zoom(mapPx, worldPx, fraction):
return 0.95 * np.log(mapPx / worldPx / fraction) / np.log(2)
latFraction = (latRad(lat_max) - latRad(lat_min)) / np.pi
lngDiff = lon_max - lon_min
lngFraction = ((lngDiff + 360) if lngDiff < 0 else lngDiff) / 360
latZoom = zoom(mapDim["height"], WORLD_DIM["height"], latFraction)
lngZoom = zoom(mapDim["width"], WORLD_DIM["width"], lngFraction)
return min(latZoom, lngZoom, ZOOM_MAX)
def _compute_hexbin(x, y, x_range, y_range, color, nx, agg_func, min_count):
"""
Computes the aggregation at hexagonal bin level.
Also defines the coordinates of the hexagons for plotting.
The binning is inspired by matplotlib's implementation.
Parameters
----------
x : np.ndarray
Array of x values (shape N)
y : np.ndarray
Array of y values (shape N)
x_range : np.ndarray
Min and max x (shape 2)
y_range : np.ndarray
Min and max y (shape 2)
color : np.ndarray
Metric to aggregate at hexagon level (shape N)
nx : int
Number of hexagons horizontally
agg_func : function
Numpy compatible aggregator, this function must take a one-dimensional
np.ndarray as input and output a scalar
min_count : int
Minimum number of points in the hexagon for the hexagon to be displayed
Returns
-------
np.ndarray
X coordinates of each hexagon (shape M x 6)
np.ndarray
Y coordinates of each hexagon (shape M x 6)
np.ndarray
Centers of the hexagons (shape M x 2)
np.ndarray
Aggregated value in each hexagon (shape M)
"""
xmin = x_range.min()
xmax = x_range.max()
ymin = y_range.min()
ymax = y_range.max()
# In the x-direction, the hexagons exactly cover the region from
# xmin to xmax. Need some padding to avoid roundoff errors.
padding = 1.0e-9 * (xmax - xmin)
xmin -= padding
xmax += padding
Dx = xmax - xmin
Dy = ymax - ymin
if Dx == 0 and Dy > 0:
dx = Dy / nx
elif Dx == 0 and Dy == 0:
dx, _ = _project_latlon_to_wgs84(1, 1)
else:
dx = Dx / nx
dy = dx * np.sqrt(3)
ny = np.ceil(Dy / dy).astype(int)
# Center the hexagons vertically since we only want regular hexagons
ymin -= (ymin + dy * ny - ymax) / 2
x = (x - xmin) / dx
y = (y - ymin) / dy
ix1 = np.round(x).astype(int)
iy1 = np.round(y).astype(int)
ix2 = np.floor(x).astype(int)
iy2 = np.floor(y).astype(int)
nx1 = nx + 1
ny1 = ny + 1
nx2 = nx
ny2 = ny
n = nx1 * ny1 + nx2 * ny2
d1 = (x - ix1) ** 2 + 3.0 * (y - iy1) ** 2
d2 = (x - ix2 - 0.5) ** 2 + 3.0 * (y - iy2 - 0.5) ** 2
bdist = d1 < d2
if color is None:
lattice1 = np.zeros((nx1, ny1))
lattice2 = np.zeros((nx2, ny2))
c1 = (0 <= ix1) & (ix1 < nx1) & (0 <= iy1) & (iy1 < ny1) & bdist
c2 = (0 <= ix2) & (ix2 < nx2) & (0 <= iy2) & (iy2 < ny2) & ~bdist
np.add.at(lattice1, (ix1[c1], iy1[c1]), 1)
np.add.at(lattice2, (ix2[c2], iy2[c2]), 1)
if min_count is not None:
lattice1[lattice1 < min_count] = np.nan
lattice2[lattice2 < min_count] = np.nan
accum = np.concatenate([lattice1.ravel(), lattice2.ravel()])
good_idxs = ~np.isnan(accum)
else:
if min_count is None:
min_count = 1
# create accumulation arrays
lattice1 = np.empty((nx1, ny1), dtype=object)
for i in range(nx1):
for j in range(ny1):
lattice1[i, j] = []
lattice2 = np.empty((nx2, ny2), dtype=object)
for i in range(nx2):
for j in range(ny2):
lattice2[i, j] = []
for i in range(len(x)):
if bdist[i]:
if 0 <= ix1[i] < nx1 and 0 <= iy1[i] < ny1:
lattice1[ix1[i], iy1[i]].append(color[i])
else:
if 0 <= ix2[i] < nx2 and 0 <= iy2[i] < ny2:
lattice2[ix2[i], iy2[i]].append(color[i])
for i in range(nx1):
for j in range(ny1):
vals = lattice1[i, j]
if len(vals) >= min_count:
lattice1[i, j] = agg_func(vals)
else:
lattice1[i, j] = np.nan
for i in range(nx2):
for j in range(ny2):
vals = lattice2[i, j]
if len(vals) >= min_count:
lattice2[i, j] = agg_func(vals)
else:
lattice2[i, j] = np.nan
accum = np.hstack(
(lattice1.astype(float).ravel(), lattice2.astype(float).ravel())
)
good_idxs = ~np.isnan(accum)
agreggated_value = accum[good_idxs]
centers = np.zeros((n, 2), float)
centers[: nx1 * ny1, 0] = np.repeat(np.arange(nx1), ny1)
centers[: nx1 * ny1, 1] = np.tile(np.arange(ny1), nx1)
centers[nx1 * ny1 :, 0] = np.repeat(np.arange(nx2) + 0.5, ny2)
centers[nx1 * ny1 :, 1] = np.tile(np.arange(ny2), nx2) + 0.5
centers[:, 0] *= dx
centers[:, 1] *= dy
centers[:, 0] += xmin
centers[:, 1] += ymin
centers = centers[good_idxs]
# Define normalised regular hexagon coordinates
hx = [0, 0.5, 0.5, 0, -0.5, -0.5]
hy = [
-0.5 / np.cos(np.pi / 6),
-0.5 * np.tan(np.pi / 6),
0.5 * np.tan(np.pi / 6),
0.5 / np.cos(np.pi / 6),
0.5 * np.tan(np.pi / 6),
-0.5 * np.tan(np.pi / 6),
]
# Number of hexagons needed
m = len(centers)
# Coordinates for all hexagonal patches
hxs = np.array([hx] * m) * dx + np.vstack(centers[:, 0])
hys = np.array([hy] * m) * dy / np.sqrt(3) + np.vstack(centers[:, 1])
return hxs, hys, centers, agreggated_value
def _compute_wgs84_hexbin(
lat=None,
lon=None,
lat_range=None,
lon_range=None,
color=None,
nx=None,
agg_func=None,
min_count=None,
native_namespace=None,
):
"""
Computes the lat-lon aggregation at hexagonal bin level.
Latitude and longitude need to be projected to WGS84 before aggregating
in order to display regular hexagons on the map.
Parameters
----------
lat : np.ndarray
Array of latitudes (shape N)
lon : np.ndarray
Array of longitudes (shape N)
lat_range : np.ndarray
Min and max latitudes (shape 2)
lon_range : np.ndarray
Min and max longitudes (shape 2)
color : np.ndarray
Metric to aggregate at hexagon level (shape N)
nx : int
Number of hexagons horizontally
agg_func : function
Numpy compatible aggregator, this function must take a one-dimensional
np.ndarray as input and output a scalar
min_count : int
Minimum number of points in the hexagon for the hexagon to be displayed
Returns
-------
np.ndarray
Lat coordinates of each hexagon (shape M x 6)
np.ndarray
Lon coordinates of each hexagon (shape M x 6)
nw.Series
Unique id for each hexagon, to be used in the geojson data (shape M)
np.ndarray
Aggregated value in each hexagon (shape M)
"""
# Project to WGS 84
x, y = _project_latlon_to_wgs84(lat, lon)
if lat_range is None:
lat_range = np.array([lat.min(), lat.max()])
if lon_range is None:
lon_range = np.array([lon.min(), lon.max()])
x_range, y_range = _project_latlon_to_wgs84(lat_range, lon_range)
hxs, hys, centers, agreggated_value = _compute_hexbin(
x, y, x_range, y_range, color, nx, agg_func, min_count
)
# Convert back to lat-lon
hexagons_lats, hexagons_lons = _project_wgs84_to_latlon(hxs, hys)
# Create unique feature id based on hexagon center
centers = centers.astype(str)
hexagons_ids = (
nw.from_dict(
{"x1": centers[:, 0], "x2": centers[:, 1]},
native_namespace=native_namespace,
)
.select(hexagons_ids=nw.concat_str([nw.col("x1"), nw.col("x2")], separator=","))
.get_column("hexagons_ids")
)
return hexagons_lats, hexagons_lons, hexagons_ids, agreggated_value
def _hexagons_to_geojson(hexagons_lats, hexagons_lons, ids=None):
"""
Creates a geojson of hexagonal features based on the outputs of
_compute_wgs84_hexbin
"""
features = []
if ids is None:
ids = np.arange(len(hexagons_lats))
for lat, lon, idx in zip(hexagons_lats, hexagons_lons, ids):
points = np.array([lon, lat]).T.tolist()
points.append(points[0])
features.append(
dict(
type="Feature",
id=idx,
geometry=dict(type="Polygon", coordinates=[points]),
)
)
return dict(type="FeatureCollection", features=features)
def create_hexbin_mapbox(
data_frame=None,
lat=None,
lon=None,
color=None,
nx_hexagon=5,
agg_func=None,
animation_frame=None,
color_discrete_sequence=None,
color_discrete_map={},
labels={},
color_continuous_scale=None,
range_color=None,
color_continuous_midpoint=None,
opacity=None,
zoom=None,
center=None,
mapbox_style=None,
title=None,
template=None,
width=None,
height=None,
min_count=None,
show_original_data=False,
original_data_marker=None,
):
"""
Returns a figure aggregating scattered points into connected hexagons
"""
args = build_dataframe(args=locals(), constructor=None)
native_namespace = nw.get_native_namespace(args["data_frame"])
if agg_func is None:
agg_func = np.mean
lat_range = (
args["data_frame"]
.select(
nw.min(args["lat"]).name.suffix("_min"),
nw.max(args["lat"]).name.suffix("_max"),
)
.to_numpy()
.squeeze()
)
lon_range = (
args["data_frame"]
.select(
nw.min(args["lon"]).name.suffix("_min"),
nw.max(args["lon"]).name.suffix("_max"),
)
.to_numpy()
.squeeze()
)
hexagons_lats, hexagons_lons, hexagons_ids, count = _compute_wgs84_hexbin(
lat=args["data_frame"].get_column(args["lat"]).to_numpy(),
lon=args["data_frame"].get_column(args["lon"]).to_numpy(),
lat_range=lat_range,
lon_range=lon_range,
color=None,
nx=nx_hexagon,
agg_func=agg_func,
min_count=min_count,
native_namespace=native_namespace,
)
geojson = _hexagons_to_geojson(hexagons_lats, hexagons_lons, hexagons_ids)
if zoom is None:
if height is None and width is None:
mapDim = dict(height=450, width=450)
elif height is None and width is not None:
mapDim = dict(height=450, width=width)
elif height is not None and width is None:
mapDim = dict(height=height, width=height)
else:
mapDim = dict(height=height, width=width)
zoom = _getBoundsZoomLevel(
lon_range[0], lon_range[1], lat_range[0], lat_range[1], mapDim
)
if center is None:
center = dict(lat=lat_range.mean(), lon=lon_range.mean())
if args["animation_frame"] is not None:
groups = dict(
args["data_frame"]
.group_by(args["animation_frame"], drop_null_keys=True)
.__iter__()
)
else:
groups = {(0,): args["data_frame"]}
agg_data_frame_list = []
for key, df in groups.items():
_, _, hexagons_ids, aggregated_value = _compute_wgs84_hexbin(
lat=df.get_column(args["lat"]).to_numpy(),
lon=df.get_column(args["lon"]).to_numpy(),
lat_range=lat_range,
lon_range=lon_range,
color=df.get_column(args["color"]).to_numpy() if args["color"] else None,
nx=nx_hexagon,
agg_func=agg_func,
min_count=min_count,
native_namespace=native_namespace,
)
agg_data_frame_list.append(
nw.from_dict(
{
"frame": [key[0]] * len(hexagons_ids),
"locations": hexagons_ids,
"color": aggregated_value,
},
native_namespace=native_namespace,
)
)
agg_data_frame = nw.concat(agg_data_frame_list, how="vertical").with_columns(
color=nw.col("color").cast(nw.Int64)
)
if range_color is None:
range_color = [agg_data_frame["color"].min(), agg_data_frame["color"].max()]
fig = choropleth_mapbox(
data_frame=agg_data_frame.to_native(),
geojson=geojson,
locations="locations",
color="color",
hover_data={"color": True, "locations": False, "frame": False},
animation_frame=("frame" if args["animation_frame"] is not None else None),
color_discrete_sequence=color_discrete_sequence,
color_discrete_map=color_discrete_map,
labels=labels,
color_continuous_scale=color_continuous_scale,
range_color=range_color,
color_continuous_midpoint=color_continuous_midpoint,
opacity=opacity,
zoom=zoom,
center=center,
mapbox_style=mapbox_style,
title=title,
template=template,
width=width,
height=height,
)
if show_original_data:
original_fig = scatter_mapbox(
data_frame=(
args["data_frame"].sort(
by=args["animation_frame"], descending=False, nulls_last=True
)
if args["animation_frame"] is not None
else args["data_frame"]
).to_native(),
lat=args["lat"],
lon=args["lon"],
animation_frame=args["animation_frame"],
)
original_fig.data[0].hoverinfo = "skip"
original_fig.data[0].hovertemplate = None
original_fig.data[0].marker = original_data_marker
fig.add_trace(original_fig.data[0])
if args["animation_frame"] is not None:
for i in range(len(original_fig.frames)):
original_fig.frames[i].data[0].hoverinfo = "skip"
original_fig.frames[i].data[0].hovertemplate = None
original_fig.frames[i].data[0].marker = original_data_marker
fig.frames[i].data = [
fig.frames[i].data[0],
original_fig.frames[i].data[0],
]
return fig
create_hexbin_mapbox.__doc__ = make_docstring(
create_hexbin_mapbox,
override_dict=dict(
nx_hexagon=["int", "Number of hexagons (horizontally) to be created"],
agg_func=[
"function",
"Numpy array aggregator, it must take as input a 1D array",
"and output a scalar value.",
],
min_count=[
"int",
"Minimum number of points in a hexagon for it to be displayed.",
"If None and color is not set, display all hexagons.",
"If None and color is set, only display hexagons that contain points.",
],
show_original_data=[
"bool",
"Whether to show the original data on top of the hexbin aggregation.",
],
original_data_marker=["dict", "Scattermapbox marker options."],
),
)

View File

@ -0,0 +1,295 @@
from plotly import exceptions
from plotly.graph_objs import graph_objs
from plotly.figure_factory import utils
# Default colours for finance charts
_DEFAULT_INCREASING_COLOR = "#3D9970" # http://clrs.cc
_DEFAULT_DECREASING_COLOR = "#FF4136"
def validate_ohlc(open, high, low, close, direction, **kwargs):
"""
ohlc and candlestick specific validations
Specifically, this checks that the high value is the greatest value and
the low value is the lowest value in each unit.
See FigureFactory.create_ohlc() or FigureFactory.create_candlestick()
for params
:raises: (PlotlyError) If the high value is not the greatest value in
each unit.
:raises: (PlotlyError) If the low value is not the lowest value in each
unit.
:raises: (PlotlyError) If direction is not 'increasing' or 'decreasing'
"""
for lst in [open, low, close]:
for index in range(len(high)):
if high[index] < lst[index]:
raise exceptions.PlotlyError(
"Oops! Looks like some of "
"your high values are less "
"the corresponding open, "
"low, or close values. "
"Double check that your data "
"is entered in O-H-L-C order"
)
for lst in [open, high, close]:
for index in range(len(low)):
if low[index] > lst[index]:
raise exceptions.PlotlyError(
"Oops! Looks like some of "
"your low values are greater "
"than the corresponding high"
", open, or close values. "
"Double check that your data "
"is entered in O-H-L-C order"
)
direction_opts = ("increasing", "decreasing", "both")
if direction not in direction_opts:
raise exceptions.PlotlyError(
"direction must be defined as 'increasing', 'decreasing', or 'both'"
)
def make_increasing_ohlc(open, high, low, close, dates, **kwargs):
"""
Makes increasing ohlc sticks
_make_increasing_ohlc() and _make_decreasing_ohlc separate the
increasing trace from the decreasing trace so kwargs (such as
color) can be passed separately to increasing or decreasing traces
when direction is set to 'increasing' or 'decreasing' in
FigureFactory.create_candlestick()
:param (list) open: opening values
:param (list) high: high values
:param (list) low: low values
:param (list) close: closing values
:param (list) dates: list of datetime objects. Default: None
:param kwargs: kwargs to be passed to increasing trace via
plotly.graph_objs.Scatter.
:rtype (trace) ohlc_incr_data: Scatter trace of all increasing ohlc
sticks.
"""
(flat_increase_x, flat_increase_y, text_increase) = _OHLC(
open, high, low, close, dates
).get_increase()
if "name" in kwargs:
showlegend = True
else:
kwargs.setdefault("name", "Increasing")
showlegend = False
kwargs.setdefault("line", dict(color=_DEFAULT_INCREASING_COLOR, width=1))
kwargs.setdefault("text", text_increase)
ohlc_incr = dict(
type="scatter",
x=flat_increase_x,
y=flat_increase_y,
mode="lines",
showlegend=showlegend,
**kwargs,
)
return ohlc_incr
def make_decreasing_ohlc(open, high, low, close, dates, **kwargs):
"""
Makes decreasing ohlc sticks
:param (list) open: opening values
:param (list) high: high values
:param (list) low: low values
:param (list) close: closing values
:param (list) dates: list of datetime objects. Default: None
:param kwargs: kwargs to be passed to increasing trace via
plotly.graph_objs.Scatter.
:rtype (trace) ohlc_decr_data: Scatter trace of all decreasing ohlc
sticks.
"""
(flat_decrease_x, flat_decrease_y, text_decrease) = _OHLC(
open, high, low, close, dates
).get_decrease()
kwargs.setdefault("line", dict(color=_DEFAULT_DECREASING_COLOR, width=1))
kwargs.setdefault("text", text_decrease)
kwargs.setdefault("showlegend", False)
kwargs.setdefault("name", "Decreasing")
ohlc_decr = dict(
type="scatter", x=flat_decrease_x, y=flat_decrease_y, mode="lines", **kwargs
)
return ohlc_decr
def create_ohlc(open, high, low, close, dates=None, direction="both", **kwargs):
"""
**deprecated**, use instead the plotly.graph_objects trace
:class:`plotly.graph_objects.Ohlc`
:param (list) open: opening values
:param (list) high: high values
:param (list) low: low values
:param (list) close: closing
:param (list) dates: list of datetime objects. Default: None
:param (string) direction: direction can be 'increasing', 'decreasing',
or 'both'. When the direction is 'increasing', the returned figure
consists of all units where the close value is greater than the
corresponding open value, and when the direction is 'decreasing',
the returned figure consists of all units where the close value is
less than or equal to the corresponding open value. When the
direction is 'both', both increasing and decreasing units are
returned. Default: 'both'
:param kwargs: kwargs passed through plotly.graph_objs.Scatter.
These kwargs describe other attributes about the ohlc Scatter trace
such as the color or the legend name. For more information on valid
kwargs call help(plotly.graph_objs.Scatter)
:rtype (dict): returns a representation of an ohlc chart figure.
Example 1: Simple OHLC chart from a Pandas DataFrame
>>> from plotly.figure_factory import create_ohlc
>>> from datetime import datetime
>>> import pandas as pd
>>> df = pd.read_csv('https://raw.githubusercontent.com/plotly/datasets/master/finance-charts-apple.csv')
>>> fig = create_ohlc(df['AAPL.Open'], df['AAPL.High'], df['AAPL.Low'], df['AAPL.Close'], dates=df.index)
>>> fig.show()
"""
if dates is not None:
utils.validate_equal_length(open, high, low, close, dates)
else:
utils.validate_equal_length(open, high, low, close)
validate_ohlc(open, high, low, close, direction, **kwargs)
if direction == "increasing":
ohlc_incr = make_increasing_ohlc(open, high, low, close, dates, **kwargs)
data = [ohlc_incr]
elif direction == "decreasing":
ohlc_decr = make_decreasing_ohlc(open, high, low, close, dates, **kwargs)
data = [ohlc_decr]
else:
ohlc_incr = make_increasing_ohlc(open, high, low, close, dates, **kwargs)
ohlc_decr = make_decreasing_ohlc(open, high, low, close, dates, **kwargs)
data = [ohlc_incr, ohlc_decr]
layout = graph_objs.Layout(xaxis=dict(zeroline=False), hovermode="closest")
return graph_objs.Figure(data=data, layout=layout)
class _OHLC(object):
"""
Refer to FigureFactory.create_ohlc_increase() for docstring.
"""
def __init__(self, open, high, low, close, dates, **kwargs):
self.open = open
self.high = high
self.low = low
self.close = close
self.empty = [None] * len(open)
self.dates = dates
self.all_x = []
self.all_y = []
self.increase_x = []
self.increase_y = []
self.decrease_x = []
self.decrease_y = []
self.get_all_xy()
self.separate_increase_decrease()
def get_all_xy(self):
"""
Zip data to create OHLC shape
OHLC shape: low to high vertical bar with
horizontal branches for open and close values.
If dates were added, the smallest date difference is calculated and
multiplied by .2 to get the length of the open and close branches.
If no date data was provided, the x-axis is a list of integers and the
length of the open and close branches is .2.
"""
self.all_y = list(
zip(
self.open,
self.open,
self.high,
self.low,
self.close,
self.close,
self.empty,
)
)
if self.dates is not None:
date_dif = []
for i in range(len(self.dates) - 1):
date_dif.append(self.dates[i + 1] - self.dates[i])
date_dif_min = (min(date_dif)) / 5
self.all_x = [
[x - date_dif_min, x, x, x, x, x + date_dif_min, None]
for x in self.dates
]
else:
self.all_x = [
[x - 0.2, x, x, x, x, x + 0.2, None] for x in range(len(self.open))
]
def separate_increase_decrease(self):
"""
Separate data into two groups: increase and decrease
(1) Increase, where close > open and
(2) Decrease, where close <= open
"""
for index in range(len(self.open)):
if self.close[index] is None:
pass
elif self.close[index] > self.open[index]:
self.increase_x.append(self.all_x[index])
self.increase_y.append(self.all_y[index])
else:
self.decrease_x.append(self.all_x[index])
self.decrease_y.append(self.all_y[index])
def get_increase(self):
"""
Flatten increase data and get increase text
:rtype (list, list, list): flat_increase_x: x-values for the increasing
trace, flat_increase_y: y=values for the increasing trace and
text_increase: hovertext for the increasing trace
"""
flat_increase_x = utils.flatten(self.increase_x)
flat_increase_y = utils.flatten(self.increase_y)
text_increase = ("Open", "Open", "High", "Low", "Close", "Close", "") * (
len(self.increase_x)
)
return flat_increase_x, flat_increase_y, text_increase
def get_decrease(self):
"""
Flatten decrease data and get decrease text
:rtype (list, list, list): flat_decrease_x: x-values for the decreasing
trace, flat_decrease_y: y=values for the decreasing trace and
text_decrease: hovertext for the decreasing trace
"""
flat_decrease_x = utils.flatten(self.decrease_x)
flat_decrease_y = utils.flatten(self.decrease_y)
text_decrease = ("Open", "Open", "High", "Low", "Close", "Close", "") * (
len(self.decrease_x)
)
return flat_decrease_x, flat_decrease_y, text_decrease

View File

@ -0,0 +1,265 @@
import math
from plotly import exceptions
from plotly.graph_objs import graph_objs
from plotly.figure_factory import utils
def create_quiver(
x, y, u, v, scale=0.1, arrow_scale=0.3, angle=math.pi / 9, scaleratio=None, **kwargs
):
"""
Returns data for a quiver plot.
:param (list|ndarray) x: x coordinates of the arrow locations
:param (list|ndarray) y: y coordinates of the arrow locations
:param (list|ndarray) u: x components of the arrow vectors
:param (list|ndarray) v: y components of the arrow vectors
:param (float in [0,1]) scale: scales size of the arrows(ideally to
avoid overlap). Default = .1
:param (float in [0,1]) arrow_scale: value multiplied to length of barb
to get length of arrowhead. Default = .3
:param (angle in radians) angle: angle of arrowhead. Default = pi/9
:param (positive float) scaleratio: the ratio between the scale of the y-axis
and the scale of the x-axis (scale_y / scale_x). Default = None, the
scale ratio is not fixed.
:param kwargs: kwargs passed through plotly.graph_objs.Scatter
for more information on valid kwargs call
help(plotly.graph_objs.Scatter)
:rtype (dict): returns a representation of quiver figure.
Example 1: Trivial Quiver
>>> from plotly.figure_factory import create_quiver
>>> import math
>>> # 1 Arrow from (0,0) to (1,1)
>>> fig = create_quiver(x=[0], y=[0], u=[1], v=[1], scale=1)
>>> fig.show()
Example 2: Quiver plot using meshgrid
>>> from plotly.figure_factory import create_quiver
>>> import numpy as np
>>> import math
>>> # Add data
>>> x,y = np.meshgrid(np.arange(0, 2, .2), np.arange(0, 2, .2))
>>> u = np.cos(x)*y
>>> v = np.sin(x)*y
>>> #Create quiver
>>> fig = create_quiver(x, y, u, v)
>>> fig.show()
Example 3: Styling the quiver plot
>>> from plotly.figure_factory import create_quiver
>>> import numpy as np
>>> import math
>>> # Add data
>>> x, y = np.meshgrid(np.arange(-np.pi, math.pi, .5),
... np.arange(-math.pi, math.pi, .5))
>>> u = np.cos(x)*y
>>> v = np.sin(x)*y
>>> # Create quiver
>>> fig = create_quiver(x, y, u, v, scale=.2, arrow_scale=.3, angle=math.pi/6,
... name='Wind Velocity', line=dict(width=1))
>>> # Add title to layout
>>> fig.update_layout(title='Quiver Plot') # doctest: +SKIP
>>> fig.show()
Example 4: Forcing a fix scale ratio to maintain the arrow length
>>> from plotly.figure_factory import create_quiver
>>> import numpy as np
>>> # Add data
>>> x,y = np.meshgrid(np.arange(0.5, 3.5, .5), np.arange(0.5, 4.5, .5))
>>> u = x
>>> v = y
>>> angle = np.arctan(v / u)
>>> norm = 0.25
>>> u = norm * np.cos(angle)
>>> v = norm * np.sin(angle)
>>> # Create quiver with a fix scale ratio
>>> fig = create_quiver(x, y, u, v, scale = 1, scaleratio = 0.5)
>>> fig.show()
"""
utils.validate_equal_length(x, y, u, v)
utils.validate_positive_scalars(arrow_scale=arrow_scale, scale=scale)
if scaleratio is None:
quiver_obj = _Quiver(x, y, u, v, scale, arrow_scale, angle)
else:
quiver_obj = _Quiver(x, y, u, v, scale, arrow_scale, angle, scaleratio)
barb_x, barb_y = quiver_obj.get_barbs()
arrow_x, arrow_y = quiver_obj.get_quiver_arrows()
quiver_plot = graph_objs.Scatter(
x=barb_x + arrow_x, y=barb_y + arrow_y, mode="lines", **kwargs
)
data = [quiver_plot]
if scaleratio is None:
layout = graph_objs.Layout(hovermode="closest")
else:
layout = graph_objs.Layout(
hovermode="closest", yaxis=dict(scaleratio=scaleratio, scaleanchor="x")
)
return graph_objs.Figure(data=data, layout=layout)
class _Quiver(object):
"""
Refer to FigureFactory.create_quiver() for docstring
"""
def __init__(self, x, y, u, v, scale, arrow_scale, angle, scaleratio=1, **kwargs):
try:
x = utils.flatten(x)
except exceptions.PlotlyError:
pass
try:
y = utils.flatten(y)
except exceptions.PlotlyError:
pass
try:
u = utils.flatten(u)
except exceptions.PlotlyError:
pass
try:
v = utils.flatten(v)
except exceptions.PlotlyError:
pass
self.x = x
self.y = y
self.u = u
self.v = v
self.scale = scale
self.scaleratio = scaleratio
self.arrow_scale = arrow_scale
self.angle = angle
self.end_x = []
self.end_y = []
self.scale_uv()
barb_x, barb_y = self.get_barbs()
arrow_x, arrow_y = self.get_quiver_arrows()
def scale_uv(self):
"""
Scales u and v to avoid overlap of the arrows.
u and v are added to x and y to get the
endpoints of the arrows so a smaller scale value will
result in less overlap of arrows.
"""
self.u = [i * self.scale * self.scaleratio for i in self.u]
self.v = [i * self.scale for i in self.v]
def get_barbs(self):
"""
Creates x and y startpoint and endpoint pairs
After finding the endpoint of each barb this zips startpoint and
endpoint pairs to create 2 lists: x_values for barbs and y values
for barbs
:rtype: (list, list) barb_x, barb_y: list of startpoint and endpoint
x_value pairs separated by a None to create the barb of the arrow,
and list of startpoint and endpoint y_value pairs separated by a
None to create the barb of the arrow.
"""
self.end_x = [i + j for i, j in zip(self.x, self.u)]
self.end_y = [i + j for i, j in zip(self.y, self.v)]
empty = [None] * len(self.x)
barb_x = utils.flatten(zip(self.x, self.end_x, empty))
barb_y = utils.flatten(zip(self.y, self.end_y, empty))
return barb_x, barb_y
def get_quiver_arrows(self):
"""
Creates lists of x and y values to plot the arrows
Gets length of each barb then calculates the length of each side of
the arrow. Gets angle of barb and applies angle to each side of the
arrowhead. Next uses arrow_scale to scale the length of arrowhead and
creates x and y values for arrowhead point1 and point2. Finally x and y
values for point1, endpoint and point2s for each arrowhead are
separated by a None and zipped to create lists of x and y values for
the arrows.
:rtype: (list, list) arrow_x, arrow_y: list of point1, endpoint, point2
x_values separated by a None to create the arrowhead and list of
point1, endpoint, point2 y_values separated by a None to create
the barb of the arrow.
"""
dif_x = [i - j for i, j in zip(self.end_x, self.x)]
dif_y = [i - j for i, j in zip(self.end_y, self.y)]
# Get barb lengths(default arrow length = 30% barb length)
barb_len = [None] * len(self.x)
for index in range(len(barb_len)):
barb_len[index] = math.hypot(dif_x[index] / self.scaleratio, dif_y[index])
# Make arrow lengths
arrow_len = [None] * len(self.x)
arrow_len = [i * self.arrow_scale for i in barb_len]
# Get barb angles
barb_ang = [None] * len(self.x)
for index in range(len(barb_ang)):
barb_ang[index] = math.atan2(dif_y[index], dif_x[index] / self.scaleratio)
# Set angles to create arrow
ang1 = [i + self.angle for i in barb_ang]
ang2 = [i - self.angle for i in barb_ang]
cos_ang1 = [None] * len(ang1)
for index in range(len(ang1)):
cos_ang1[index] = math.cos(ang1[index])
seg1_x = [i * j for i, j in zip(arrow_len, cos_ang1)]
sin_ang1 = [None] * len(ang1)
for index in range(len(ang1)):
sin_ang1[index] = math.sin(ang1[index])
seg1_y = [i * j for i, j in zip(arrow_len, sin_ang1)]
cos_ang2 = [None] * len(ang2)
for index in range(len(ang2)):
cos_ang2[index] = math.cos(ang2[index])
seg2_x = [i * j for i, j in zip(arrow_len, cos_ang2)]
sin_ang2 = [None] * len(ang2)
for index in range(len(ang2)):
sin_ang2[index] = math.sin(ang2[index])
seg2_y = [i * j for i, j in zip(arrow_len, sin_ang2)]
# Set coordinates to create arrow
for index in range(len(self.end_x)):
point1_x = [i - j * self.scaleratio for i, j in zip(self.end_x, seg1_x)]
point1_y = [i - j for i, j in zip(self.end_y, seg1_y)]
point2_x = [i - j * self.scaleratio for i, j in zip(self.end_x, seg2_x)]
point2_y = [i - j for i, j in zip(self.end_y, seg2_y)]
# Combine lists to create arrow
empty = [None] * len(self.end_x)
arrow_x = utils.flatten(zip(point1_x, self.end_x, point2_x, empty))
arrow_y = utils.flatten(zip(point1_y, self.end_y, point2_y, empty))
return arrow_x, arrow_y

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,406 @@
import math
from plotly import exceptions, optional_imports
from plotly.figure_factory import utils
from plotly.graph_objs import graph_objs
np = optional_imports.get_module("numpy")
def validate_streamline(x, y):
"""
Streamline-specific validations
Specifically, this checks that x and y are both evenly spaced,
and that the package numpy is available.
See FigureFactory.create_streamline() for params
:raises: (ImportError) If numpy is not available.
:raises: (PlotlyError) If x is not evenly spaced.
:raises: (PlotlyError) If y is not evenly spaced.
"""
if np is False:
raise ImportError("FigureFactory.create_streamline requires numpy")
for index in range(len(x) - 1):
if ((x[index + 1] - x[index]) - (x[1] - x[0])) > 0.0001:
raise exceptions.PlotlyError(
"x must be a 1 dimensional, evenly spaced array"
)
for index in range(len(y) - 1):
if ((y[index + 1] - y[index]) - (y[1] - y[0])) > 0.0001:
raise exceptions.PlotlyError(
"y must be a 1 dimensional, evenly spaced array"
)
def create_streamline(
x, y, u, v, density=1, angle=math.pi / 9, arrow_scale=0.09, **kwargs
):
"""
Returns data for a streamline plot.
:param (list|ndarray) x: 1 dimensional, evenly spaced list or array
:param (list|ndarray) y: 1 dimensional, evenly spaced list or array
:param (ndarray) u: 2 dimensional array
:param (ndarray) v: 2 dimensional array
:param (float|int) density: controls the density of streamlines in
plot. This is multiplied by 30 to scale similiarly to other
available streamline functions such as matplotlib.
Default = 1
:param (angle in radians) angle: angle of arrowhead. Default = pi/9
:param (float in [0,1]) arrow_scale: value to scale length of arrowhead
Default = .09
:param kwargs: kwargs passed through plotly.graph_objs.Scatter
for more information on valid kwargs call
help(plotly.graph_objs.Scatter)
:rtype (dict): returns a representation of streamline figure.
Example 1: Plot simple streamline and increase arrow size
>>> from plotly.figure_factory import create_streamline
>>> import plotly.graph_objects as go
>>> import numpy as np
>>> import math
>>> # Add data
>>> x = np.linspace(-3, 3, 100)
>>> y = np.linspace(-3, 3, 100)
>>> Y, X = np.meshgrid(x, y)
>>> u = -1 - X**2 + Y
>>> v = 1 + X - Y**2
>>> u = u.T # Transpose
>>> v = v.T # Transpose
>>> # Create streamline
>>> fig = create_streamline(x, y, u, v, arrow_scale=.1)
>>> fig.show()
Example 2: from nbviewer.ipython.org/github/barbagroup/AeroPython
>>> from plotly.figure_factory import create_streamline
>>> import numpy as np
>>> import math
>>> # Add data
>>> N = 50
>>> x_start, x_end = -2.0, 2.0
>>> y_start, y_end = -1.0, 1.0
>>> x = np.linspace(x_start, x_end, N)
>>> y = np.linspace(y_start, y_end, N)
>>> X, Y = np.meshgrid(x, y)
>>> ss = 5.0
>>> x_s, y_s = -1.0, 0.0
>>> # Compute the velocity field on the mesh grid
>>> u_s = ss/(2*np.pi) * (X-x_s)/((X-x_s)**2 + (Y-y_s)**2)
>>> v_s = ss/(2*np.pi) * (Y-y_s)/((X-x_s)**2 + (Y-y_s)**2)
>>> # Create streamline
>>> fig = create_streamline(x, y, u_s, v_s, density=2, name='streamline')
>>> # Add source point
>>> point = go.Scatter(x=[x_s], y=[y_s], mode='markers',
... marker_size=14, name='source point')
>>> fig.add_trace(point) # doctest: +SKIP
>>> fig.show()
"""
utils.validate_equal_length(x, y)
utils.validate_equal_length(u, v)
validate_streamline(x, y)
utils.validate_positive_scalars(density=density, arrow_scale=arrow_scale)
streamline_x, streamline_y = _Streamline(
x, y, u, v, density, angle, arrow_scale
).sum_streamlines()
arrow_x, arrow_y = _Streamline(
x, y, u, v, density, angle, arrow_scale
).get_streamline_arrows()
streamline = graph_objs.Scatter(
x=streamline_x + arrow_x, y=streamline_y + arrow_y, mode="lines", **kwargs
)
data = [streamline]
layout = graph_objs.Layout(hovermode="closest")
return graph_objs.Figure(data=data, layout=layout)
class _Streamline(object):
"""
Refer to FigureFactory.create_streamline() for docstring
"""
def __init__(self, x, y, u, v, density, angle, arrow_scale, **kwargs):
self.x = np.array(x)
self.y = np.array(y)
self.u = np.array(u)
self.v = np.array(v)
self.angle = angle
self.arrow_scale = arrow_scale
self.density = int(30 * density) # Scale similarly to other functions
self.delta_x = self.x[1] - self.x[0]
self.delta_y = self.y[1] - self.y[0]
self.val_x = self.x
self.val_y = self.y
# Set up spacing
self.blank = np.zeros((self.density, self.density))
self.spacing_x = len(self.x) / float(self.density - 1)
self.spacing_y = len(self.y) / float(self.density - 1)
self.trajectories = []
# Rescale speed onto axes-coordinates
self.u = self.u / (self.x[-1] - self.x[0])
self.v = self.v / (self.y[-1] - self.y[0])
self.speed = np.sqrt(self.u**2 + self.v**2)
# Rescale u and v for integrations.
self.u *= len(self.x)
self.v *= len(self.y)
self.st_x = []
self.st_y = []
self.get_streamlines()
streamline_x, streamline_y = self.sum_streamlines()
arrows_x, arrows_y = self.get_streamline_arrows()
def blank_pos(self, xi, yi):
"""
Set up positions for trajectories to be used with rk4 function.
"""
return (int((xi / self.spacing_x) + 0.5), int((yi / self.spacing_y) + 0.5))
def value_at(self, a, xi, yi):
"""
Set up for RK4 function, based on Bokeh's streamline code
"""
if isinstance(xi, np.ndarray):
self.x = xi.astype(int)
self.y = yi.astype(int)
else:
self.val_x = int(xi)
self.val_y = int(yi)
a00 = a[self.val_y, self.val_x]
a01 = a[self.val_y, self.val_x + 1]
a10 = a[self.val_y + 1, self.val_x]
a11 = a[self.val_y + 1, self.val_x + 1]
xt = xi - self.val_x
yt = yi - self.val_y
a0 = a00 * (1 - xt) + a01 * xt
a1 = a10 * (1 - xt) + a11 * xt
return a0 * (1 - yt) + a1 * yt
def rk4_integrate(self, x0, y0):
"""
RK4 forward and back trajectories from the initial conditions.
Adapted from Bokeh's streamline -uses Runge-Kutta method to fill
x and y trajectories then checks length of traj (s in units of axes)
"""
def f(xi, yi):
dt_ds = 1.0 / self.value_at(self.speed, xi, yi)
ui = self.value_at(self.u, xi, yi)
vi = self.value_at(self.v, xi, yi)
return ui * dt_ds, vi * dt_ds
def g(xi, yi):
dt_ds = 1.0 / self.value_at(self.speed, xi, yi)
ui = self.value_at(self.u, xi, yi)
vi = self.value_at(self.v, xi, yi)
return -ui * dt_ds, -vi * dt_ds
def check(xi, yi):
return (0 <= xi < len(self.x) - 1) and (0 <= yi < len(self.y) - 1)
xb_changes = []
yb_changes = []
def rk4(x0, y0, f):
ds = 0.01
stotal = 0
xi = x0
yi = y0
xb, yb = self.blank_pos(xi, yi)
xf_traj = []
yf_traj = []
while check(xi, yi):
xf_traj.append(xi)
yf_traj.append(yi)
try:
k1x, k1y = f(xi, yi)
k2x, k2y = f(xi + 0.5 * ds * k1x, yi + 0.5 * ds * k1y)
k3x, k3y = f(xi + 0.5 * ds * k2x, yi + 0.5 * ds * k2y)
k4x, k4y = f(xi + ds * k3x, yi + ds * k3y)
except IndexError:
break
xi += ds * (k1x + 2 * k2x + 2 * k3x + k4x) / 6.0
yi += ds * (k1y + 2 * k2y + 2 * k3y + k4y) / 6.0
if not check(xi, yi):
break
stotal += ds
new_xb, new_yb = self.blank_pos(xi, yi)
if new_xb != xb or new_yb != yb:
if self.blank[new_yb, new_xb] == 0:
self.blank[new_yb, new_xb] = 1
xb_changes.append(new_xb)
yb_changes.append(new_yb)
xb = new_xb
yb = new_yb
else:
break
if stotal > 2:
break
return stotal, xf_traj, yf_traj
sf, xf_traj, yf_traj = rk4(x0, y0, f)
sb, xb_traj, yb_traj = rk4(x0, y0, g)
stotal = sf + sb
x_traj = xb_traj[::-1] + xf_traj[1:]
y_traj = yb_traj[::-1] + yf_traj[1:]
if len(x_traj) < 1:
return None
if stotal > 0.2:
initxb, inityb = self.blank_pos(x0, y0)
self.blank[inityb, initxb] = 1
return x_traj, y_traj
else:
for xb, yb in zip(xb_changes, yb_changes):
self.blank[yb, xb] = 0
return None
def traj(self, xb, yb):
"""
Integrate trajectories
:param (int) xb: results of passing xi through self.blank_pos
:param (int) xy: results of passing yi through self.blank_pos
Calculate each trajectory based on rk4 integrate method.
"""
if xb < 0 or xb >= self.density or yb < 0 or yb >= self.density:
return
if self.blank[yb, xb] == 0:
t = self.rk4_integrate(xb * self.spacing_x, yb * self.spacing_y)
if t is not None:
self.trajectories.append(t)
def get_streamlines(self):
"""
Get streamlines by building trajectory set.
"""
for indent in range(self.density // 2):
for xi in range(self.density - 2 * indent):
self.traj(xi + indent, indent)
self.traj(xi + indent, self.density - 1 - indent)
self.traj(indent, xi + indent)
self.traj(self.density - 1 - indent, xi + indent)
self.st_x = [
np.array(t[0]) * self.delta_x + self.x[0] for t in self.trajectories
]
self.st_y = [
np.array(t[1]) * self.delta_y + self.y[0] for t in self.trajectories
]
for index in range(len(self.st_x)):
self.st_x[index] = self.st_x[index].tolist()
self.st_x[index].append(np.nan)
for index in range(len(self.st_y)):
self.st_y[index] = self.st_y[index].tolist()
self.st_y[index].append(np.nan)
def get_streamline_arrows(self):
"""
Makes an arrow for each streamline.
Gets angle of streamline at 1/3 mark and creates arrow coordinates
based off of user defined angle and arrow_scale.
:param (array) st_x: x-values for all streamlines
:param (array) st_y: y-values for all streamlines
:param (angle in radians) angle: angle of arrowhead. Default = pi/9
:param (float in [0,1]) arrow_scale: value to scale length of arrowhead
Default = .09
:rtype (list, list) arrows_x: x-values to create arrowhead and
arrows_y: y-values to create arrowhead
"""
arrow_end_x = np.empty((len(self.st_x)))
arrow_end_y = np.empty((len(self.st_y)))
arrow_start_x = np.empty((len(self.st_x)))
arrow_start_y = np.empty((len(self.st_y)))
for index in range(len(self.st_x)):
arrow_end_x[index] = self.st_x[index][int(len(self.st_x[index]) / 3)]
arrow_start_x[index] = self.st_x[index][
(int(len(self.st_x[index]) / 3)) - 1
]
arrow_end_y[index] = self.st_y[index][int(len(self.st_y[index]) / 3)]
arrow_start_y[index] = self.st_y[index][
(int(len(self.st_y[index]) / 3)) - 1
]
dif_x = arrow_end_x - arrow_start_x
dif_y = arrow_end_y - arrow_start_y
orig_err = np.geterr()
np.seterr(divide="ignore", invalid="ignore")
streamline_ang = np.arctan(dif_y / dif_x)
np.seterr(**orig_err)
ang1 = streamline_ang + (self.angle)
ang2 = streamline_ang - (self.angle)
seg1_x = np.cos(ang1) * self.arrow_scale
seg1_y = np.sin(ang1) * self.arrow_scale
seg2_x = np.cos(ang2) * self.arrow_scale
seg2_y = np.sin(ang2) * self.arrow_scale
point1_x = np.empty((len(dif_x)))
point1_y = np.empty((len(dif_y)))
point2_x = np.empty((len(dif_x)))
point2_y = np.empty((len(dif_y)))
for index in range(len(dif_x)):
if dif_x[index] >= 0:
point1_x[index] = arrow_end_x[index] - seg1_x[index]
point1_y[index] = arrow_end_y[index] - seg1_y[index]
point2_x[index] = arrow_end_x[index] - seg2_x[index]
point2_y[index] = arrow_end_y[index] - seg2_y[index]
else:
point1_x[index] = arrow_end_x[index] + seg1_x[index]
point1_y[index] = arrow_end_y[index] + seg1_y[index]
point2_x[index] = arrow_end_x[index] + seg2_x[index]
point2_y[index] = arrow_end_y[index] + seg2_y[index]
space = np.empty((len(point1_x)))
space[:] = np.nan
# Combine arrays into array
arrows_x = np.array([point1_x, arrow_end_x, point2_x, space])
arrows_x = arrows_x.flatten("F")
arrows_x = arrows_x.tolist()
# Combine arrays into array
arrows_y = np.array([point1_y, arrow_end_y, point2_y, space])
arrows_y = arrows_y.flatten("F")
arrows_y = arrows_y.tolist()
return arrows_x, arrows_y
def sum_streamlines(self):
"""
Makes all streamlines readable as a single trace.
:rtype (list, list): streamline_x: all x values for each streamline
combined into single list and streamline_y: all y values for each
streamline combined into single list
"""
streamline_x = sum(self.st_x, [])
streamline_y = sum(self.st_y, [])
return streamline_x, streamline_y

View File

@ -0,0 +1,280 @@
from plotly import exceptions, optional_imports
from plotly.graph_objs import graph_objs
pd = optional_imports.get_module("pandas")
def validate_table(table_text, font_colors):
"""
Table-specific validations
Check that font_colors is supplied correctly (1, 3, or len(text)
colors).
:raises: (PlotlyError) If font_colors is supplied incorretly.
See FigureFactory.create_table() for params
"""
font_colors_len_options = [1, 3, len(table_text)]
if len(font_colors) not in font_colors_len_options:
raise exceptions.PlotlyError(
"Oops, font_colors should be a list of length 1, 3 or len(text)"
)
def create_table(
table_text,
colorscale=None,
font_colors=None,
index=False,
index_title="",
annotation_offset=0.45,
height_constant=30,
hoverinfo="none",
**kwargs,
):
"""
Function that creates data tables.
See also the plotly.graph_objects trace
:class:`plotly.graph_objects.Table`
:param (pandas.Dataframe | list[list]) text: data for table.
:param (str|list[list]) colorscale: Colorscale for table where the
color at value 0 is the header color, .5 is the first table color
and 1 is the second table color. (Set .5 and 1 to avoid the striped
table effect). Default=[[0, '#66b2ff'], [.5, '#d9d9d9'],
[1, '#ffffff']]
:param (list) font_colors: Color for fonts in table. Can be a single
color, three colors, or a color for each row in the table.
Default=['#000000'] (black text for the entire table)
:param (int) height_constant: Constant multiplied by # of rows to
create table height. Default=30.
:param (bool) index: Create (header-colored) index column index from
Pandas dataframe or list[0] for each list in text. Default=False.
:param (string) index_title: Title for index column. Default=''.
:param kwargs: kwargs passed through plotly.graph_objs.Heatmap.
These kwargs describe other attributes about the annotated Heatmap
trace such as the colorscale. For more information on valid kwargs
call help(plotly.graph_objs.Heatmap)
Example 1: Simple Plotly Table
>>> from plotly.figure_factory import create_table
>>> text = [['Country', 'Year', 'Population'],
... ['US', 2000, 282200000],
... ['Canada', 2000, 27790000],
... ['US', 2010, 309000000],
... ['Canada', 2010, 34000000]]
>>> table = create_table(text)
>>> table.show()
Example 2: Table with Custom Coloring
>>> from plotly.figure_factory import create_table
>>> text = [['Country', 'Year', 'Population'],
... ['US', 2000, 282200000],
... ['Canada', 2000, 27790000],
... ['US', 2010, 309000000],
... ['Canada', 2010, 34000000]]
>>> table = create_table(text,
... colorscale=[[0, '#000000'],
... [.5, '#80beff'],
... [1, '#cce5ff']],
... font_colors=['#ffffff', '#000000',
... '#000000'])
>>> table.show()
Example 3: Simple Plotly Table with Pandas
>>> from plotly.figure_factory import create_table
>>> import pandas as pd
>>> df = pd.read_csv('http://www.stat.ubc.ca/~jenny/notOcto/STAT545A/examples/gapminder/data/gapminderDataFiveYear.txt', sep='\t')
>>> df_p = df[0:25]
>>> table_simple = create_table(df_p)
>>> table_simple.show()
"""
# Avoiding mutables in the call signature
colorscale = (
colorscale
if colorscale is not None
else [[0, "#00083e"], [0.5, "#ededee"], [1, "#ffffff"]]
)
font_colors = (
font_colors if font_colors is not None else ["#ffffff", "#000000", "#000000"]
)
validate_table(table_text, font_colors)
table_matrix = _Table(
table_text,
colorscale,
font_colors,
index,
index_title,
annotation_offset,
**kwargs,
).get_table_matrix()
annotations = _Table(
table_text,
colorscale,
font_colors,
index,
index_title,
annotation_offset,
**kwargs,
).make_table_annotations()
trace = dict(
type="heatmap",
z=table_matrix,
opacity=0.75,
colorscale=colorscale,
showscale=False,
hoverinfo=hoverinfo,
**kwargs,
)
data = [trace]
layout = dict(
annotations=annotations,
height=len(table_matrix) * height_constant + 50,
margin=dict(t=0, b=0, r=0, l=0),
yaxis=dict(
autorange="reversed",
zeroline=False,
gridwidth=2,
ticks="",
dtick=1,
tick0=0.5,
showticklabels=False,
),
xaxis=dict(
zeroline=False,
gridwidth=2,
ticks="",
dtick=1,
tick0=-0.5,
showticklabels=False,
),
)
return graph_objs.Figure(data=data, layout=layout)
class _Table(object):
"""
Refer to TraceFactory.create_table() for docstring
"""
def __init__(
self,
table_text,
colorscale,
font_colors,
index,
index_title,
annotation_offset,
**kwargs,
):
if pd and isinstance(table_text, pd.DataFrame):
headers = table_text.columns.tolist()
table_text_index = table_text.index.tolist()
table_text = table_text.values.tolist()
table_text.insert(0, headers)
if index:
table_text_index.insert(0, index_title)
for i in range(len(table_text)):
table_text[i].insert(0, table_text_index[i])
self.table_text = table_text
self.colorscale = colorscale
self.font_colors = font_colors
self.index = index
self.annotation_offset = annotation_offset
self.x = range(len(table_text[0]))
self.y = range(len(table_text))
def get_table_matrix(self):
"""
Create z matrix to make heatmap with striped table coloring
:rtype (list[list]) table_matrix: z matrix to make heatmap with striped
table coloring.
"""
header = [0] * len(self.table_text[0])
odd_row = [0.5] * len(self.table_text[0])
even_row = [1] * len(self.table_text[0])
table_matrix = [None] * len(self.table_text)
table_matrix[0] = header
for i in range(1, len(self.table_text), 2):
table_matrix[i] = odd_row
for i in range(2, len(self.table_text), 2):
table_matrix[i] = even_row
if self.index:
for array in table_matrix:
array[0] = 0
return table_matrix
def get_table_font_color(self):
"""
Fill font-color array.
Table text color can vary by row so this extends a single color or
creates an array to set a header color and two alternating colors to
create the striped table pattern.
:rtype (list[list]) all_font_colors: list of font colors for each row
in table.
"""
if len(self.font_colors) == 1:
all_font_colors = self.font_colors * len(self.table_text)
elif len(self.font_colors) == 3:
all_font_colors = list(range(len(self.table_text)))
all_font_colors[0] = self.font_colors[0]
for i in range(1, len(self.table_text), 2):
all_font_colors[i] = self.font_colors[1]
for i in range(2, len(self.table_text), 2):
all_font_colors[i] = self.font_colors[2]
elif len(self.font_colors) == len(self.table_text):
all_font_colors = self.font_colors
else:
all_font_colors = ["#000000"] * len(self.table_text)
return all_font_colors
def make_table_annotations(self):
"""
Generate annotations to fill in table text
:rtype (list) annotations: list of annotations for each cell of the
table.
"""
all_font_colors = _Table.get_table_font_color(self)
annotations = []
for n, row in enumerate(self.table_text):
for m, val in enumerate(row):
# Bold text in header and index
format_text = (
"<b>" + str(val) + "</b>"
if n == 0 or self.index and m < 1
else str(val)
)
# Match font color of index to font color of header
font_color = (
self.font_colors[0] if self.index and m == 0 else all_font_colors[n]
)
annotations.append(
graph_objs.layout.Annotation(
text=format_text,
x=self.x[m] - self.annotation_offset,
y=self.y[n],
xref="x1",
yref="y1",
align="left",
xanchor="left",
font=dict(color=font_color),
showarrow=False,
)
)
return annotations

View File

@ -0,0 +1,692 @@
import plotly.colors as clrs
from plotly.graph_objs import graph_objs as go
from plotly import exceptions
from plotly import optional_imports
from skimage import measure
np = optional_imports.get_module("numpy")
scipy_interp = optional_imports.get_module("scipy.interpolate")
# -------------------------- Layout ------------------------------
def _ternary_layout(
title="Ternary contour plot", width=550, height=525, pole_labels=["a", "b", "c"]
):
"""
Layout of ternary contour plot, to be passed to ``go.FigureWidget``
object.
Parameters
==========
title : str or None
Title of ternary plot
width : int
Figure width.
height : int
Figure height.
pole_labels : str, default ['a', 'b', 'c']
Names of the three poles of the triangle.
"""
return dict(
title=title,
width=width,
height=height,
ternary=dict(
sum=1,
aaxis=dict(
title=dict(text=pole_labels[0]), min=0.01, linewidth=2, ticks="outside"
),
baxis=dict(
title=dict(text=pole_labels[1]), min=0.01, linewidth=2, ticks="outside"
),
caxis=dict(
title=dict(text=pole_labels[2]), min=0.01, linewidth=2, ticks="outside"
),
),
showlegend=False,
)
# ------------- Transformations of coordinates -------------------
def _replace_zero_coords(ternary_data, delta=0.0005):
"""
Replaces zero ternary coordinates with delta and normalize the new
triplets (a, b, c).
Parameters
----------
ternary_data : ndarray of shape (N, 3)
delta : float
Small float to regularize logarithm.
Notes
-----
Implements a method
by J. A. Martin-Fernandez, C. Barcelo-Vidal, V. Pawlowsky-Glahn,
Dealing with zeros and missing values in compositional data sets
using nonparametric imputation, Mathematical Geology 35 (2003),
pp 253-278.
"""
zero_mask = ternary_data == 0
is_any_coord_zero = np.any(zero_mask, axis=0)
unity_complement = 1 - delta * is_any_coord_zero
if np.any(unity_complement) < 0:
raise ValueError(
"The provided value of delta led to negative"
"ternary coords.Set a smaller delta"
)
ternary_data = np.where(zero_mask, delta, unity_complement * ternary_data)
return ternary_data
def _ilr_transform(barycentric):
"""
Perform Isometric Log-Ratio on barycentric (compositional) data.
Parameters
----------
barycentric: ndarray of shape (3, N)
Barycentric coordinates.
References
----------
"An algebraic method to compute isometric logratio transformation and
back transformation of compositional data", Jarauta-Bragulat, E.,
Buenestado, P.; Hervada-Sala, C., in Proc. of the Annual Conf. of the
Intl Assoc for Math Geology, 2003, pp 31-30.
"""
barycentric = np.asarray(barycentric)
x_0 = np.log(barycentric[0] / barycentric[1]) / np.sqrt(2)
x_1 = (
1.0 / np.sqrt(6) * np.log(barycentric[0] * barycentric[1] / barycentric[2] ** 2)
)
ilr_tdata = np.stack((x_0, x_1))
return ilr_tdata
def _ilr_inverse(x):
"""
Perform inverse Isometric Log-Ratio (ILR) transform to retrieve
barycentric (compositional) data.
Parameters
----------
x : array of shape (2, N)
Coordinates in ILR space.
References
----------
"An algebraic method to compute isometric logratio transformation and
back transformation of compositional data", Jarauta-Bragulat, E.,
Buenestado, P.; Hervada-Sala, C., in Proc. of the Annual Conf. of the
Intl Assoc for Math Geology, 2003, pp 31-30.
"""
x = np.array(x)
matrix = np.array([[0.5, 1, 1.0], [-0.5, 1, 1.0], [0.0, 0.0, 1.0]])
s = np.sqrt(2) / 2
t = np.sqrt(3 / 2)
Sk = np.einsum("ik, kj -> ij", np.array([[s, t], [-s, t]]), x)
Z = -np.log(1 + np.exp(Sk).sum(axis=0))
log_barycentric = np.einsum(
"ik, kj -> ij", matrix, np.stack((2 * s * x[0], t * x[1], Z))
)
iilr_tdata = np.exp(log_barycentric)
return iilr_tdata
def _transform_barycentric_cartesian():
"""
Returns the transformation matrix from barycentric to Cartesian
coordinates and conversely.
"""
# reference triangle
tri_verts = np.array([[0.5, np.sqrt(3) / 2], [0, 0], [1, 0]])
M = np.array([tri_verts[:, 0], tri_verts[:, 1], np.ones(3)])
return M, np.linalg.inv(M)
def _prepare_barycentric_coord(b_coords):
"""
Check ternary coordinates and return the right barycentric coordinates.
"""
if not isinstance(b_coords, (list, np.ndarray)):
raise ValueError(
"Data should be either an array of shape (n,m),"
"or a list of n m-lists, m=2 or 3"
)
b_coords = np.asarray(b_coords)
if b_coords.shape[0] not in (2, 3):
raise ValueError(
"A point should have 2 (a, b) or 3 (a, b, c)barycentric coordinates"
)
if (
(len(b_coords) == 3)
and not np.allclose(b_coords.sum(axis=0), 1, rtol=0.01)
and not np.allclose(b_coords.sum(axis=0), 100, rtol=0.01)
):
msg = "The sum of coordinates should be 1 or 100 for all data points"
raise ValueError(msg)
if len(b_coords) == 2:
A, B = b_coords
C = 1 - (A + B)
else:
A, B, C = b_coords / b_coords.sum(axis=0)
if np.any(np.stack((A, B, C)) < 0):
raise ValueError("Barycentric coordinates should be positive.")
return np.stack((A, B, C))
def _compute_grid(coordinates, values, interp_mode="ilr"):
"""
Transform data points with Cartesian or ILR mapping, then Compute
interpolation on a regular grid.
Parameters
==========
coordinates : array-like
Barycentric coordinates of data points.
values : 1-d array-like
Data points, field to be represented as contours.
interp_mode : 'ilr' (default) or 'cartesian'
Defines how data are interpolated to compute contours.
"""
if interp_mode == "cartesian":
M, invM = _transform_barycentric_cartesian()
coord_points = np.einsum("ik, kj -> ij", M, coordinates)
elif interp_mode == "ilr":
coordinates = _replace_zero_coords(coordinates)
coord_points = _ilr_transform(coordinates)
else:
raise ValueError("interp_mode should be cartesian or ilr")
xx, yy = coord_points[:2]
x_min, x_max = xx.min(), xx.max()
y_min, y_max = yy.min(), yy.max()
n_interp = max(200, int(np.sqrt(len(values))))
gr_x = np.linspace(x_min, x_max, n_interp)
gr_y = np.linspace(y_min, y_max, n_interp)
grid_x, grid_y = np.meshgrid(gr_x, gr_y)
# We use cubic interpolation, except outside of the convex hull
# of data points where we use nearest neighbor values.
grid_z = scipy_interp.griddata(
coord_points[:2].T, values, (grid_x, grid_y), method="cubic"
)
return grid_z, gr_x, gr_y
# ----------------------- Contour traces ----------------------
def _polygon_area(x, y):
return 0.5 * np.abs(np.dot(x, np.roll(y, 1)) - np.dot(y, np.roll(x, 1)))
def _colors(ncontours, colormap=None):
"""
Return a list of ``ncontours`` colors from the ``colormap`` colorscale.
"""
if colormap in clrs.PLOTLY_SCALES.keys():
cmap = clrs.PLOTLY_SCALES[colormap]
else:
raise exceptions.PlotlyError(
"Colorscale must be a valid Plotly Colorscale."
"The available colorscale names are {}".format(clrs.PLOTLY_SCALES.keys())
)
values = np.linspace(0, 1, ncontours)
vals_cmap = np.array([pair[0] for pair in cmap])
cols = np.array([pair[1] for pair in cmap])
inds = np.searchsorted(vals_cmap, values)
if "#" in cols[0]: # for Viridis
cols = [clrs.label_rgb(clrs.hex_to_rgb(col)) for col in cols]
colors = [cols[0]]
for ind, val in zip(inds[1:], values[1:]):
val1, val2 = vals_cmap[ind - 1], vals_cmap[ind]
interm = (val - val1) / (val2 - val1)
col = clrs.find_intermediate_color(
cols[ind - 1], cols[ind], interm, colortype="rgb"
)
colors.append(col)
return colors
def _is_invalid_contour(x, y):
"""
Utility function for _contour_trace
Contours with an area of the order as 1 pixel are considered spurious.
"""
too_small = np.all(np.abs(x - x[0]) < 2) and np.all(np.abs(y - y[0]) < 2)
return too_small
def _extract_contours(im, values, colors):
"""
Utility function for _contour_trace.
In ``im`` only one part of the domain has valid values (corresponding
to a subdomain where barycentric coordinates are well defined). When
computing contours, we need to assign values outside of this domain.
We can choose a value either smaller than all the values inside the
valid domain, or larger. This value must be chose with caution so that
no spurious contours are added. For example, if the boundary of the valid
domain has large values and the outer value is set to a small one, all
intermediate contours will be added at the boundary.
Therefore, we compute the two sets of contours (with an outer value
smaller of larger than all values in the valid domain), and choose
the value resulting in a smaller total number of contours. There might
be a faster way to do this, but it works...
"""
mask_nan = np.isnan(im)
im_min, im_max = (
im[np.logical_not(mask_nan)].min(),
im[np.logical_not(mask_nan)].max(),
)
zz_min = np.copy(im)
zz_min[mask_nan] = 2 * im_min
zz_max = np.copy(im)
zz_max[mask_nan] = 2 * im_max
all_contours1, all_values1, all_areas1, all_colors1 = [], [], [], []
all_contours2, all_values2, all_areas2, all_colors2 = [], [], [], []
for i, val in enumerate(values):
contour_level1 = measure.find_contours(zz_min, val)
contour_level2 = measure.find_contours(zz_max, val)
all_contours1.extend(contour_level1)
all_contours2.extend(contour_level2)
all_values1.extend([val] * len(contour_level1))
all_values2.extend([val] * len(contour_level2))
all_areas1.extend(
[_polygon_area(contour.T[1], contour.T[0]) for contour in contour_level1]
)
all_areas2.extend(
[_polygon_area(contour.T[1], contour.T[0]) for contour in contour_level2]
)
all_colors1.extend([colors[i]] * len(contour_level1))
all_colors2.extend([colors[i]] * len(contour_level2))
if len(all_contours1) <= len(all_contours2):
return all_contours1, all_values1, all_areas1, all_colors1
else:
return all_contours2, all_values2, all_areas2, all_colors2
def _add_outer_contour(
all_contours,
all_values,
all_areas,
all_colors,
values,
val_outer,
v_min,
v_max,
colors,
color_min,
color_max,
):
"""
Utility function for _contour_trace
Adds the background color to fill gaps outside of computed contours.
To compute the background color, the color of the contour with largest
area (``val_outer``) is used. As background color, we choose the next
color value in the direction of the extrema of the colormap.
Then we add information for the outer contour for the different lists
provided as arguments.
A discrete colormap with all used colors is also returned (to be used
by colorscale trace).
"""
# The exact value of outer contour is not used when defining the trace
outer_contour = 20 * np.array([[0, 0, 1], [0, 1, 0.5]]).T
all_contours = [outer_contour] + all_contours
delta_values = np.diff(values)[0]
values = np.concatenate(
([values[0] - delta_values], values, [values[-1] + delta_values])
)
colors = np.concatenate(([color_min], colors, [color_max]))
index = np.nonzero(values == val_outer)[0][0]
if index < len(values) / 2:
index -= 1
else:
index += 1
all_colors = [colors[index]] + all_colors
all_values = [values[index]] + all_values
all_areas = [0] + all_areas
used_colors = [color for color in colors if color in all_colors]
# Define discrete colorscale
color_number = len(used_colors)
scale = np.linspace(0, 1, color_number + 1)
discrete_cm = []
for i, color in enumerate(used_colors):
discrete_cm.append([scale[i], used_colors[i]])
discrete_cm.append([scale[i + 1], used_colors[i]])
discrete_cm.append([scale[color_number], used_colors[color_number - 1]])
return all_contours, all_values, all_areas, all_colors, discrete_cm
def _contour_trace(
x,
y,
z,
ncontours=None,
colorscale="Electric",
linecolor="rgb(150,150,150)",
interp_mode="llr",
coloring=None,
v_min=0,
v_max=1,
):
"""
Contour trace in Cartesian coordinates.
Parameters
==========
x, y : array-like
Cartesian coordinates
z : array-like
Field to be represented as contours.
ncontours : int or None
Number of contours to display (determined automatically if None).
colorscale : None or str (Plotly colormap)
colorscale of the contours.
linecolor : rgb color
Color used for lines. If ``colorscale`` is not None, line colors are
determined from ``colorscale`` instead.
interp_mode : 'ilr' (default) or 'cartesian'
Defines how data are interpolated to compute contours. If 'irl',
ILR (Isometric Log-Ratio) of compositional data is performed. If
'cartesian', contours are determined in Cartesian space.
coloring : None or 'lines'
How to display contour. Filled contours if None, lines if ``lines``.
vmin, vmax : float
Bounds of interval of values used for the colorspace
Notes
=====
"""
# Prepare colors
# We do not take extrema, for example for one single contour
# the color will be the middle point of the colormap
colors = _colors(ncontours + 2, colorscale)
# Values used for contours, extrema are not used
# For example for a binary array [0, 1], the value of
# the contour for ncontours=1 is 0.5.
values = np.linspace(v_min, v_max, ncontours + 2)
color_min, color_max = colors[0], colors[-1]
colors = colors[1:-1]
values = values[1:-1]
# Color of line contours
if linecolor is None:
linecolor = "rgb(150, 150, 150)"
else:
colors = [linecolor] * ncontours
# Retrieve all contours
all_contours, all_values, all_areas, all_colors = _extract_contours(
z, values, colors
)
# Now sort contours by decreasing area
order = np.argsort(all_areas)[::-1]
# Add outer contour
all_contours, all_values, all_areas, all_colors, discrete_cm = _add_outer_contour(
all_contours,
all_values,
all_areas,
all_colors,
values,
all_values[order[0]],
v_min,
v_max,
colors,
color_min,
color_max,
)
order = np.concatenate(([0], order + 1))
# Compute traces, in the order of decreasing area
traces = []
M, invM = _transform_barycentric_cartesian()
dx = (x.max() - x.min()) / x.size
dy = (y.max() - y.min()) / y.size
for index in order:
y_contour, x_contour = all_contours[index].T
val = all_values[index]
if interp_mode == "cartesian":
bar_coords = np.dot(
invM,
np.stack((dx * x_contour, dy * y_contour, np.ones(x_contour.shape))),
)
elif interp_mode == "ilr":
bar_coords = _ilr_inverse(
np.stack((dx * x_contour + x.min(), dy * y_contour + y.min()))
)
if index == 0: # outer triangle
a = np.array([1, 0, 0])
b = np.array([0, 1, 0])
c = np.array([0, 0, 1])
else:
a, b, c = bar_coords
if _is_invalid_contour(x_contour, y_contour):
continue
_col = all_colors[index] if coloring == "lines" else linecolor
trace = dict(
type="scatterternary",
a=a,
b=b,
c=c,
mode="lines",
line=dict(color=_col, shape="spline", width=1),
fill="toself",
fillcolor=all_colors[index],
showlegend=True,
hoverinfo="skip",
name="%.3f" % val,
)
if coloring == "lines":
trace["fill"] = None
traces.append(trace)
return traces, discrete_cm
# -------------------- Figure Factory for ternary contour -------------
def create_ternary_contour(
coordinates,
values,
pole_labels=["a", "b", "c"],
width=500,
height=500,
ncontours=None,
showscale=False,
coloring=None,
colorscale="Bluered",
linecolor=None,
title=None,
interp_mode="ilr",
showmarkers=False,
):
"""
Ternary contour plot.
Parameters
----------
coordinates : list or ndarray
Barycentric coordinates of shape (2, N) or (3, N) where N is the
number of data points. The sum of the 3 coordinates is expected
to be 1 for all data points.
values : array-like
Data points of field to be represented as contours.
pole_labels : str, default ['a', 'b', 'c']
Names of the three poles of the triangle.
width : int
Figure width.
height : int
Figure height.
ncontours : int or None
Number of contours to display (determined automatically if None).
showscale : bool, default False
If True, a colorbar showing the color scale is displayed.
coloring : None or 'lines'
How to display contour. Filled contours if None, lines if ``lines``.
colorscale : None or str (Plotly colormap)
colorscale of the contours.
linecolor : None or rgb color
Color used for lines. ``colorscale`` has to be set to None, otherwise
line colors are determined from ``colorscale``.
title : str or None
Title of ternary plot
interp_mode : 'ilr' (default) or 'cartesian'
Defines how data are interpolated to compute contours. If 'irl',
ILR (Isometric Log-Ratio) of compositional data is performed. If
'cartesian', contours are determined in Cartesian space.
showmarkers : bool, default False
If True, markers corresponding to input compositional points are
superimposed on contours, using the same colorscale.
Examples
========
Example 1: ternary contour plot with filled contours
>>> import plotly.figure_factory as ff
>>> import numpy as np
>>> # Define coordinates
>>> a, b = np.mgrid[0:1:20j, 0:1:20j]
>>> mask = a + b <= 1
>>> a = a[mask].ravel()
>>> b = b[mask].ravel()
>>> c = 1 - a - b
>>> # Values to be displayed as contours
>>> z = a * b * c
>>> fig = ff.create_ternary_contour(np.stack((a, b, c)), z)
>>> fig.show()
It is also possible to give only two barycentric coordinates for each
point, since the sum of the three coordinates is one:
>>> fig = ff.create_ternary_contour(np.stack((a, b)), z)
Example 2: ternary contour plot with line contours
>>> fig = ff.create_ternary_contour(np.stack((a, b, c)), z, coloring='lines')
Example 3: customize number of contours
>>> fig = ff.create_ternary_contour(np.stack((a, b, c)), z, ncontours=8)
Example 4: superimpose contour plot and original data as markers
>>> fig = ff.create_ternary_contour(np.stack((a, b, c)), z, coloring='lines',
... showmarkers=True)
Example 5: customize title and pole labels
>>> fig = ff.create_ternary_contour(np.stack((a, b, c)), z,
... title='Ternary plot',
... pole_labels=['clay', 'quartz', 'fledspar'])
"""
if scipy_interp is None:
raise ImportError(
"""\
The create_ternary_contour figure factory requires the scipy package"""
)
sk_measure = optional_imports.get_module("skimage")
if sk_measure is None:
raise ImportError(
"""\
The create_ternary_contour figure factory requires the scikit-image
package"""
)
if colorscale is None:
showscale = False
if ncontours is None:
ncontours = 5
coordinates = _prepare_barycentric_coord(coordinates)
v_min, v_max = values.min(), values.max()
grid_z, gr_x, gr_y = _compute_grid(coordinates, values, interp_mode=interp_mode)
layout = _ternary_layout(
pole_labels=pole_labels, width=width, height=height, title=title
)
contour_trace, discrete_cm = _contour_trace(
gr_x,
gr_y,
grid_z,
ncontours=ncontours,
colorscale=colorscale,
linecolor=linecolor,
interp_mode=interp_mode,
coloring=coloring,
v_min=v_min,
v_max=v_max,
)
fig = go.Figure(data=contour_trace, layout=layout)
opacity = 1 if showmarkers else 0
a, b, c = coordinates
hovertemplate = (
pole_labels[0]
+ ": %{a:.3f}<br>"
+ pole_labels[1]
+ ": %{b:.3f}<br>"
+ pole_labels[2]
+ ": %{c:.3f}<br>"
"z: %{marker.color:.3f}<extra></extra>"
)
fig.add_scatterternary(
a=a,
b=b,
c=c,
mode="markers",
marker={
"color": values,
"colorscale": colorscale,
"line": {"color": "rgb(120, 120, 120)", "width": int(coloring != "lines")},
},
opacity=opacity,
hovertemplate=hovertemplate,
)
if showscale:
if not showmarkers:
colorscale = discrete_cm
colorbar = dict(
{
"type": "scatterternary",
"a": [None],
"b": [None],
"c": [None],
"marker": {
"cmin": values.min(),
"cmax": values.max(),
"colorscale": colorscale,
"showscale": True,
},
"mode": "markers",
}
)
fig.add_trace(colorbar)
return fig

View File

@ -0,0 +1,509 @@
from plotly import exceptions, optional_imports
import plotly.colors as clrs
from plotly.graph_objs import graph_objs
np = optional_imports.get_module("numpy")
def map_face2color(face, colormap, scale, vmin, vmax):
"""
Normalize facecolor values by vmin/vmax and return rgb-color strings
This function takes a tuple color along with a colormap and a minimum
(vmin) and maximum (vmax) range of possible mean distances for the
given parametrized surface. It returns an rgb color based on the mean
distance between vmin and vmax
"""
if vmin >= vmax:
raise exceptions.PlotlyError(
"Incorrect relation between vmin "
"and vmax. The vmin value cannot be "
"bigger than or equal to the value "
"of vmax."
)
if len(colormap) == 1:
# color each triangle face with the same color in colormap
face_color = colormap[0]
face_color = clrs.convert_to_RGB_255(face_color)
face_color = clrs.label_rgb(face_color)
return face_color
if face == vmax:
# pick last color in colormap
face_color = colormap[-1]
face_color = clrs.convert_to_RGB_255(face_color)
face_color = clrs.label_rgb(face_color)
return face_color
else:
if scale is None:
# find the normalized distance t of a triangle face between
# vmin and vmax where the distance is between 0 and 1
t = (face - vmin) / float((vmax - vmin))
low_color_index = int(t / (1.0 / (len(colormap) - 1)))
face_color = clrs.find_intermediate_color(
colormap[low_color_index],
colormap[low_color_index + 1],
t * (len(colormap) - 1) - low_color_index,
)
face_color = clrs.convert_to_RGB_255(face_color)
face_color = clrs.label_rgb(face_color)
else:
# find the face color for a non-linearly interpolated scale
t = (face - vmin) / float((vmax - vmin))
low_color_index = 0
for k in range(len(scale) - 1):
if scale[k] <= t < scale[k + 1]:
break
low_color_index += 1
low_scale_val = scale[low_color_index]
high_scale_val = scale[low_color_index + 1]
face_color = clrs.find_intermediate_color(
colormap[low_color_index],
colormap[low_color_index + 1],
(t - low_scale_val) / (high_scale_val - low_scale_val),
)
face_color = clrs.convert_to_RGB_255(face_color)
face_color = clrs.label_rgb(face_color)
return face_color
def trisurf(
x,
y,
z,
simplices,
show_colorbar,
edges_color,
scale,
colormap=None,
color_func=None,
plot_edges=False,
x_edge=None,
y_edge=None,
z_edge=None,
facecolor=None,
):
"""
Refer to FigureFactory.create_trisurf() for docstring
"""
# numpy import check
if not np:
raise ImportError("FigureFactory._trisurf() requires numpy imported.")
points3D = np.vstack((x, y, z)).T
simplices = np.atleast_2d(simplices)
# vertices of the surface triangles
tri_vertices = points3D[simplices]
# Define colors for the triangle faces
if color_func is None:
# mean values of z-coordinates of triangle vertices
mean_dists = tri_vertices[:, :, 2].mean(-1)
elif isinstance(color_func, (list, np.ndarray)):
# Pre-computed list / array of values to map onto color
if len(color_func) != len(simplices):
raise ValueError(
"If color_func is a list/array, it must "
"be the same length as simplices."
)
# convert all colors in color_func to rgb
for index in range(len(color_func)):
if isinstance(color_func[index], str):
if "#" in color_func[index]:
foo = clrs.hex_to_rgb(color_func[index])
color_func[index] = clrs.label_rgb(foo)
if isinstance(color_func[index], tuple):
foo = clrs.convert_to_RGB_255(color_func[index])
color_func[index] = clrs.label_rgb(foo)
mean_dists = np.asarray(color_func)
else:
# apply user inputted function to calculate
# custom coloring for triangle vertices
mean_dists = []
for triangle in tri_vertices:
dists = []
for vertex in triangle:
dist = color_func(vertex[0], vertex[1], vertex[2])
dists.append(dist)
mean_dists.append(np.mean(dists))
mean_dists = np.asarray(mean_dists)
# Check if facecolors are already strings and can be skipped
if isinstance(mean_dists[0], str):
facecolor = mean_dists
else:
min_mean_dists = np.min(mean_dists)
max_mean_dists = np.max(mean_dists)
if facecolor is None:
facecolor = []
for index in range(len(mean_dists)):
color = map_face2color(
mean_dists[index], colormap, scale, min_mean_dists, max_mean_dists
)
facecolor.append(color)
# Make sure facecolor is a list so output is consistent across Pythons
facecolor = np.asarray(facecolor)
ii, jj, kk = simplices.T
triangles = graph_objs.Mesh3d(
x=x, y=y, z=z, facecolor=facecolor, i=ii, j=jj, k=kk, name=""
)
mean_dists_are_numbers = not isinstance(mean_dists[0], str)
if mean_dists_are_numbers and show_colorbar is True:
# make a colorscale from the colors
colorscale = clrs.make_colorscale(colormap, scale)
colorscale = clrs.convert_colorscale_to_rgb(colorscale)
colorbar = graph_objs.Scatter3d(
x=x[:1],
y=y[:1],
z=z[:1],
mode="markers",
marker=dict(
size=0.1,
color=[min_mean_dists, max_mean_dists],
colorscale=colorscale,
showscale=True,
),
hoverinfo="none",
showlegend=False,
)
# the triangle sides are not plotted
if plot_edges is False:
if mean_dists_are_numbers and show_colorbar is True:
return [triangles, colorbar]
else:
return [triangles]
# define the lists x_edge, y_edge and z_edge, of x, y, resp z
# coordinates of edge end points for each triangle
# None separates data corresponding to two consecutive triangles
is_none = [ii is None for ii in [x_edge, y_edge, z_edge]]
if any(is_none):
if not all(is_none):
raise ValueError(
"If any (x_edge, y_edge, z_edge) is None, all must be None"
)
else:
x_edge = []
y_edge = []
z_edge = []
# Pull indices we care about, then add a None column to separate tris
ixs_triangles = [0, 1, 2, 0]
pull_edges = tri_vertices[:, ixs_triangles, :]
x_edge_pull = np.hstack(
[pull_edges[:, :, 0], np.tile(None, [pull_edges.shape[0], 1])]
)
y_edge_pull = np.hstack(
[pull_edges[:, :, 1], np.tile(None, [pull_edges.shape[0], 1])]
)
z_edge_pull = np.hstack(
[pull_edges[:, :, 2], np.tile(None, [pull_edges.shape[0], 1])]
)
# Now unravel the edges into a 1-d vector for plotting
x_edge = np.hstack([x_edge, x_edge_pull.reshape([1, -1])[0]])
y_edge = np.hstack([y_edge, y_edge_pull.reshape([1, -1])[0]])
z_edge = np.hstack([z_edge, z_edge_pull.reshape([1, -1])[0]])
if not (len(x_edge) == len(y_edge) == len(z_edge)):
raise exceptions.PlotlyError(
"The lengths of x_edge, y_edge and z_edge are not the same."
)
# define the lines for plotting
lines = graph_objs.Scatter3d(
x=x_edge,
y=y_edge,
z=z_edge,
mode="lines",
line=graph_objs.scatter3d.Line(color=edges_color, width=1.5),
showlegend=False,
)
if mean_dists_are_numbers and show_colorbar is True:
return [triangles, lines, colorbar]
else:
return [triangles, lines]
def create_trisurf(
x,
y,
z,
simplices,
colormap=None,
show_colorbar=True,
scale=None,
color_func=None,
title="Trisurf Plot",
plot_edges=True,
showbackground=True,
backgroundcolor="rgb(230, 230, 230)",
gridcolor="rgb(255, 255, 255)",
zerolinecolor="rgb(255, 255, 255)",
edges_color="rgb(50, 50, 50)",
height=800,
width=800,
aspectratio=None,
):
"""
Returns figure for a triangulated surface plot
:param (array) x: data values of x in a 1D array
:param (array) y: data values of y in a 1D array
:param (array) z: data values of z in a 1D array
:param (array) simplices: an array of shape (ntri, 3) where ntri is
the number of triangles in the triangularization. Each row of the
array contains the indicies of the verticies of each triangle
:param (str|tuple|list) colormap: either a plotly scale name, an rgb
or hex color, a color tuple or a list of colors. An rgb color is
of the form 'rgb(x, y, z)' where x, y, z belong to the interval
[0, 255] and a color tuple is a tuple of the form (a, b, c) where
a, b and c belong to [0, 1]. If colormap is a list, it must
contain the valid color types aforementioned as its members
:param (bool) show_colorbar: determines if colorbar is visible
:param (list|array) scale: sets the scale values to be used if a non-
linearly interpolated colormap is desired. If left as None, a
linear interpolation between the colors will be excecuted
:param (function|list) color_func: The parameter that determines the
coloring of the surface. Takes either a function with 3 arguments
x, y, z or a list/array of color values the same length as
simplices. If None, coloring will only depend on the z axis
:param (str) title: title of the plot
:param (bool) plot_edges: determines if the triangles on the trisurf
are visible
:param (bool) showbackground: makes background in plot visible
:param (str) backgroundcolor: color of background. Takes a string of
the form 'rgb(x,y,z)' x,y,z are between 0 and 255 inclusive
:param (str) gridcolor: color of the gridlines besides the axes. Takes
a string of the form 'rgb(x,y,z)' x,y,z are between 0 and 255
inclusive
:param (str) zerolinecolor: color of the axes. Takes a string of the
form 'rgb(x,y,z)' x,y,z are between 0 and 255 inclusive
:param (str) edges_color: color of the edges, if plot_edges is True
:param (int|float) height: the height of the plot (in pixels)
:param (int|float) width: the width of the plot (in pixels)
:param (dict) aspectratio: a dictionary of the aspect ratio values for
the x, y and z axes. 'x', 'y' and 'z' take (int|float) values
Example 1: Sphere
>>> # Necessary Imports for Trisurf
>>> import numpy as np
>>> from scipy.spatial import Delaunay
>>> from plotly.figure_factory import create_trisurf
>>> from plotly.graph_objs import graph_objs
>>> # Make data for plot
>>> u = np.linspace(0, 2*np.pi, 20)
>>> v = np.linspace(0, np.pi, 20)
>>> u,v = np.meshgrid(u,v)
>>> u = u.flatten()
>>> v = v.flatten()
>>> x = np.sin(v)*np.cos(u)
>>> y = np.sin(v)*np.sin(u)
>>> z = np.cos(v)
>>> points2D = np.vstack([u,v]).T
>>> tri = Delaunay(points2D)
>>> simplices = tri.simplices
>>> # Create a figure
>>> fig1 = create_trisurf(x=x, y=y, z=z, colormap="Rainbow",
... simplices=simplices)
Example 2: Torus
>>> # Necessary Imports for Trisurf
>>> import numpy as np
>>> from scipy.spatial import Delaunay
>>> from plotly.figure_factory import create_trisurf
>>> from plotly.graph_objs import graph_objs
>>> # Make data for plot
>>> u = np.linspace(0, 2*np.pi, 20)
>>> v = np.linspace(0, 2*np.pi, 20)
>>> u,v = np.meshgrid(u,v)
>>> u = u.flatten()
>>> v = v.flatten()
>>> x = (3 + (np.cos(v)))*np.cos(u)
>>> y = (3 + (np.cos(v)))*np.sin(u)
>>> z = np.sin(v)
>>> points2D = np.vstack([u,v]).T
>>> tri = Delaunay(points2D)
>>> simplices = tri.simplices
>>> # Create a figure
>>> fig1 = create_trisurf(x=x, y=y, z=z, colormap="Viridis",
... simplices=simplices)
Example 3: Mobius Band
>>> # Necessary Imports for Trisurf
>>> import numpy as np
>>> from scipy.spatial import Delaunay
>>> from plotly.figure_factory import create_trisurf
>>> from plotly.graph_objs import graph_objs
>>> # Make data for plot
>>> u = np.linspace(0, 2*np.pi, 24)
>>> v = np.linspace(-1, 1, 8)
>>> u,v = np.meshgrid(u,v)
>>> u = u.flatten()
>>> v = v.flatten()
>>> tp = 1 + 0.5*v*np.cos(u/2.)
>>> x = tp*np.cos(u)
>>> y = tp*np.sin(u)
>>> z = 0.5*v*np.sin(u/2.)
>>> points2D = np.vstack([u,v]).T
>>> tri = Delaunay(points2D)
>>> simplices = tri.simplices
>>> # Create a figure
>>> fig1 = create_trisurf(x=x, y=y, z=z, colormap=[(0.2, 0.4, 0.6), (1, 1, 1)],
... simplices=simplices)
Example 4: Using a Custom Colormap Function with Light Cone
>>> # Necessary Imports for Trisurf
>>> import numpy as np
>>> from scipy.spatial import Delaunay
>>> from plotly.figure_factory import create_trisurf
>>> from plotly.graph_objs import graph_objs
>>> # Make data for plot
>>> u=np.linspace(-np.pi, np.pi, 30)
>>> v=np.linspace(-np.pi, np.pi, 30)
>>> u,v=np.meshgrid(u,v)
>>> u=u.flatten()
>>> v=v.flatten()
>>> x = u
>>> y = u*np.cos(v)
>>> z = u*np.sin(v)
>>> points2D = np.vstack([u,v]).T
>>> tri = Delaunay(points2D)
>>> simplices = tri.simplices
>>> # Define distance function
>>> def dist_origin(x, y, z):
... return np.sqrt((1.0 * x)**2 + (1.0 * y)**2 + (1.0 * z)**2)
>>> # Create a figure
>>> fig1 = create_trisurf(x=x, y=y, z=z,
... colormap=['#FFFFFF', '#E4FFFE',
... '#A4F6F9', '#FF99FE',
... '#BA52ED'],
... scale=[0, 0.6, 0.71, 0.89, 1],
... simplices=simplices,
... color_func=dist_origin)
Example 5: Enter color_func as a list of colors
>>> # Necessary Imports for Trisurf
>>> import numpy as np
>>> from scipy.spatial import Delaunay
>>> import random
>>> from plotly.figure_factory import create_trisurf
>>> from plotly.graph_objs import graph_objs
>>> # Make data for plot
>>> u=np.linspace(-np.pi, np.pi, 30)
>>> v=np.linspace(-np.pi, np.pi, 30)
>>> u,v=np.meshgrid(u,v)
>>> u=u.flatten()
>>> v=v.flatten()
>>> x = u
>>> y = u*np.cos(v)
>>> z = u*np.sin(v)
>>> points2D = np.vstack([u,v]).T
>>> tri = Delaunay(points2D)
>>> simplices = tri.simplices
>>> colors = []
>>> color_choices = ['rgb(0, 0, 0)', '#6c4774', '#d6c7dd']
>>> for index in range(len(simplices)):
... colors.append(random.choice(color_choices))
>>> fig = create_trisurf(
... x, y, z, simplices,
... color_func=colors,
... show_colorbar=True,
... edges_color='rgb(2, 85, 180)',
... title=' Modern Art'
... )
"""
if aspectratio is None:
aspectratio = {"x": 1, "y": 1, "z": 1}
# Validate colormap
clrs.validate_colors(colormap)
colormap, scale = clrs.convert_colors_to_same_type(
colormap, colortype="tuple", return_default_colors=True, scale=scale
)
data1 = trisurf(
x,
y,
z,
simplices,
show_colorbar=show_colorbar,
color_func=color_func,
colormap=colormap,
scale=scale,
edges_color=edges_color,
plot_edges=plot_edges,
)
axis = dict(
showbackground=showbackground,
backgroundcolor=backgroundcolor,
gridcolor=gridcolor,
zerolinecolor=zerolinecolor,
)
layout = graph_objs.Layout(
title=title,
width=width,
height=height,
scene=graph_objs.layout.Scene(
xaxis=graph_objs.layout.scene.XAxis(**axis),
yaxis=graph_objs.layout.scene.YAxis(**axis),
zaxis=graph_objs.layout.scene.ZAxis(**axis),
aspectratio=dict(
x=aspectratio["x"], y=aspectratio["y"], z=aspectratio["z"]
),
),
)
return graph_objs.Figure(data=data1, layout=layout)

View File

@ -0,0 +1,704 @@
from numbers import Number
from plotly import exceptions, optional_imports
import plotly.colors as clrs
from plotly.graph_objs import graph_objs
from plotly.subplots import make_subplots
pd = optional_imports.get_module("pandas")
np = optional_imports.get_module("numpy")
scipy_stats = optional_imports.get_module("scipy.stats")
def calc_stats(data):
"""
Calculate statistics for use in violin plot.
"""
x = np.asarray(data, float)
vals_min = np.min(x)
vals_max = np.max(x)
q2 = np.percentile(x, 50, interpolation="linear")
q1 = np.percentile(x, 25, interpolation="lower")
q3 = np.percentile(x, 75, interpolation="higher")
iqr = q3 - q1
whisker_dist = 1.5 * iqr
# in order to prevent drawing whiskers outside the interval
# of data one defines the whisker positions as:
d1 = np.min(x[x >= (q1 - whisker_dist)])
d2 = np.max(x[x <= (q3 + whisker_dist)])
return {
"min": vals_min,
"max": vals_max,
"q1": q1,
"q2": q2,
"q3": q3,
"d1": d1,
"d2": d2,
}
def make_half_violin(x, y, fillcolor="#1f77b4", linecolor="rgb(0, 0, 0)"):
"""
Produces a sideways probability distribution fig violin plot.
"""
text = [
"(pdf(y), y)=(" + "{:0.2f}".format(x[i]) + ", " + "{:0.2f}".format(y[i]) + ")"
for i in range(len(x))
]
return graph_objs.Scatter(
x=x,
y=y,
mode="lines",
name="",
text=text,
fill="tonextx",
fillcolor=fillcolor,
line=graph_objs.scatter.Line(width=0.5, color=linecolor, shape="spline"),
hoverinfo="text",
opacity=0.5,
)
def make_violin_rugplot(vals, pdf_max, distance, color="#1f77b4"):
"""
Returns a rugplot fig for a violin plot.
"""
return graph_objs.Scatter(
y=vals,
x=[-pdf_max - distance] * len(vals),
marker=graph_objs.scatter.Marker(color=color, symbol="line-ew-open"),
mode="markers",
name="",
showlegend=False,
hoverinfo="y",
)
def make_non_outlier_interval(d1, d2):
"""
Returns the scatterplot fig of most of a violin plot.
"""
return graph_objs.Scatter(
x=[0, 0],
y=[d1, d2],
name="",
mode="lines",
line=graph_objs.scatter.Line(width=1.5, color="rgb(0,0,0)"),
)
def make_quartiles(q1, q3):
"""
Makes the upper and lower quartiles for a violin plot.
"""
return graph_objs.Scatter(
x=[0, 0],
y=[q1, q3],
text=[
"lower-quartile: " + "{:0.2f}".format(q1),
"upper-quartile: " + "{:0.2f}".format(q3),
],
mode="lines",
line=graph_objs.scatter.Line(width=4, color="rgb(0,0,0)"),
hoverinfo="text",
)
def make_median(q2):
"""
Formats the 'median' hovertext for a violin plot.
"""
return graph_objs.Scatter(
x=[0],
y=[q2],
text=["median: " + "{:0.2f}".format(q2)],
mode="markers",
marker=dict(symbol="square", color="rgb(255,255,255)"),
hoverinfo="text",
)
def make_XAxis(xaxis_title, xaxis_range):
"""
Makes the x-axis for a violin plot.
"""
xaxis = graph_objs.layout.XAxis(
title=xaxis_title,
range=xaxis_range,
showgrid=False,
zeroline=False,
showline=False,
mirror=False,
ticks="",
showticklabels=False,
)
return xaxis
def make_YAxis(yaxis_title):
"""
Makes the y-axis for a violin plot.
"""
yaxis = graph_objs.layout.YAxis(
title=yaxis_title,
showticklabels=True,
autorange=True,
ticklen=4,
showline=True,
zeroline=False,
showgrid=False,
mirror=False,
)
return yaxis
def violinplot(vals, fillcolor="#1f77b4", rugplot=True):
"""
Refer to FigureFactory.create_violin() for docstring.
"""
vals = np.asarray(vals, float)
# summary statistics
vals_min = calc_stats(vals)["min"]
vals_max = calc_stats(vals)["max"]
q1 = calc_stats(vals)["q1"]
q2 = calc_stats(vals)["q2"]
q3 = calc_stats(vals)["q3"]
d1 = calc_stats(vals)["d1"]
d2 = calc_stats(vals)["d2"]
# kernel density estimation of pdf
pdf = scipy_stats.gaussian_kde(vals)
# grid over the data interval
xx = np.linspace(vals_min, vals_max, 100)
# evaluate the pdf at the grid xx
yy = pdf(xx)
max_pdf = np.max(yy)
# distance from the violin plot to rugplot
distance = (2.0 * max_pdf) / 10 if rugplot else 0
# range for x values in the plot
plot_xrange = [-max_pdf - distance - 0.1, max_pdf + 0.1]
plot_data = [
make_half_violin(-yy, xx, fillcolor=fillcolor),
make_half_violin(yy, xx, fillcolor=fillcolor),
make_non_outlier_interval(d1, d2),
make_quartiles(q1, q3),
make_median(q2),
]
if rugplot:
plot_data.append(
make_violin_rugplot(vals, max_pdf, distance=distance, color=fillcolor)
)
return plot_data, plot_xrange
def violin_no_colorscale(
data,
data_header,
group_header,
colors,
use_colorscale,
group_stats,
rugplot,
sort,
height,
width,
title,
):
"""
Refer to FigureFactory.create_violin() for docstring.
Returns fig for violin plot without colorscale.
"""
# collect all group names
group_name = []
for name in data[group_header]:
if name not in group_name:
group_name.append(name)
if sort:
group_name.sort()
gb = data.groupby([group_header])
L = len(group_name)
fig = make_subplots(
rows=1, cols=L, shared_yaxes=True, horizontal_spacing=0.025, print_grid=False
)
color_index = 0
for k, gr in enumerate(group_name):
vals = np.asarray(gb.get_group(gr)[data_header], float)
if color_index >= len(colors):
color_index = 0
plot_data, plot_xrange = violinplot(
vals, fillcolor=colors[color_index], rugplot=rugplot
)
for item in plot_data:
fig.append_trace(item, 1, k + 1)
color_index += 1
# add violin plot labels
fig["layout"].update(
{"xaxis{}".format(k + 1): make_XAxis(group_name[k], plot_xrange)}
)
# set the sharey axis style
fig["layout"].update({"yaxis{}".format(1): make_YAxis("")})
fig["layout"].update(
title=title,
showlegend=False,
hovermode="closest",
autosize=False,
height=height,
width=width,
)
return fig
def violin_colorscale(
data,
data_header,
group_header,
colors,
use_colorscale,
group_stats,
rugplot,
sort,
height,
width,
title,
):
"""
Refer to FigureFactory.create_violin() for docstring.
Returns fig for violin plot with colorscale.
"""
# collect all group names
group_name = []
for name in data[group_header]:
if name not in group_name:
group_name.append(name)
if sort:
group_name.sort()
# make sure all group names are keys in group_stats
for group in group_name:
if group not in group_stats:
raise exceptions.PlotlyError(
"All values/groups in the index "
"column must be represented "
"as a key in group_stats."
)
gb = data.groupby([group_header])
L = len(group_name)
fig = make_subplots(
rows=1, cols=L, shared_yaxes=True, horizontal_spacing=0.025, print_grid=False
)
# prepare low and high color for colorscale
lowcolor = clrs.color_parser(colors[0], clrs.unlabel_rgb)
highcolor = clrs.color_parser(colors[1], clrs.unlabel_rgb)
# find min and max values in group_stats
group_stats_values = []
for key in group_stats:
group_stats_values.append(group_stats[key])
max_value = max(group_stats_values)
min_value = min(group_stats_values)
for k, gr in enumerate(group_name):
vals = np.asarray(gb.get_group(gr)[data_header], float)
# find intermediate color from colorscale
intermed = (group_stats[gr] - min_value) / (max_value - min_value)
intermed_color = clrs.find_intermediate_color(lowcolor, highcolor, intermed)
plot_data, plot_xrange = violinplot(
vals, fillcolor="rgb{}".format(intermed_color), rugplot=rugplot
)
for item in plot_data:
fig.append_trace(item, 1, k + 1)
fig["layout"].update(
{"xaxis{}".format(k + 1): make_XAxis(group_name[k], plot_xrange)}
)
# add colorbar to plot
trace_dummy = graph_objs.Scatter(
x=[0],
y=[0],
mode="markers",
marker=dict(
size=2,
cmin=min_value,
cmax=max_value,
colorscale=[[0, colors[0]], [1, colors[1]]],
showscale=True,
),
showlegend=False,
)
fig.append_trace(trace_dummy, 1, L)
# set the sharey axis style
fig["layout"].update({"yaxis{}".format(1): make_YAxis("")})
fig["layout"].update(
title=title,
showlegend=False,
hovermode="closest",
autosize=False,
height=height,
width=width,
)
return fig
def violin_dict(
data,
data_header,
group_header,
colors,
use_colorscale,
group_stats,
rugplot,
sort,
height,
width,
title,
):
"""
Refer to FigureFactory.create_violin() for docstring.
Returns fig for violin plot without colorscale.
"""
# collect all group names
group_name = []
for name in data[group_header]:
if name not in group_name:
group_name.append(name)
if sort:
group_name.sort()
# check if all group names appear in colors dict
for group in group_name:
if group not in colors:
raise exceptions.PlotlyError(
"If colors is a dictionary, all "
"the group names must appear as "
"keys in colors."
)
gb = data.groupby([group_header])
L = len(group_name)
fig = make_subplots(
rows=1, cols=L, shared_yaxes=True, horizontal_spacing=0.025, print_grid=False
)
for k, gr in enumerate(group_name):
vals = np.asarray(gb.get_group(gr)[data_header], float)
plot_data, plot_xrange = violinplot(vals, fillcolor=colors[gr], rugplot=rugplot)
for item in plot_data:
fig.append_trace(item, 1, k + 1)
# add violin plot labels
fig["layout"].update(
{"xaxis{}".format(k + 1): make_XAxis(group_name[k], plot_xrange)}
)
# set the sharey axis style
fig["layout"].update({"yaxis{}".format(1): make_YAxis("")})
fig["layout"].update(
title=title,
showlegend=False,
hovermode="closest",
autosize=False,
height=height,
width=width,
)
return fig
def create_violin(
data,
data_header=None,
group_header=None,
colors=None,
use_colorscale=False,
group_stats=None,
rugplot=True,
sort=False,
height=450,
width=600,
title="Violin and Rug Plot",
):
"""
**deprecated**, use instead the plotly.graph_objects trace
:class:`plotly.graph_objects.Violin`.
:param (list|array) data: accepts either a list of numerical values,
a list of dictionaries all with identical keys and at least one
column of numeric values, or a pandas dataframe with at least one
column of numbers.
:param (str) data_header: the header of the data column to be used
from an inputted pandas dataframe. Not applicable if 'data' is
a list of numeric values.
:param (str) group_header: applicable if grouping data by a variable.
'group_header' must be set to the name of the grouping variable.
:param (str|tuple|list|dict) colors: either a plotly scale name,
an rgb or hex color, a color tuple, a list of colors or a
dictionary. An rgb color is of the form 'rgb(x, y, z)' where
x, y and z belong to the interval [0, 255] and a color tuple is a
tuple of the form (a, b, c) where a, b and c belong to [0, 1].
If colors is a list, it must contain valid color types as its
members.
:param (bool) use_colorscale: only applicable if grouping by another
variable. Will implement a colorscale based on the first 2 colors
of param colors. This means colors must be a list with at least 2
colors in it (Plotly colorscales are accepted since they map to a
list of two rgb colors). Default = False
:param (dict) group_stats: a dictionary where each key is a unique
value from the group_header column in data. Each value must be a
number and will be used to color the violin plots if a colorscale
is being used.
:param (bool) rugplot: determines if a rugplot is draw on violin plot.
Default = True
:param (bool) sort: determines if violins are sorted
alphabetically (True) or by input order (False). Default = False
:param (float) height: the height of the violin plot.
:param (float) width: the width of the violin plot.
:param (str) title: the title of the violin plot.
Example 1: Single Violin Plot
>>> from plotly.figure_factory import create_violin
>>> import plotly.graph_objs as graph_objects
>>> import numpy as np
>>> from scipy import stats
>>> # create list of random values
>>> data_list = np.random.randn(100)
>>> # create violin fig
>>> fig = create_violin(data_list, colors='#604d9e')
>>> # plot
>>> fig.show()
Example 2: Multiple Violin Plots with Qualitative Coloring
>>> from plotly.figure_factory import create_violin
>>> import plotly.graph_objs as graph_objects
>>> import numpy as np
>>> import pandas as pd
>>> from scipy import stats
>>> # create dataframe
>>> np.random.seed(619517)
>>> Nr=250
>>> y = np.random.randn(Nr)
>>> gr = np.random.choice(list("ABCDE"), Nr)
>>> norm_params=[(0, 1.2), (0.7, 1), (-0.5, 1.4), (0.3, 1), (0.8, 0.9)]
>>> for i, letter in enumerate("ABCDE"):
... y[gr == letter] *=norm_params[i][1]+ norm_params[i][0]
>>> df = pd.DataFrame(dict(Score=y, Group=gr))
>>> # create violin fig
>>> fig = create_violin(df, data_header='Score', group_header='Group',
... sort=True, height=600, width=1000)
>>> # plot
>>> fig.show()
Example 3: Violin Plots with Colorscale
>>> from plotly.figure_factory import create_violin
>>> import plotly.graph_objs as graph_objects
>>> import numpy as np
>>> import pandas as pd
>>> from scipy import stats
>>> # create dataframe
>>> np.random.seed(619517)
>>> Nr=250
>>> y = np.random.randn(Nr)
>>> gr = np.random.choice(list("ABCDE"), Nr)
>>> norm_params=[(0, 1.2), (0.7, 1), (-0.5, 1.4), (0.3, 1), (0.8, 0.9)]
>>> for i, letter in enumerate("ABCDE"):
... y[gr == letter] *=norm_params[i][1]+ norm_params[i][0]
>>> df = pd.DataFrame(dict(Score=y, Group=gr))
>>> # define header params
>>> data_header = 'Score'
>>> group_header = 'Group'
>>> # make groupby object with pandas
>>> group_stats = {}
>>> groupby_data = df.groupby([group_header])
>>> for group in "ABCDE":
... data_from_group = groupby_data.get_group(group)[data_header]
... # take a stat of the grouped data
... stat = np.median(data_from_group)
... # add to dictionary
... group_stats[group] = stat
>>> # create violin fig
>>> fig = create_violin(df, data_header='Score', group_header='Group',
... height=600, width=1000, use_colorscale=True,
... group_stats=group_stats)
>>> # plot
>>> fig.show()
"""
# Validate colors
if isinstance(colors, dict):
valid_colors = clrs.validate_colors_dict(colors, "rgb")
else:
valid_colors = clrs.validate_colors(colors, "rgb")
# validate data and choose plot type
if group_header is None:
if isinstance(data, list):
if len(data) <= 0:
raise exceptions.PlotlyError(
"If data is a list, it must be "
"nonempty and contain either "
"numbers or dictionaries."
)
if not all(isinstance(element, Number) for element in data):
raise exceptions.PlotlyError(
"If data is a list, it must contain only numbers."
)
if pd and isinstance(data, pd.core.frame.DataFrame):
if data_header is None:
raise exceptions.PlotlyError(
"data_header must be the "
"column name with the "
"desired numeric data for "
"the violin plot."
)
data = data[data_header].values.tolist()
# call the plotting functions
plot_data, plot_xrange = violinplot(
data, fillcolor=valid_colors[0], rugplot=rugplot
)
layout = graph_objs.Layout(
title=title,
autosize=False,
font=graph_objs.layout.Font(size=11),
height=height,
showlegend=False,
width=width,
xaxis=make_XAxis("", plot_xrange),
yaxis=make_YAxis(""),
hovermode="closest",
)
layout["yaxis"].update(dict(showline=False, showticklabels=False, ticks=""))
fig = graph_objs.Figure(data=plot_data, layout=layout)
return fig
else:
if not isinstance(data, pd.core.frame.DataFrame):
raise exceptions.PlotlyError(
"Error. You must use a pandas "
"DataFrame if you are using a "
"group header."
)
if data_header is None:
raise exceptions.PlotlyError(
"data_header must be the column "
"name with the desired numeric "
"data for the violin plot."
)
if use_colorscale is False:
if isinstance(valid_colors, dict):
# validate colors dict choice below
fig = violin_dict(
data,
data_header,
group_header,
valid_colors,
use_colorscale,
group_stats,
rugplot,
sort,
height,
width,
title,
)
return fig
else:
fig = violin_no_colorscale(
data,
data_header,
group_header,
valid_colors,
use_colorscale,
group_stats,
rugplot,
sort,
height,
width,
title,
)
return fig
else:
if isinstance(valid_colors, dict):
raise exceptions.PlotlyError(
"The colors param cannot be "
"a dictionary if you are "
"using a colorscale."
)
if len(valid_colors) < 2:
raise exceptions.PlotlyError(
"colors must be a list with "
"at least 2 colors. A "
"Plotly scale is allowed."
)
if not isinstance(group_stats, dict):
raise exceptions.PlotlyError(
"Your group_stats param must be a dictionary."
)
fig = violin_colorscale(
data,
data_header,
group_header,
valid_colors,
use_colorscale,
group_stats,
rugplot,
sort,
height,
width,
title,
)
return fig

View File

@ -0,0 +1,249 @@
from collections.abc import Sequence
from plotly import exceptions
def is_sequence(obj):
return isinstance(obj, Sequence) and not isinstance(obj, str)
def validate_index(index_vals):
"""
Validates if a list contains all numbers or all strings
:raises: (PlotlyError) If there are any two items in the list whose
types differ
"""
from numbers import Number
if isinstance(index_vals[0], Number):
if not all(isinstance(item, Number) for item in index_vals):
raise exceptions.PlotlyError(
"Error in indexing column. "
"Make sure all entries of each "
"column are all numbers or "
"all strings."
)
elif isinstance(index_vals[0], str):
if not all(isinstance(item, str) for item in index_vals):
raise exceptions.PlotlyError(
"Error in indexing column. "
"Make sure all entries of each "
"column are all numbers or "
"all strings."
)
def validate_dataframe(array):
"""
Validates all strings or numbers in each dataframe column
:raises: (PlotlyError) If there are any two items in any list whose
types differ
"""
from numbers import Number
for vector in array:
if isinstance(vector[0], Number):
if not all(isinstance(item, Number) for item in vector):
raise exceptions.PlotlyError(
"Error in dataframe. "
"Make sure all entries of "
"each column are either "
"numbers or strings."
)
elif isinstance(vector[0], str):
if not all(isinstance(item, str) for item in vector):
raise exceptions.PlotlyError(
"Error in dataframe. "
"Make sure all entries of "
"each column are either "
"numbers or strings."
)
def validate_equal_length(*args):
"""
Validates that data lists or ndarrays are the same length.
:raises: (PlotlyError) If any data lists are not the same length.
"""
length = len(args[0])
if any(len(lst) != length for lst in args):
raise exceptions.PlotlyError(
"Oops! Your data lists or ndarrays should be the same length."
)
def validate_positive_scalars(**kwargs):
"""
Validates that all values given in key/val pairs are positive.
Accepts kwargs to improve Exception messages.
:raises: (PlotlyError) If any value is < 0 or raises.
"""
for key, val in kwargs.items():
try:
if val <= 0:
raise ValueError("{} must be > 0, got {}".format(key, val))
except TypeError:
raise exceptions.PlotlyError("{} must be a number, got {}".format(key, val))
def flatten(array):
"""
Uses list comprehension to flatten array
:param (array): An iterable to flatten
:raises (PlotlyError): If iterable is not nested.
:rtype (list): The flattened list.
"""
try:
return [item for sublist in array for item in sublist]
except TypeError:
raise exceptions.PlotlyError(
"Your data array could not be "
"flattened! Make sure your data is "
"entered as lists or ndarrays!"
)
def endpts_to_intervals(endpts):
"""
Returns a list of intervals for categorical colormaps
Accepts a list or tuple of sequentially increasing numbers and returns
a list representation of the mathematical intervals with these numbers
as endpoints. For example, [1, 6] returns [[-inf, 1], [1, 6], [6, inf]]
:raises: (PlotlyError) If input is not a list or tuple
:raises: (PlotlyError) If the input contains a string
:raises: (PlotlyError) If any number does not increase after the
previous one in the sequence
"""
length = len(endpts)
# Check if endpts is a list or tuple
if not (isinstance(endpts, (tuple)) or isinstance(endpts, (list))):
raise exceptions.PlotlyError(
"The intervals_endpts argument must "
"be a list or tuple of a sequence "
"of increasing numbers."
)
# Check if endpts contains only numbers
for item in endpts:
if isinstance(item, str):
raise exceptions.PlotlyError(
"The intervals_endpts argument "
"must be a list or tuple of a "
"sequence of increasing "
"numbers."
)
# Check if numbers in endpts are increasing
for k in range(length - 1):
if endpts[k] >= endpts[k + 1]:
raise exceptions.PlotlyError(
"The intervals_endpts argument "
"must be a list or tuple of a "
"sequence of increasing "
"numbers."
)
else:
intervals = []
# add -inf to intervals
intervals.append([float("-inf"), endpts[0]])
for k in range(length - 1):
interval = []
interval.append(endpts[k])
interval.append(endpts[k + 1])
intervals.append(interval)
# add +inf to intervals
intervals.append([endpts[length - 1], float("inf")])
return intervals
def annotation_dict_for_label(
text,
lane,
num_of_lanes,
subplot_spacing,
row_col="col",
flipped=True,
right_side=True,
text_color="#0f0f0f",
):
"""
Returns annotation dict for label of n labels of a 1xn or nx1 subplot.
:param (str) text: the text for a label.
:param (int) lane: the label number for text. From 1 to n inclusive.
:param (int) num_of_lanes: the number 'n' of rows or columns in subplot.
:param (float) subplot_spacing: the value for the horizontal_spacing and
vertical_spacing params in your plotly.tools.make_subplots() call.
:param (str) row_col: choose whether labels are placed along rows or
columns.
:param (bool) flipped: flips text by 90 degrees. Text is printed
horizontally if set to True and row_col='row', or if False and
row_col='col'.
:param (bool) right_side: only applicable if row_col is set to 'row'.
:param (str) text_color: color of the text.
"""
temp = (1 - (num_of_lanes - 1) * subplot_spacing) / (num_of_lanes)
if not flipped:
xanchor = "center"
yanchor = "middle"
if row_col == "col":
x = (lane - 1) * (temp + subplot_spacing) + 0.5 * temp
y = 1.03
textangle = 0
elif row_col == "row":
y = (lane - 1) * (temp + subplot_spacing) + 0.5 * temp
x = 1.03
textangle = 90
else:
if row_col == "col":
xanchor = "center"
yanchor = "bottom"
x = (lane - 1) * (temp + subplot_spacing) + 0.5 * temp
y = 1.0
textangle = 270
elif row_col == "row":
yanchor = "middle"
y = (lane - 1) * (temp + subplot_spacing) + 0.5 * temp
if right_side:
x = 1.0
xanchor = "left"
else:
x = -0.01
xanchor = "right"
textangle = 0
annotation_dict = dict(
textangle=textangle,
xanchor=xanchor,
yanchor=yanchor,
x=x,
y=y,
showarrow=False,
xref="paper",
yref="paper",
text=text,
font=dict(size=13, color=text_color),
)
return annotation_dict
def list_of_options(iterable, conj="and", period=True):
"""
Returns an English listing of objects seperated by commas ','
For example, ['foo', 'bar', 'baz'] becomes 'foo, bar and baz'
if the conjunction 'and' is selected.
"""
if len(iterable) < 2:
raise exceptions.PlotlyError(
"Your list or tuple must contain at least 2 items."
)
template = (len(iterable) - 2) * "{}, " + "{} " + conj + " {}" + period * "."
return template.format(*iterable)

View File

@ -0,0 +1 @@
from _plotly_utils.files import PLOTLY_DIR, ensure_writable_plotly_dir # noqa: F401

View File

@ -0,0 +1,306 @@
# ruff: noqa: F401
import sys
from typing import TYPE_CHECKING
if TYPE_CHECKING:
from ..graph_objs import Waterfall
from ..graph_objs import Volume
from ..graph_objs import Violin
from ..graph_objs import Treemap
from ..graph_objs import Table
from ..graph_objs import Surface
from ..graph_objs import Sunburst
from ..graph_objs import Streamtube
from ..graph_objs import Splom
from ..graph_objs import Scatterternary
from ..graph_objs import Scattersmith
from ..graph_objs import Scatterpolargl
from ..graph_objs import Scatterpolar
from ..graph_objs import Scattermapbox
from ..graph_objs import Scattermap
from ..graph_objs import Scattergl
from ..graph_objs import Scattergeo
from ..graph_objs import Scattercarpet
from ..graph_objs import Scatter3d
from ..graph_objs import Scatter
from ..graph_objs import Sankey
from ..graph_objs import Pie
from ..graph_objs import Parcoords
from ..graph_objs import Parcats
from ..graph_objs import Ohlc
from ..graph_objs import Mesh3d
from ..graph_objs import Isosurface
from ..graph_objs import Indicator
from ..graph_objs import Image
from ..graph_objs import Icicle
from ..graph_objs import Histogram2dContour
from ..graph_objs import Histogram2d
from ..graph_objs import Histogram
from ..graph_objs import Heatmap
from ..graph_objs import Funnelarea
from ..graph_objs import Funnel
from ..graph_objs import Densitymapbox
from ..graph_objs import Densitymap
from ..graph_objs import Contourcarpet
from ..graph_objs import Contour
from ..graph_objs import Cone
from ..graph_objs import Choroplethmapbox
from ..graph_objs import Choroplethmap
from ..graph_objs import Choropleth
from ..graph_objs import Carpet
from ..graph_objs import Candlestick
from ..graph_objs import Box
from ..graph_objs import Barpolar
from ..graph_objs import Bar
from ..graph_objs import Layout
from ..graph_objs import Frame
from ..graph_objs import Figure
from ..graph_objs import Data
from ..graph_objs import Annotations
from ..graph_objs import Frames
from ..graph_objs import AngularAxis
from ..graph_objs import Annotation
from ..graph_objs import ColorBar
from ..graph_objs import Contours
from ..graph_objs import ErrorX
from ..graph_objs import ErrorY
from ..graph_objs import ErrorZ
from ..graph_objs import Font
from ..graph_objs import Legend
from ..graph_objs import Line
from ..graph_objs import Margin
from ..graph_objs import Marker
from ..graph_objs import RadialAxis
from ..graph_objs import Scene
from ..graph_objs import Stream
from ..graph_objs import XAxis
from ..graph_objs import YAxis
from ..graph_objs import ZAxis
from ..graph_objs import XBins
from ..graph_objs import YBins
from ..graph_objs import Trace
from ..graph_objs import Histogram2dcontour
from ..graph_objs import waterfall
from ..graph_objs import volume
from ..graph_objs import violin
from ..graph_objs import treemap
from ..graph_objs import table
from ..graph_objs import surface
from ..graph_objs import sunburst
from ..graph_objs import streamtube
from ..graph_objs import splom
from ..graph_objs import scatterternary
from ..graph_objs import scattersmith
from ..graph_objs import scatterpolargl
from ..graph_objs import scatterpolar
from ..graph_objs import scattermapbox
from ..graph_objs import scattermap
from ..graph_objs import scattergl
from ..graph_objs import scattergeo
from ..graph_objs import scattercarpet
from ..graph_objs import scatter3d
from ..graph_objs import scatter
from ..graph_objs import sankey
from ..graph_objs import pie
from ..graph_objs import parcoords
from ..graph_objs import parcats
from ..graph_objs import ohlc
from ..graph_objs import mesh3d
from ..graph_objs import isosurface
from ..graph_objs import indicator
from ..graph_objs import image
from ..graph_objs import icicle
from ..graph_objs import histogram2dcontour
from ..graph_objs import histogram2d
from ..graph_objs import histogram
from ..graph_objs import heatmap
from ..graph_objs import funnelarea
from ..graph_objs import funnel
from ..graph_objs import densitymapbox
from ..graph_objs import densitymap
from ..graph_objs import contourcarpet
from ..graph_objs import contour
from ..graph_objs import cone
from ..graph_objs import choroplethmapbox
from ..graph_objs import choroplethmap
from ..graph_objs import choropleth
from ..graph_objs import carpet
from ..graph_objs import candlestick
from ..graph_objs import box
from ..graph_objs import barpolar
from ..graph_objs import bar
from ..graph_objs import layout
else:
from _plotly_utils.importers import relative_import
__all__, __getattr__, __dir__ = relative_import(
__name__,
[
"..graph_objs.waterfall",
"..graph_objs.volume",
"..graph_objs.violin",
"..graph_objs.treemap",
"..graph_objs.table",
"..graph_objs.surface",
"..graph_objs.sunburst",
"..graph_objs.streamtube",
"..graph_objs.splom",
"..graph_objs.scatterternary",
"..graph_objs.scattersmith",
"..graph_objs.scatterpolargl",
"..graph_objs.scatterpolar",
"..graph_objs.scattermapbox",
"..graph_objs.scattermap",
"..graph_objs.scattergl",
"..graph_objs.scattergeo",
"..graph_objs.scattercarpet",
"..graph_objs.scatter3d",
"..graph_objs.scatter",
"..graph_objs.sankey",
"..graph_objs.pie",
"..graph_objs.parcoords",
"..graph_objs.parcats",
"..graph_objs.ohlc",
"..graph_objs.mesh3d",
"..graph_objs.isosurface",
"..graph_objs.indicator",
"..graph_objs.image",
"..graph_objs.icicle",
"..graph_objs.histogram2dcontour",
"..graph_objs.histogram2d",
"..graph_objs.histogram",
"..graph_objs.heatmap",
"..graph_objs.funnelarea",
"..graph_objs.funnel",
"..graph_objs.densitymapbox",
"..graph_objs.densitymap",
"..graph_objs.contourcarpet",
"..graph_objs.contour",
"..graph_objs.cone",
"..graph_objs.choroplethmapbox",
"..graph_objs.choroplethmap",
"..graph_objs.choropleth",
"..graph_objs.carpet",
"..graph_objs.candlestick",
"..graph_objs.box",
"..graph_objs.barpolar",
"..graph_objs.bar",
"..graph_objs.layout",
],
[
"..graph_objs.Waterfall",
"..graph_objs.Volume",
"..graph_objs.Violin",
"..graph_objs.Treemap",
"..graph_objs.Table",
"..graph_objs.Surface",
"..graph_objs.Sunburst",
"..graph_objs.Streamtube",
"..graph_objs.Splom",
"..graph_objs.Scatterternary",
"..graph_objs.Scattersmith",
"..graph_objs.Scatterpolargl",
"..graph_objs.Scatterpolar",
"..graph_objs.Scattermapbox",
"..graph_objs.Scattermap",
"..graph_objs.Scattergl",
"..graph_objs.Scattergeo",
"..graph_objs.Scattercarpet",
"..graph_objs.Scatter3d",
"..graph_objs.Scatter",
"..graph_objs.Sankey",
"..graph_objs.Pie",
"..graph_objs.Parcoords",
"..graph_objs.Parcats",
"..graph_objs.Ohlc",
"..graph_objs.Mesh3d",
"..graph_objs.Isosurface",
"..graph_objs.Indicator",
"..graph_objs.Image",
"..graph_objs.Icicle",
"..graph_objs.Histogram2dContour",
"..graph_objs.Histogram2d",
"..graph_objs.Histogram",
"..graph_objs.Heatmap",
"..graph_objs.Funnelarea",
"..graph_objs.Funnel",
"..graph_objs.Densitymapbox",
"..graph_objs.Densitymap",
"..graph_objs.Contourcarpet",
"..graph_objs.Contour",
"..graph_objs.Cone",
"..graph_objs.Choroplethmapbox",
"..graph_objs.Choroplethmap",
"..graph_objs.Choropleth",
"..graph_objs.Carpet",
"..graph_objs.Candlestick",
"..graph_objs.Box",
"..graph_objs.Barpolar",
"..graph_objs.Bar",
"..graph_objs.Layout",
"..graph_objs.Frame",
"..graph_objs.Figure",
"..graph_objs.Data",
"..graph_objs.Annotations",
"..graph_objs.Frames",
"..graph_objs.AngularAxis",
"..graph_objs.Annotation",
"..graph_objs.ColorBar",
"..graph_objs.Contours",
"..graph_objs.ErrorX",
"..graph_objs.ErrorY",
"..graph_objs.ErrorZ",
"..graph_objs.Font",
"..graph_objs.Legend",
"..graph_objs.Line",
"..graph_objs.Margin",
"..graph_objs.Marker",
"..graph_objs.RadialAxis",
"..graph_objs.Scene",
"..graph_objs.Stream",
"..graph_objs.XAxis",
"..graph_objs.YAxis",
"..graph_objs.ZAxis",
"..graph_objs.XBins",
"..graph_objs.YBins",
"..graph_objs.Trace",
"..graph_objs.Histogram2dcontour",
],
)
if sys.version_info < (3, 7) or TYPE_CHECKING:
try:
import ipywidgets as _ipywidgets
from packaging.version import Version as _Version
if _Version(_ipywidgets.__version__) >= _Version("7.0.0"):
from ..graph_objs._figurewidget import FigureWidget
else:
raise ImportError()
except Exception:
from ..missing_anywidget import FigureWidget
else:
__all__.append("FigureWidget")
orig_getattr = __getattr__
def __getattr__(import_name):
if import_name == "FigureWidget":
try:
import ipywidgets
from packaging.version import Version
if Version(ipywidgets.__version__) >= Version("7.0.0"):
from ..graph_objs._figurewidget import FigureWidget
return FigureWidget
else:
raise ImportError()
except Exception:
from ..missing_anywidget import FigureWidget
return FigureWidget
else:
raise ImportError()
return orig_getattr(import_name)

View File

@ -0,0 +1,305 @@
import sys
from typing import TYPE_CHECKING
if TYPE_CHECKING:
from ._bar import Bar
from ._barpolar import Barpolar
from ._box import Box
from ._candlestick import Candlestick
from ._carpet import Carpet
from ._choropleth import Choropleth
from ._choroplethmap import Choroplethmap
from ._choroplethmapbox import Choroplethmapbox
from ._cone import Cone
from ._contour import Contour
from ._contourcarpet import Contourcarpet
from ._densitymap import Densitymap
from ._densitymapbox import Densitymapbox
from ._deprecations import AngularAxis
from ._deprecations import Annotation
from ._deprecations import Annotations
from ._deprecations import ColorBar
from ._deprecations import Contours
from ._deprecations import Data
from ._deprecations import ErrorX
from ._deprecations import ErrorY
from ._deprecations import ErrorZ
from ._deprecations import Font
from ._deprecations import Frames
from ._deprecations import Histogram2dcontour
from ._deprecations import Legend
from ._deprecations import Line
from ._deprecations import Margin
from ._deprecations import Marker
from ._deprecations import RadialAxis
from ._deprecations import Scene
from ._deprecations import Stream
from ._deprecations import Trace
from ._deprecations import XAxis
from ._deprecations import XBins
from ._deprecations import YAxis
from ._deprecations import YBins
from ._deprecations import ZAxis
from ._figure import Figure
from ._frame import Frame
from ._funnel import Funnel
from ._funnelarea import Funnelarea
from ._heatmap import Heatmap
from ._histogram import Histogram
from ._histogram2d import Histogram2d
from ._histogram2dcontour import Histogram2dContour
from ._icicle import Icicle
from ._image import Image
from ._indicator import Indicator
from ._isosurface import Isosurface
from ._layout import Layout
from ._mesh3d import Mesh3d
from ._ohlc import Ohlc
from ._parcats import Parcats
from ._parcoords import Parcoords
from ._pie import Pie
from ._sankey import Sankey
from ._scatter import Scatter
from ._scatter3d import Scatter3d
from ._scattercarpet import Scattercarpet
from ._scattergeo import Scattergeo
from ._scattergl import Scattergl
from ._scattermap import Scattermap
from ._scattermapbox import Scattermapbox
from ._scatterpolar import Scatterpolar
from ._scatterpolargl import Scatterpolargl
from ._scattersmith import Scattersmith
from ._scatterternary import Scatterternary
from ._splom import Splom
from ._streamtube import Streamtube
from ._sunburst import Sunburst
from ._surface import Surface
from ._table import Table
from ._treemap import Treemap
from ._violin import Violin
from ._volume import Volume
from ._waterfall import Waterfall
from . import bar
from . import barpolar
from . import box
from . import candlestick
from . import carpet
from . import choropleth
from . import choroplethmap
from . import choroplethmapbox
from . import cone
from . import contour
from . import contourcarpet
from . import densitymap
from . import densitymapbox
from . import funnel
from . import funnelarea
from . import heatmap
from . import histogram
from . import histogram2d
from . import histogram2dcontour
from . import icicle
from . import image
from . import indicator
from . import isosurface
from . import layout
from . import mesh3d
from . import ohlc
from . import parcats
from . import parcoords
from . import pie
from . import sankey
from . import scatter
from . import scatter3d
from . import scattercarpet
from . import scattergeo
from . import scattergl
from . import scattermap
from . import scattermapbox
from . import scatterpolar
from . import scatterpolargl
from . import scattersmith
from . import scatterternary
from . import splom
from . import streamtube
from . import sunburst
from . import surface
from . import table
from . import treemap
from . import violin
from . import volume
from . import waterfall
else:
from _plotly_utils.importers import relative_import
__all__, __getattr__, __dir__ = relative_import(
__name__,
[
".bar",
".barpolar",
".box",
".candlestick",
".carpet",
".choropleth",
".choroplethmap",
".choroplethmapbox",
".cone",
".contour",
".contourcarpet",
".densitymap",
".densitymapbox",
".funnel",
".funnelarea",
".heatmap",
".histogram",
".histogram2d",
".histogram2dcontour",
".icicle",
".image",
".indicator",
".isosurface",
".layout",
".mesh3d",
".ohlc",
".parcats",
".parcoords",
".pie",
".sankey",
".scatter",
".scatter3d",
".scattercarpet",
".scattergeo",
".scattergl",
".scattermap",
".scattermapbox",
".scatterpolar",
".scatterpolargl",
".scattersmith",
".scatterternary",
".splom",
".streamtube",
".sunburst",
".surface",
".table",
".treemap",
".violin",
".volume",
".waterfall",
],
[
"._bar.Bar",
"._barpolar.Barpolar",
"._box.Box",
"._candlestick.Candlestick",
"._carpet.Carpet",
"._choropleth.Choropleth",
"._choroplethmap.Choroplethmap",
"._choroplethmapbox.Choroplethmapbox",
"._cone.Cone",
"._contour.Contour",
"._contourcarpet.Contourcarpet",
"._densitymap.Densitymap",
"._densitymapbox.Densitymapbox",
"._deprecations.AngularAxis",
"._deprecations.Annotation",
"._deprecations.Annotations",
"._deprecations.ColorBar",
"._deprecations.Contours",
"._deprecations.Data",
"._deprecations.ErrorX",
"._deprecations.ErrorY",
"._deprecations.ErrorZ",
"._deprecations.Font",
"._deprecations.Frames",
"._deprecations.Histogram2dcontour",
"._deprecations.Legend",
"._deprecations.Line",
"._deprecations.Margin",
"._deprecations.Marker",
"._deprecations.RadialAxis",
"._deprecations.Scene",
"._deprecations.Stream",
"._deprecations.Trace",
"._deprecations.XAxis",
"._deprecations.XBins",
"._deprecations.YAxis",
"._deprecations.YBins",
"._deprecations.ZAxis",
"._figure.Figure",
"._frame.Frame",
"._funnel.Funnel",
"._funnelarea.Funnelarea",
"._heatmap.Heatmap",
"._histogram.Histogram",
"._histogram2d.Histogram2d",
"._histogram2dcontour.Histogram2dContour",
"._icicle.Icicle",
"._image.Image",
"._indicator.Indicator",
"._isosurface.Isosurface",
"._layout.Layout",
"._mesh3d.Mesh3d",
"._ohlc.Ohlc",
"._parcats.Parcats",
"._parcoords.Parcoords",
"._pie.Pie",
"._sankey.Sankey",
"._scatter.Scatter",
"._scatter3d.Scatter3d",
"._scattercarpet.Scattercarpet",
"._scattergeo.Scattergeo",
"._scattergl.Scattergl",
"._scattermap.Scattermap",
"._scattermapbox.Scattermapbox",
"._scatterpolar.Scatterpolar",
"._scatterpolargl.Scatterpolargl",
"._scattersmith.Scattersmith",
"._scatterternary.Scatterternary",
"._splom.Splom",
"._streamtube.Streamtube",
"._sunburst.Sunburst",
"._surface.Surface",
"._table.Table",
"._treemap.Treemap",
"._violin.Violin",
"._volume.Volume",
"._waterfall.Waterfall",
],
)
if sys.version_info < (3, 7) or TYPE_CHECKING:
try:
import ipywidgets as _ipywidgets
from packaging.version import Version as _Version
if _Version(_ipywidgets.__version__) >= _Version("7.0.0"):
from ..graph_objs._figurewidget import FigureWidget
else:
raise ImportError()
except Exception:
from ..missing_anywidget import FigureWidget
else:
__all__.append("FigureWidget")
orig_getattr = __getattr__
def __getattr__(import_name):
if import_name == "FigureWidget":
try:
import ipywidgets
from packaging.version import Version
if Version(ipywidgets.__version__) >= Version("7.0.0"):
from ..graph_objs._figurewidget import FigureWidget
return FigureWidget
else:
raise ImportError()
except Exception:
from ..missing_anywidget import FigureWidget
return FigureWidget
else:
raise ImportError()
return orig_getattr(import_name)

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,723 @@
import warnings
warnings.filterwarnings(
"default", r"plotly\.graph_objs\.\w+ is deprecated", DeprecationWarning
)
class Data(list):
"""
plotly.graph_objs.Data is deprecated.
Please replace it with a list or tuple of instances of the following types
- plotly.graph_objs.Scatter
- plotly.graph_objs.Bar
- plotly.graph_objs.Area
- plotly.graph_objs.Histogram
- etc.
"""
def __init__(self, *args, **kwargs):
"""
plotly.graph_objs.Data is deprecated.
Please replace it with a list or tuple of instances of the following types
- plotly.graph_objs.Scatter
- plotly.graph_objs.Bar
- plotly.graph_objs.Area
- plotly.graph_objs.Histogram
- etc.
"""
warnings.warn(
"""plotly.graph_objs.Data is deprecated.
Please replace it with a list or tuple of instances of the following types
- plotly.graph_objs.Scatter
- plotly.graph_objs.Bar
- plotly.graph_objs.Area
- plotly.graph_objs.Histogram
- etc.
""",
DeprecationWarning,
)
super().__init__(*args, **kwargs)
class Annotations(list):
"""
plotly.graph_objs.Annotations is deprecated.
Please replace it with a list or tuple of instances of the following types
- plotly.graph_objs.layout.Annotation
- plotly.graph_objs.layout.scene.Annotation
"""
def __init__(self, *args, **kwargs):
"""
plotly.graph_objs.Annotations is deprecated.
Please replace it with a list or tuple of instances of the following types
- plotly.graph_objs.layout.Annotation
- plotly.graph_objs.layout.scene.Annotation
"""
warnings.warn(
"""plotly.graph_objs.Annotations is deprecated.
Please replace it with a list or tuple of instances of the following types
- plotly.graph_objs.layout.Annotation
- plotly.graph_objs.layout.scene.Annotation
""",
DeprecationWarning,
)
super().__init__(*args, **kwargs)
class Frames(list):
"""
plotly.graph_objs.Frames is deprecated.
Please replace it with a list or tuple of instances of the following types
- plotly.graph_objs.Frame
"""
def __init__(self, *args, **kwargs):
"""
plotly.graph_objs.Frames is deprecated.
Please replace it with a list or tuple of instances of the following types
- plotly.graph_objs.Frame
"""
warnings.warn(
"""plotly.graph_objs.Frames is deprecated.
Please replace it with a list or tuple of instances of the following types
- plotly.graph_objs.Frame
""",
DeprecationWarning,
)
super().__init__(*args, **kwargs)
class AngularAxis(dict):
"""
plotly.graph_objs.AngularAxis is deprecated.
Please replace it with one of the following more specific types
- plotly.graph_objs.layout.AngularAxis
- plotly.graph_objs.layout.polar.AngularAxis
"""
def __init__(self, *args, **kwargs):
"""
plotly.graph_objs.AngularAxis is deprecated.
Please replace it with one of the following more specific types
- plotly.graph_objs.layout.AngularAxis
- plotly.graph_objs.layout.polar.AngularAxis
"""
warnings.warn(
"""plotly.graph_objs.AngularAxis is deprecated.
Please replace it with one of the following more specific types
- plotly.graph_objs.layout.AngularAxis
- plotly.graph_objs.layout.polar.AngularAxis
""",
DeprecationWarning,
)
super().__init__(*args, **kwargs)
class Annotation(dict):
"""
plotly.graph_objs.Annotation is deprecated.
Please replace it with one of the following more specific types
- plotly.graph_objs.layout.Annotation
- plotly.graph_objs.layout.scene.Annotation
"""
def __init__(self, *args, **kwargs):
"""
plotly.graph_objs.Annotation is deprecated.
Please replace it with one of the following more specific types
- plotly.graph_objs.layout.Annotation
- plotly.graph_objs.layout.scene.Annotation
"""
warnings.warn(
"""plotly.graph_objs.Annotation is deprecated.
Please replace it with one of the following more specific types
- plotly.graph_objs.layout.Annotation
- plotly.graph_objs.layout.scene.Annotation
""",
DeprecationWarning,
)
super().__init__(*args, **kwargs)
class ColorBar(dict):
"""
plotly.graph_objs.ColorBar is deprecated.
Please replace it with one of the following more specific types
- plotly.graph_objs.scatter.marker.ColorBar
- plotly.graph_objs.surface.ColorBar
- etc.
"""
def __init__(self, *args, **kwargs):
"""
plotly.graph_objs.ColorBar is deprecated.
Please replace it with one of the following more specific types
- plotly.graph_objs.scatter.marker.ColorBar
- plotly.graph_objs.surface.ColorBar
- etc.
"""
warnings.warn(
"""plotly.graph_objs.ColorBar is deprecated.
Please replace it with one of the following more specific types
- plotly.graph_objs.scatter.marker.ColorBar
- plotly.graph_objs.surface.ColorBar
- etc.
""",
DeprecationWarning,
)
super().__init__(*args, **kwargs)
class Contours(dict):
"""
plotly.graph_objs.Contours is deprecated.
Please replace it with one of the following more specific types
- plotly.graph_objs.contour.Contours
- plotly.graph_objs.surface.Contours
- etc.
"""
def __init__(self, *args, **kwargs):
"""
plotly.graph_objs.Contours is deprecated.
Please replace it with one of the following more specific types
- plotly.graph_objs.contour.Contours
- plotly.graph_objs.surface.Contours
- etc.
"""
warnings.warn(
"""plotly.graph_objs.Contours is deprecated.
Please replace it with one of the following more specific types
- plotly.graph_objs.contour.Contours
- plotly.graph_objs.surface.Contours
- etc.
""",
DeprecationWarning,
)
super().__init__(*args, **kwargs)
class ErrorX(dict):
"""
plotly.graph_objs.ErrorX is deprecated.
Please replace it with one of the following more specific types
- plotly.graph_objs.scatter.ErrorX
- plotly.graph_objs.histogram.ErrorX
- etc.
"""
def __init__(self, *args, **kwargs):
"""
plotly.graph_objs.ErrorX is deprecated.
Please replace it with one of the following more specific types
- plotly.graph_objs.scatter.ErrorX
- plotly.graph_objs.histogram.ErrorX
- etc.
"""
warnings.warn(
"""plotly.graph_objs.ErrorX is deprecated.
Please replace it with one of the following more specific types
- plotly.graph_objs.scatter.ErrorX
- plotly.graph_objs.histogram.ErrorX
- etc.
""",
DeprecationWarning,
)
super().__init__(*args, **kwargs)
class ErrorY(dict):
"""
plotly.graph_objs.ErrorY is deprecated.
Please replace it with one of the following more specific types
- plotly.graph_objs.scatter.ErrorY
- plotly.graph_objs.histogram.ErrorY
- etc.
"""
def __init__(self, *args, **kwargs):
"""
plotly.graph_objs.ErrorY is deprecated.
Please replace it with one of the following more specific types
- plotly.graph_objs.scatter.ErrorY
- plotly.graph_objs.histogram.ErrorY
- etc.
"""
warnings.warn(
"""plotly.graph_objs.ErrorY is deprecated.
Please replace it with one of the following more specific types
- plotly.graph_objs.scatter.ErrorY
- plotly.graph_objs.histogram.ErrorY
- etc.
""",
DeprecationWarning,
)
super().__init__(*args, **kwargs)
class ErrorZ(dict):
"""
plotly.graph_objs.ErrorZ is deprecated.
Please replace it with one of the following more specific types
- plotly.graph_objs.scatter3d.ErrorZ
"""
def __init__(self, *args, **kwargs):
"""
plotly.graph_objs.ErrorZ is deprecated.
Please replace it with one of the following more specific types
- plotly.graph_objs.scatter3d.ErrorZ
"""
warnings.warn(
"""plotly.graph_objs.ErrorZ is deprecated.
Please replace it with one of the following more specific types
- plotly.graph_objs.scatter3d.ErrorZ
""",
DeprecationWarning,
)
super().__init__(*args, **kwargs)
class Font(dict):
"""
plotly.graph_objs.Font is deprecated.
Please replace it with one of the following more specific types
- plotly.graph_objs.layout.Font
- plotly.graph_objs.layout.hoverlabel.Font
- etc.
"""
def __init__(self, *args, **kwargs):
"""
plotly.graph_objs.Font is deprecated.
Please replace it with one of the following more specific types
- plotly.graph_objs.layout.Font
- plotly.graph_objs.layout.hoverlabel.Font
- etc.
"""
warnings.warn(
"""plotly.graph_objs.Font is deprecated.
Please replace it with one of the following more specific types
- plotly.graph_objs.layout.Font
- plotly.graph_objs.layout.hoverlabel.Font
- etc.
""",
DeprecationWarning,
)
super().__init__(*args, **kwargs)
class Legend(dict):
"""
plotly.graph_objs.Legend is deprecated.
Please replace it with one of the following more specific types
- plotly.graph_objs.layout.Legend
"""
def __init__(self, *args, **kwargs):
"""
plotly.graph_objs.Legend is deprecated.
Please replace it with one of the following more specific types
- plotly.graph_objs.layout.Legend
"""
warnings.warn(
"""plotly.graph_objs.Legend is deprecated.
Please replace it with one of the following more specific types
- plotly.graph_objs.layout.Legend
""",
DeprecationWarning,
)
super().__init__(*args, **kwargs)
class Line(dict):
"""
plotly.graph_objs.Line is deprecated.
Please replace it with one of the following more specific types
- plotly.graph_objs.scatter.Line
- plotly.graph_objs.layout.shape.Line
- etc.
"""
def __init__(self, *args, **kwargs):
"""
plotly.graph_objs.Line is deprecated.
Please replace it with one of the following more specific types
- plotly.graph_objs.scatter.Line
- plotly.graph_objs.layout.shape.Line
- etc.
"""
warnings.warn(
"""plotly.graph_objs.Line is deprecated.
Please replace it with one of the following more specific types
- plotly.graph_objs.scatter.Line
- plotly.graph_objs.layout.shape.Line
- etc.
""",
DeprecationWarning,
)
super().__init__(*args, **kwargs)
class Margin(dict):
"""
plotly.graph_objs.Margin is deprecated.
Please replace it with one of the following more specific types
- plotly.graph_objs.layout.Margin
"""
def __init__(self, *args, **kwargs):
"""
plotly.graph_objs.Margin is deprecated.
Please replace it with one of the following more specific types
- plotly.graph_objs.layout.Margin
"""
warnings.warn(
"""plotly.graph_objs.Margin is deprecated.
Please replace it with one of the following more specific types
- plotly.graph_objs.layout.Margin
""",
DeprecationWarning,
)
super().__init__(*args, **kwargs)
class Marker(dict):
"""
plotly.graph_objs.Marker is deprecated.
Please replace it with one of the following more specific types
- plotly.graph_objs.scatter.Marker
- plotly.graph_objs.histogram.selected.Marker
- etc.
"""
def __init__(self, *args, **kwargs):
"""
plotly.graph_objs.Marker is deprecated.
Please replace it with one of the following more specific types
- plotly.graph_objs.scatter.Marker
- plotly.graph_objs.histogram.selected.Marker
- etc.
"""
warnings.warn(
"""plotly.graph_objs.Marker is deprecated.
Please replace it with one of the following more specific types
- plotly.graph_objs.scatter.Marker
- plotly.graph_objs.histogram.selected.Marker
- etc.
""",
DeprecationWarning,
)
super().__init__(*args, **kwargs)
class RadialAxis(dict):
"""
plotly.graph_objs.RadialAxis is deprecated.
Please replace it with one of the following more specific types
- plotly.graph_objs.layout.RadialAxis
- plotly.graph_objs.layout.polar.RadialAxis
"""
def __init__(self, *args, **kwargs):
"""
plotly.graph_objs.RadialAxis is deprecated.
Please replace it with one of the following more specific types
- plotly.graph_objs.layout.RadialAxis
- plotly.graph_objs.layout.polar.RadialAxis
"""
warnings.warn(
"""plotly.graph_objs.RadialAxis is deprecated.
Please replace it with one of the following more specific types
- plotly.graph_objs.layout.RadialAxis
- plotly.graph_objs.layout.polar.RadialAxis
""",
DeprecationWarning,
)
super().__init__(*args, **kwargs)
class Scene(dict):
"""
plotly.graph_objs.Scene is deprecated.
Please replace it with one of the following more specific types
- plotly.graph_objs.layout.Scene
"""
def __init__(self, *args, **kwargs):
"""
plotly.graph_objs.Scene is deprecated.
Please replace it with one of the following more specific types
- plotly.graph_objs.layout.Scene
"""
warnings.warn(
"""plotly.graph_objs.Scene is deprecated.
Please replace it with one of the following more specific types
- plotly.graph_objs.layout.Scene
""",
DeprecationWarning,
)
super().__init__(*args, **kwargs)
class Stream(dict):
"""
plotly.graph_objs.Stream is deprecated.
Please replace it with one of the following more specific types
- plotly.graph_objs.scatter.Stream
- plotly.graph_objs.area.Stream
"""
def __init__(self, *args, **kwargs):
"""
plotly.graph_objs.Stream is deprecated.
Please replace it with one of the following more specific types
- plotly.graph_objs.scatter.Stream
- plotly.graph_objs.area.Stream
"""
warnings.warn(
"""plotly.graph_objs.Stream is deprecated.
Please replace it with one of the following more specific types
- plotly.graph_objs.scatter.Stream
- plotly.graph_objs.area.Stream
""",
DeprecationWarning,
)
super().__init__(*args, **kwargs)
class XAxis(dict):
"""
plotly.graph_objs.XAxis is deprecated.
Please replace it with one of the following more specific types
- plotly.graph_objs.layout.XAxis
- plotly.graph_objs.layout.scene.XAxis
"""
def __init__(self, *args, **kwargs):
"""
plotly.graph_objs.XAxis is deprecated.
Please replace it with one of the following more specific types
- plotly.graph_objs.layout.XAxis
- plotly.graph_objs.layout.scene.XAxis
"""
warnings.warn(
"""plotly.graph_objs.XAxis is deprecated.
Please replace it with one of the following more specific types
- plotly.graph_objs.layout.XAxis
- plotly.graph_objs.layout.scene.XAxis
""",
DeprecationWarning,
)
super().__init__(*args, **kwargs)
class YAxis(dict):
"""
plotly.graph_objs.YAxis is deprecated.
Please replace it with one of the following more specific types
- plotly.graph_objs.layout.YAxis
- plotly.graph_objs.layout.scene.YAxis
"""
def __init__(self, *args, **kwargs):
"""
plotly.graph_objs.YAxis is deprecated.
Please replace it with one of the following more specific types
- plotly.graph_objs.layout.YAxis
- plotly.graph_objs.layout.scene.YAxis
"""
warnings.warn(
"""plotly.graph_objs.YAxis is deprecated.
Please replace it with one of the following more specific types
- plotly.graph_objs.layout.YAxis
- plotly.graph_objs.layout.scene.YAxis
""",
DeprecationWarning,
)
super().__init__(*args, **kwargs)
class ZAxis(dict):
"""
plotly.graph_objs.ZAxis is deprecated.
Please replace it with one of the following more specific types
- plotly.graph_objs.layout.scene.ZAxis
"""
def __init__(self, *args, **kwargs):
"""
plotly.graph_objs.ZAxis is deprecated.
Please replace it with one of the following more specific types
- plotly.graph_objs.layout.scene.ZAxis
"""
warnings.warn(
"""plotly.graph_objs.ZAxis is deprecated.
Please replace it with one of the following more specific types
- plotly.graph_objs.layout.scene.ZAxis
""",
DeprecationWarning,
)
super().__init__(*args, **kwargs)
class XBins(dict):
"""
plotly.graph_objs.XBins is deprecated.
Please replace it with one of the following more specific types
- plotly.graph_objs.histogram.XBins
- plotly.graph_objs.histogram2d.XBins
"""
def __init__(self, *args, **kwargs):
"""
plotly.graph_objs.XBins is deprecated.
Please replace it with one of the following more specific types
- plotly.graph_objs.histogram.XBins
- plotly.graph_objs.histogram2d.XBins
"""
warnings.warn(
"""plotly.graph_objs.XBins is deprecated.
Please replace it with one of the following more specific types
- plotly.graph_objs.histogram.XBins
- plotly.graph_objs.histogram2d.XBins
""",
DeprecationWarning,
)
super().__init__(*args, **kwargs)
class YBins(dict):
"""
plotly.graph_objs.YBins is deprecated.
Please replace it with one of the following more specific types
- plotly.graph_objs.histogram.YBins
- plotly.graph_objs.histogram2d.YBins
"""
def __init__(self, *args, **kwargs):
"""
plotly.graph_objs.YBins is deprecated.
Please replace it with one of the following more specific types
- plotly.graph_objs.histogram.YBins
- plotly.graph_objs.histogram2d.YBins
"""
warnings.warn(
"""plotly.graph_objs.YBins is deprecated.
Please replace it with one of the following more specific types
- plotly.graph_objs.histogram.YBins
- plotly.graph_objs.histogram2d.YBins
""",
DeprecationWarning,
)
super().__init__(*args, **kwargs)
class Trace(dict):
"""
plotly.graph_objs.Trace is deprecated.
Please replace it with one of the following more specific types
- plotly.graph_objs.Scatter
- plotly.graph_objs.Bar
- plotly.graph_objs.Area
- plotly.graph_objs.Histogram
- etc.
"""
def __init__(self, *args, **kwargs):
"""
plotly.graph_objs.Trace is deprecated.
Please replace it with one of the following more specific types
- plotly.graph_objs.Scatter
- plotly.graph_objs.Bar
- plotly.graph_objs.Area
- plotly.graph_objs.Histogram
- etc.
"""
warnings.warn(
"""plotly.graph_objs.Trace is deprecated.
Please replace it with one of the following more specific types
- plotly.graph_objs.Scatter
- plotly.graph_objs.Bar
- plotly.graph_objs.Area
- plotly.graph_objs.Histogram
- etc.
""",
DeprecationWarning,
)
super().__init__(*args, **kwargs)
class Histogram2dcontour(dict):
"""
plotly.graph_objs.Histogram2dcontour is deprecated.
Please replace it with one of the following more specific types
- plotly.graph_objs.Histogram2dContour
"""
def __init__(self, *args, **kwargs):
"""
plotly.graph_objs.Histogram2dcontour is deprecated.
Please replace it with one of the following more specific types
- plotly.graph_objs.Histogram2dContour
"""
warnings.warn(
"""plotly.graph_objs.Histogram2dcontour is deprecated.
Please replace it with one of the following more specific types
- plotly.graph_objs.Histogram2dContour
""",
DeprecationWarning,
)
super().__init__(*args, **kwargs)

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,220 @@
# --- THIS FILE IS AUTO-GENERATED ---
# Modifications will be overwitten the next time code generation run.
from plotly.basedatatypes import BaseFrameHierarchyType as _BaseFrameHierarchyType
import copy as _copy
class Frame(_BaseFrameHierarchyType):
_parent_path_str = ""
_path_str = "frame"
_valid_props = {"baseframe", "data", "group", "layout", "name", "traces"}
@property
def baseframe(self):
"""
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.
The 'baseframe' property is a string and must be specified as:
- A string
- A number that will be converted to a string
Returns
-------
str
"""
return self["baseframe"]
@baseframe.setter
def baseframe(self, val):
self["baseframe"] = val
@property
def data(self):
"""
A list of traces this frame modifies. The format is identical
to the normal trace definition.
Returns
-------
Any
"""
return self["data"]
@data.setter
def data(self, val):
self["data"] = val
@property
def group(self):
"""
An identifier that specifies the group to which the frame
belongs, used by animate to select a subset of frames.
The 'group' property is a string and must be specified as:
- A string
- A number that will be converted to a string
Returns
-------
str
"""
return self["group"]
@group.setter
def group(self, val):
self["group"] = val
@property
def layout(self):
"""
Layout properties which this frame modifies. The format is
identical to the normal layout definition.
Returns
-------
Any
"""
return self["layout"]
@layout.setter
def layout(self, val):
self["layout"] = val
@property
def name(self):
"""
A label by which to identify the frame
The 'name' property is a string and must be specified as:
- A string
- A number that will be converted to a string
Returns
-------
str
"""
return self["name"]
@name.setter
def name(self, val):
self["name"] = val
@property
def traces(self):
"""
A list of trace indices that identify the respective traces in
the data attribute
The 'traces' property accepts values of any type
Returns
-------
Any
"""
return self["traces"]
@traces.setter
def traces(self, val):
self["traces"] = val
@property
def _prop_descriptions(self):
return """\
baseframe
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
A list of traces this frame modifies. The format is
identical to the normal trace definition.
group
An identifier that specifies the group to which the
frame belongs, used by animate to select a subset of
frames.
layout
Layout properties which this frame modifies. The format
is identical to the normal layout definition.
name
A label by which to identify the frame
traces
A list of trace indices that identify the respective
traces in the data attribute
"""
def __init__(
self,
arg=None,
baseframe=None,
data=None,
group=None,
layout=None,
name=None,
traces=None,
**kwargs,
):
"""
Construct a new Frame object
Parameters
----------
arg
dict of properties compatible with this constructor or
an instance of :class:`plotly.graph_objs.Frame`
baseframe
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
A list of traces this frame modifies. The format is
identical to the normal trace definition.
group
An identifier that specifies the group to which the
frame belongs, used by animate to select a subset of
frames.
layout
Layout properties which this frame modifies. The format
is identical to the normal layout definition.
name
A label by which to identify the frame
traces
A list of trace indices that identify the respective
traces in the data attribute
Returns
-------
Frame
"""
super().__init__("frames")
if "_parent" in kwargs:
self._parent = kwargs["_parent"]
return
if arg is None:
arg = {}
elif isinstance(arg, self.__class__):
arg = arg.to_plotly_json()
elif isinstance(arg, dict):
arg = _copy.copy(arg)
else:
raise ValueError("""\
The first argument to the plotly.graph_objs.Frame
constructor must be a dict or
an instance of :class:`plotly.graph_objs.Frame`""")
self._skip_invalid = kwargs.pop("skip_invalid", False)
self._validate = kwargs.pop("_validate", True)
self._set_property("baseframe", arg, baseframe)
self._set_property("data", arg, data)
self._set_property("group", arg, group)
self._set_property("layout", arg, layout)
self._set_property("name", arg, name)
self._set_property("traces", arg, traces)
self._process_kwargs(**dict(arg, **kwargs))
self._skip_invalid = False

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,848 @@
# --- THIS FILE IS AUTO-GENERATED ---
# Modifications will be overwitten the next time code generation run.
from plotly.basedatatypes import BaseTraceType as _BaseTraceType
import copy as _copy
class Indicator(_BaseTraceType):
_parent_path_str = ""
_path_str = "indicator"
_valid_props = {
"align",
"customdata",
"customdatasrc",
"delta",
"domain",
"gauge",
"ids",
"idssrc",
"legend",
"legendgrouptitle",
"legendrank",
"legendwidth",
"meta",
"metasrc",
"mode",
"name",
"number",
"stream",
"title",
"type",
"uid",
"uirevision",
"value",
"visible",
}
@property
def align(self):
"""
Sets the horizontal alignment of the `text` within the box.
Note that this attribute has no effect if an angular gauge is
displayed: in this case, it is always centered
The 'align' property is an enumeration that may be specified as:
- One of the following enumeration values:
['left', 'center', 'right']
Returns
-------
Any
"""
return self["align"]
@align.setter
def align(self, val):
self["align"] = val
@property
def customdata(self):
"""
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
The 'customdata' property is an array that may be specified as a tuple,
list, numpy array, or pandas Series
Returns
-------
numpy.ndarray
"""
return self["customdata"]
@customdata.setter
def customdata(self, val):
self["customdata"] = val
@property
def customdatasrc(self):
"""
Sets the source reference on Chart Studio Cloud for
`customdata`.
The 'customdatasrc' property must be specified as a string or
as a plotly.grid_objs.Column object
Returns
-------
str
"""
return self["customdatasrc"]
@customdatasrc.setter
def customdatasrc(self, val):
self["customdatasrc"] = val
@property
def delta(self):
"""
The 'delta' property is an instance of Delta
that may be specified as:
- An instance of :class:`plotly.graph_objs.indicator.Delta`
- A dict of string/value properties that will be passed
to the Delta constructor
Returns
-------
plotly.graph_objs.indicator.Delta
"""
return self["delta"]
@delta.setter
def delta(self, val):
self["delta"] = val
@property
def domain(self):
"""
The 'domain' property is an instance of Domain
that may be specified as:
- An instance of :class:`plotly.graph_objs.indicator.Domain`
- A dict of string/value properties that will be passed
to the Domain constructor
Returns
-------
plotly.graph_objs.indicator.Domain
"""
return self["domain"]
@domain.setter
def domain(self, val):
self["domain"] = val
@property
def gauge(self):
"""
The gauge of the Indicator plot.
The 'gauge' property is an instance of Gauge
that may be specified as:
- An instance of :class:`plotly.graph_objs.indicator.Gauge`
- A dict of string/value properties that will be passed
to the Gauge constructor
Returns
-------
plotly.graph_objs.indicator.Gauge
"""
return self["gauge"]
@gauge.setter
def gauge(self, val):
self["gauge"] = val
@property
def ids(self):
"""
Assigns id labels to each datum. These ids for object constancy
of data points during animation. Should be an array of strings,
not numbers or any other type.
The 'ids' property is an array that may be specified as a tuple,
list, numpy array, or pandas Series
Returns
-------
numpy.ndarray
"""
return self["ids"]
@ids.setter
def ids(self, val):
self["ids"] = val
@property
def idssrc(self):
"""
Sets the source reference on Chart Studio Cloud for `ids`.
The 'idssrc' property must be specified as a string or
as a plotly.grid_objs.Column object
Returns
-------
str
"""
return self["idssrc"]
@idssrc.setter
def idssrc(self, val):
self["idssrc"] = val
@property
def legend(self):
"""
Sets the reference to a legend to show this trace in.
References to these legends are "legend", "legend2", "legend3",
etc. Settings for these legends are set in the layout, under
`layout.legend`, `layout.legend2`, etc.
The 'legend' property is an identifier of a particular
subplot, of type 'legend', that may be specified as the string 'legend'
optionally followed by an integer >= 1
(e.g. 'legend', 'legend1', 'legend2', 'legend3', etc.)
Returns
-------
str
"""
return self["legend"]
@legend.setter
def legend(self, val):
self["legend"] = val
@property
def legendgrouptitle(self):
"""
The 'legendgrouptitle' property is an instance of Legendgrouptitle
that may be specified as:
- An instance of :class:`plotly.graph_objs.indicator.Legendgrouptitle`
- A dict of string/value properties that will be passed
to the Legendgrouptitle constructor
Returns
-------
plotly.graph_objs.indicator.Legendgrouptitle
"""
return self["legendgrouptitle"]
@legendgrouptitle.setter
def legendgrouptitle(self, val):
self["legendgrouptitle"] = val
@property
def legendrank(self):
"""
Sets the legend rank for this trace. Items and groups with
smaller ranks are presented on top/left side while with
"reversed" `legend.traceorder` they are on bottom/right side.
The default legendrank is 1000, so that you can use ranks less
than 1000 to place certain items before all unranked items, and
ranks greater than 1000 to go after all unranked items. When
having unranked or equal rank items shapes would be displayed
after traces i.e. according to their order in data and layout.
The 'legendrank' property is a number and may be specified as:
- An int or float
Returns
-------
int|float
"""
return self["legendrank"]
@legendrank.setter
def legendrank(self, val):
self["legendrank"] = val
@property
def legendwidth(self):
"""
Sets the width (in px or fraction) of the legend for this
trace.
The 'legendwidth' property is a number and may be specified as:
- An int or float in the interval [0, inf]
Returns
-------
int|float
"""
return self["legendwidth"]
@legendwidth.setter
def legendwidth(self, val):
self["legendwidth"] = val
@property
def meta(self):
"""
Assigns extra meta information associated with this trace that
can be used in various text attributes. Attributes such as
trace `name`, graph, axis and colorbar `title.text`, annotation
`text` `rangeselector`, `updatemenues` and `sliders` `label`
text all support `meta`. To access the trace `meta` values in
an attribute in the same trace, simply use `%{meta[i]}` where
`i` is the index or key of the `meta` item in question. To
access trace `meta` in layout attributes, use
`%{data[n[.meta[i]}` where `i` is the index or key of the
`meta` and `n` is the trace index.
The 'meta' property accepts values of any type
Returns
-------
Any|numpy.ndarray
"""
return self["meta"]
@meta.setter
def meta(self, val):
self["meta"] = val
@property
def metasrc(self):
"""
Sets the source reference on Chart Studio Cloud for `meta`.
The 'metasrc' property must be specified as a string or
as a plotly.grid_objs.Column object
Returns
-------
str
"""
return self["metasrc"]
@metasrc.setter
def metasrc(self, val):
self["metasrc"] = val
@property
def mode(self):
"""
Determines how the value is displayed on the graph. `number`
displays the value numerically in text. `delta` displays the
difference to a reference value in text. Finally, `gauge`
displays the value graphically on an axis.
The 'mode' property is a flaglist and may be specified
as a string containing:
- Any combination of ['number', 'delta', 'gauge'] joined with '+' characters
(e.g. 'number+delta')
Returns
-------
Any
"""
return self["mode"]
@mode.setter
def mode(self, val):
self["mode"] = val
@property
def name(self):
"""
Sets the trace name. The trace name appears as the legend item
and on hover.
The 'name' property is a string and must be specified as:
- A string
- A number that will be converted to a string
Returns
-------
str
"""
return self["name"]
@name.setter
def name(self, val):
self["name"] = val
@property
def number(self):
"""
The 'number' property is an instance of Number
that may be specified as:
- An instance of :class:`plotly.graph_objs.indicator.Number`
- A dict of string/value properties that will be passed
to the Number constructor
Returns
-------
plotly.graph_objs.indicator.Number
"""
return self["number"]
@number.setter
def number(self, val):
self["number"] = val
@property
def stream(self):
"""
The 'stream' property is an instance of Stream
that may be specified as:
- An instance of :class:`plotly.graph_objs.indicator.Stream`
- A dict of string/value properties that will be passed
to the Stream constructor
Returns
-------
plotly.graph_objs.indicator.Stream
"""
return self["stream"]
@stream.setter
def stream(self, val):
self["stream"] = val
@property
def title(self):
"""
The 'title' property is an instance of Title
that may be specified as:
- An instance of :class:`plotly.graph_objs.indicator.Title`
- A dict of string/value properties that will be passed
to the Title constructor
Returns
-------
plotly.graph_objs.indicator.Title
"""
return self["title"]
@title.setter
def title(self, val):
self["title"] = val
@property
def uid(self):
"""
Assign an id to this trace, Use this to provide object
constancy between traces during animations and transitions.
The 'uid' property is a string and must be specified as:
- A string
- A number that will be converted to a string
Returns
-------
str
"""
return self["uid"]
@uid.setter
def uid(self, val):
self["uid"] = val
@property
def uirevision(self):
"""
Controls persistence of some user-driven changes to the trace:
`constraintrange` in `parcoords` traces, as well as some
`editable: true` modifications such as `name` and
`colorbar.title`. Defaults to `layout.uirevision`. Note that
other user-driven trace attribute changes are controlled by
`layout` attributes: `trace.visible` is controlled by
`layout.legend.uirevision`, `selectedpoints` is controlled by
`layout.selectionrevision`, and `colorbar.(x|y)` (accessible
with `config: {editable: true}`) is controlled by
`layout.editrevision`. Trace changes are tracked by `uid`,
which only falls back on trace index if no `uid` is provided.
So if your app can add/remove traces before the end of the
`data` array, such that the same trace has a different index,
you can still preserve user-driven changes if you give each
trace a `uid` that stays with it as it moves.
The 'uirevision' property accepts values of any type
Returns
-------
Any
"""
return self["uirevision"]
@uirevision.setter
def uirevision(self, val):
self["uirevision"] = val
@property
def value(self):
"""
Sets the number to be displayed.
The 'value' property is a number and may be specified as:
- An int or float
Returns
-------
int|float
"""
return self["value"]
@value.setter
def value(self, val):
self["value"] = val
@property
def visible(self):
"""
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).
The 'visible' property is an enumeration that may be specified as:
- One of the following enumeration values:
[True, False, 'legendonly']
Returns
-------
Any
"""
return self["visible"]
@visible.setter
def visible(self, val):
self["visible"] = val
@property
def type(self):
return self._props["type"]
@property
def _prop_descriptions(self):
return """\
align
Sets the horizontal alignment of the `text` within the
box. Note that this attribute has no effect if an
angular gauge is displayed: in this case, it is always
centered
customdata
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
customdatasrc
Sets the source reference on Chart Studio Cloud for
`customdata`.
delta
:class:`plotly.graph_objects.indicator.Delta` instance
or dict with compatible properties
domain
:class:`plotly.graph_objects.indicator.Domain` instance
or dict with compatible properties
gauge
The gauge of the Indicator plot.
ids
Assigns id labels to each datum. These ids for object
constancy of data points during animation. Should be an
array of strings, not numbers or any other type.
idssrc
Sets the source reference on Chart Studio Cloud for
`ids`.
legend
Sets the reference to a legend to show this trace in.
References to these legends are "legend", "legend2",
"legend3", etc. Settings for these legends are set in
the layout, under `layout.legend`, `layout.legend2`,
etc.
legendgrouptitle
:class:`plotly.graph_objects.indicator.Legendgrouptitle
` instance or dict with compatible properties
legendrank
Sets the legend rank for this trace. Items and groups
with smaller ranks are presented on top/left side while
with "reversed" `legend.traceorder` they are on
bottom/right side. The default legendrank is 1000, so
that you can use ranks less than 1000 to place certain
items before all unranked items, and ranks greater than
1000 to go after all unranked items. When having
unranked or equal rank items shapes would be displayed
after traces i.e. according to their order in data and
layout.
legendwidth
Sets the width (in px or fraction) of the legend for
this trace.
meta
Assigns extra meta information associated with this
trace that can be used in various text attributes.
Attributes such as trace `name`, graph, axis and
colorbar `title.text`, annotation `text`
`rangeselector`, `updatemenues` and `sliders` `label`
text all support `meta`. To access the trace `meta`
values in an attribute in the same trace, simply use
`%{meta[i]}` where `i` is the index or key of the
`meta` item in question. To access trace `meta` in
layout attributes, use `%{data[n[.meta[i]}` where `i`
is the index or key of the `meta` and `n` is the trace
index.
metasrc
Sets the source reference on Chart Studio Cloud for
`meta`.
mode
Determines how the value is displayed on the graph.
`number` displays the value numerically in text.
`delta` displays the difference to a reference value in
text. Finally, `gauge` displays the value graphically
on an axis.
name
Sets the trace name. The trace name appears as the
legend item and on hover.
number
:class:`plotly.graph_objects.indicator.Number` instance
or dict with compatible properties
stream
:class:`plotly.graph_objects.indicator.Stream` instance
or dict with compatible properties
title
:class:`plotly.graph_objects.indicator.Title` instance
or dict with compatible properties
uid
Assign an id to this trace, Use this to provide object
constancy between traces during animations and
transitions.
uirevision
Controls persistence of some user-driven changes to the
trace: `constraintrange` in `parcoords` traces, as well
as some `editable: true` modifications such as `name`
and `colorbar.title`. Defaults to `layout.uirevision`.
Note that other user-driven trace attribute changes are
controlled by `layout` attributes: `trace.visible` is
controlled by `layout.legend.uirevision`,
`selectedpoints` is controlled by
`layout.selectionrevision`, and `colorbar.(x|y)`
(accessible with `config: {editable: true}`) is
controlled by `layout.editrevision`. Trace changes are
tracked by `uid`, which only falls back on trace index
if no `uid` is provided. So if your app can add/remove
traces before the end of the `data` array, such that
the same trace has a different index, you can still
preserve user-driven changes if you give each trace a
`uid` that stays with it as it moves.
value
Sets the number to be displayed.
visible
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).
"""
def __init__(
self,
arg=None,
align=None,
customdata=None,
customdatasrc=None,
delta=None,
domain=None,
gauge=None,
ids=None,
idssrc=None,
legend=None,
legendgrouptitle=None,
legendrank=None,
legendwidth=None,
meta=None,
metasrc=None,
mode=None,
name=None,
number=None,
stream=None,
title=None,
uid=None,
uirevision=None,
value=None,
visible=None,
**kwargs,
):
"""
Construct a new Indicator object
An indicator is used to visualize a single `value` along with
some contextual information such as `steps` or a `threshold`,
using a combination of three visual elements: a number, a
delta, and/or a gauge. Deltas are taken with respect to a
`reference`. Gauges can be either angular or bullet (aka
linear) gauges.
Parameters
----------
arg
dict of properties compatible with this constructor or
an instance of :class:`plotly.graph_objs.Indicator`
align
Sets the horizontal alignment of the `text` within the
box. Note that this attribute has no effect if an
angular gauge is displayed: in this case, it is always
centered
customdata
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
customdatasrc
Sets the source reference on Chart Studio Cloud for
`customdata`.
delta
:class:`plotly.graph_objects.indicator.Delta` instance
or dict with compatible properties
domain
:class:`plotly.graph_objects.indicator.Domain` instance
or dict with compatible properties
gauge
The gauge of the Indicator plot.
ids
Assigns id labels to each datum. These ids for object
constancy of data points during animation. Should be an
array of strings, not numbers or any other type.
idssrc
Sets the source reference on Chart Studio Cloud for
`ids`.
legend
Sets the reference to a legend to show this trace in.
References to these legends are "legend", "legend2",
"legend3", etc. Settings for these legends are set in
the layout, under `layout.legend`, `layout.legend2`,
etc.
legendgrouptitle
:class:`plotly.graph_objects.indicator.Legendgrouptitle
` instance or dict with compatible properties
legendrank
Sets the legend rank for this trace. Items and groups
with smaller ranks are presented on top/left side while
with "reversed" `legend.traceorder` they are on
bottom/right side. The default legendrank is 1000, so
that you can use ranks less than 1000 to place certain
items before all unranked items, and ranks greater than
1000 to go after all unranked items. When having
unranked or equal rank items shapes would be displayed
after traces i.e. according to their order in data and
layout.
legendwidth
Sets the width (in px or fraction) of the legend for
this trace.
meta
Assigns extra meta information associated with this
trace that can be used in various text attributes.
Attributes such as trace `name`, graph, axis and
colorbar `title.text`, annotation `text`
`rangeselector`, `updatemenues` and `sliders` `label`
text all support `meta`. To access the trace `meta`
values in an attribute in the same trace, simply use
`%{meta[i]}` where `i` is the index or key of the
`meta` item in question. To access trace `meta` in
layout attributes, use `%{data[n[.meta[i]}` where `i`
is the index or key of the `meta` and `n` is the trace
index.
metasrc
Sets the source reference on Chart Studio Cloud for
`meta`.
mode
Determines how the value is displayed on the graph.
`number` displays the value numerically in text.
`delta` displays the difference to a reference value in
text. Finally, `gauge` displays the value graphically
on an axis.
name
Sets the trace name. The trace name appears as the
legend item and on hover.
number
:class:`plotly.graph_objects.indicator.Number` instance
or dict with compatible properties
stream
:class:`plotly.graph_objects.indicator.Stream` instance
or dict with compatible properties
title
:class:`plotly.graph_objects.indicator.Title` instance
or dict with compatible properties
uid
Assign an id to this trace, Use this to provide object
constancy between traces during animations and
transitions.
uirevision
Controls persistence of some user-driven changes to the
trace: `constraintrange` in `parcoords` traces, as well
as some `editable: true` modifications such as `name`
and `colorbar.title`. Defaults to `layout.uirevision`.
Note that other user-driven trace attribute changes are
controlled by `layout` attributes: `trace.visible` is
controlled by `layout.legend.uirevision`,
`selectedpoints` is controlled by
`layout.selectionrevision`, and `colorbar.(x|y)`
(accessible with `config: {editable: true}`) is
controlled by `layout.editrevision`. Trace changes are
tracked by `uid`, which only falls back on trace index
if no `uid` is provided. So if your app can add/remove
traces before the end of the `data` array, such that
the same trace has a different index, you can still
preserve user-driven changes if you give each trace a
`uid` that stays with it as it moves.
value
Sets the number to be displayed.
visible
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).
Returns
-------
Indicator
"""
super().__init__("indicator")
if "_parent" in kwargs:
self._parent = kwargs["_parent"]
return
if arg is None:
arg = {}
elif isinstance(arg, self.__class__):
arg = arg.to_plotly_json()
elif isinstance(arg, dict):
arg = _copy.copy(arg)
else:
raise ValueError("""\
The first argument to the plotly.graph_objs.Indicator
constructor must be a dict or
an instance of :class:`plotly.graph_objs.Indicator`""")
self._skip_invalid = kwargs.pop("skip_invalid", False)
self._validate = kwargs.pop("_validate", True)
self._set_property("align", arg, align)
self._set_property("customdata", arg, customdata)
self._set_property("customdatasrc", arg, customdatasrc)
self._set_property("delta", arg, delta)
self._set_property("domain", arg, domain)
self._set_property("gauge", arg, gauge)
self._set_property("ids", arg, ids)
self._set_property("idssrc", arg, idssrc)
self._set_property("legend", arg, legend)
self._set_property("legendgrouptitle", arg, legendgrouptitle)
self._set_property("legendrank", arg, legendrank)
self._set_property("legendwidth", arg, legendwidth)
self._set_property("meta", arg, meta)
self._set_property("metasrc", arg, metasrc)
self._set_property("mode", arg, mode)
self._set_property("name", arg, name)
self._set_property("number", arg, number)
self._set_property("stream", arg, stream)
self._set_property("title", arg, title)
self._set_property("uid", arg, uid)
self._set_property("uirevision", arg, uirevision)
self._set_property("value", arg, value)
self._set_property("visible", arg, visible)
self._props["type"] = "indicator"
arg.pop("type", None)
self._process_kwargs(**dict(arg, **kwargs))
self._skip_invalid = False

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,934 @@
# --- THIS FILE IS AUTO-GENERATED ---
# Modifications will be overwitten the next time code generation run.
from plotly.basedatatypes import BaseTraceType as _BaseTraceType
import copy as _copy
class Parcats(_BaseTraceType):
_parent_path_str = ""
_path_str = "parcats"
_valid_props = {
"arrangement",
"bundlecolors",
"counts",
"countssrc",
"dimensiondefaults",
"dimensions",
"domain",
"hoverinfo",
"hoveron",
"hovertemplate",
"labelfont",
"legendgrouptitle",
"legendwidth",
"line",
"meta",
"metasrc",
"name",
"sortpaths",
"stream",
"tickfont",
"type",
"uid",
"uirevision",
"visible",
}
@property
def arrangement(self):
"""
Sets the drag interaction mode for categories and dimensions.
If `perpendicular`, the categories can only move along a line
perpendicular to the paths. If `freeform`, the categories can
freely move on the plane. If `fixed`, the categories and
dimensions are stationary.
The 'arrangement' property is an enumeration that may be specified as:
- One of the following enumeration values:
['perpendicular', 'freeform', 'fixed']
Returns
-------
Any
"""
return self["arrangement"]
@arrangement.setter
def arrangement(self, val):
self["arrangement"] = val
@property
def bundlecolors(self):
"""
Sort paths so that like colors are bundled together within each
category.
The 'bundlecolors' property must be specified as a bool
(either True, or False)
Returns
-------
bool
"""
return self["bundlecolors"]
@bundlecolors.setter
def bundlecolors(self, val):
self["bundlecolors"] = val
@property
def counts(self):
"""
The number of observations represented by each state. Defaults
to 1 so that each state represents one observation
The 'counts' property is a number and may be specified as:
- An int or float in the interval [0, inf]
- A tuple, list, or one-dimensional numpy array of the above
Returns
-------
int|float|numpy.ndarray
"""
return self["counts"]
@counts.setter
def counts(self, val):
self["counts"] = val
@property
def countssrc(self):
"""
Sets the source reference on Chart Studio Cloud for `counts`.
The 'countssrc' property must be specified as a string or
as a plotly.grid_objs.Column object
Returns
-------
str
"""
return self["countssrc"]
@countssrc.setter
def countssrc(self, val):
self["countssrc"] = val
@property
def dimensions(self):
"""
The dimensions (variables) of the parallel categories diagram.
The 'dimensions' property is a tuple of instances of
Dimension that may be specified as:
- A list or tuple of instances of plotly.graph_objs.parcats.Dimension
- A list or tuple of dicts of string/value properties that
will be passed to the Dimension constructor
Returns
-------
tuple[plotly.graph_objs.parcats.Dimension]
"""
return self["dimensions"]
@dimensions.setter
def dimensions(self, val):
self["dimensions"] = val
@property
def dimensiondefaults(self):
"""
When used in a template (as
layout.template.data.parcats.dimensiondefaults), sets the
default property values to use for elements of
parcats.dimensions
The 'dimensiondefaults' property is an instance of Dimension
that may be specified as:
- An instance of :class:`plotly.graph_objs.parcats.Dimension`
- A dict of string/value properties that will be passed
to the Dimension constructor
Returns
-------
plotly.graph_objs.parcats.Dimension
"""
return self["dimensiondefaults"]
@dimensiondefaults.setter
def dimensiondefaults(self, val):
self["dimensiondefaults"] = val
@property
def domain(self):
"""
The 'domain' property is an instance of Domain
that may be specified as:
- An instance of :class:`plotly.graph_objs.parcats.Domain`
- A dict of string/value properties that will be passed
to the Domain constructor
Returns
-------
plotly.graph_objs.parcats.Domain
"""
return self["domain"]
@domain.setter
def domain(self, val):
self["domain"] = val
@property
def hoverinfo(self):
"""
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.
The 'hoverinfo' property is a flaglist and may be specified
as a string containing:
- Any combination of ['count', 'probability'] joined with '+' characters
(e.g. 'count+probability')
OR exactly one of ['all', 'none', 'skip'] (e.g. 'skip')
Returns
-------
Any
"""
return self["hoverinfo"]
@hoverinfo.setter
def hoverinfo(self, val):
self["hoverinfo"] = val
@property
def hoveron(self):
"""
Sets the hover interaction mode for the parcats diagram. If
`category`, hover interaction take place per category. If
`color`, hover interactions take place per color per category.
If `dimension`, hover interactions take place across all
categories per dimension.
The 'hoveron' property is an enumeration that may be specified as:
- One of the following enumeration values:
['category', 'color', 'dimension']
Returns
-------
Any
"""
return self["hoveron"]
@hoveron.setter
def hoveron(self, val):
self["hoveron"] = val
@property
def hovertemplate(self):
"""
Template string used for rendering the information that appear
on hover box. Note that this will override `hoverinfo`.
Variables are inserted using %{variable}, for example "y: %{y}"
as well as %{xother}, {%_xother}, {%_xother_}, {%xother_}. When
showing info for several points, "xother" will be added to
those with different x positions from the first point. An
underscore before or after "(x|y)other" will add a space on
that side, only when this field is shown. Numbers are formatted
using d3-format's syntax %{variable:d3-format}, for example
"Price: %{y:$.2f}".
https://github.com/d3/d3-format/tree/v1.4.5#d3-format for
details on the formatting syntax. Dates are formatted using
d3-time-format's syntax %{variable|d3-time-format}, for example
"Day: %{2019-01-01|%A}". https://github.com/d3/d3-time-
format/tree/v2.2.3#locale_format for details on the date
formatting syntax. The variables available in `hovertemplate`
are the ones emitted as event data described at this link
https://plotly.com/javascript/plotlyjs-events/#event-data.
Additionally, every attributes that can be specified per-point
(the ones that are `arrayOk: true`) are available. This value
here applies when hovering over dimensions. Note that
`*categorycount`, "colorcount" and "bandcolorcount" are only
available when `hoveron` contains the "color" flagFinally, the
template string has access to variables `count`, `probability`,
`category`, `categorycount`, `colorcount` and `bandcolorcount`.
Anything contained in tag `<extra>` is displayed in the
secondary box, for example `<extra>%{fullData.name}</extra>`.
To hide the secondary box completely, use an empty tag
`<extra></extra>`.
The 'hovertemplate' property is a string and must be specified as:
- A string
- A number that will be converted to a string
Returns
-------
str
"""
return self["hovertemplate"]
@hovertemplate.setter
def hovertemplate(self, val):
self["hovertemplate"] = val
@property
def labelfont(self):
"""
Sets the font for the `dimension` labels.
The 'labelfont' property is an instance of Labelfont
that may be specified as:
- An instance of :class:`plotly.graph_objs.parcats.Labelfont`
- A dict of string/value properties that will be passed
to the Labelfont constructor
Returns
-------
plotly.graph_objs.parcats.Labelfont
"""
return self["labelfont"]
@labelfont.setter
def labelfont(self, val):
self["labelfont"] = val
@property
def legendgrouptitle(self):
"""
The 'legendgrouptitle' property is an instance of Legendgrouptitle
that may be specified as:
- An instance of :class:`plotly.graph_objs.parcats.Legendgrouptitle`
- A dict of string/value properties that will be passed
to the Legendgrouptitle constructor
Returns
-------
plotly.graph_objs.parcats.Legendgrouptitle
"""
return self["legendgrouptitle"]
@legendgrouptitle.setter
def legendgrouptitle(self, val):
self["legendgrouptitle"] = val
@property
def legendwidth(self):
"""
Sets the width (in px or fraction) of the legend for this
trace.
The 'legendwidth' property is a number and may be specified as:
- An int or float in the interval [0, inf]
Returns
-------
int|float
"""
return self["legendwidth"]
@legendwidth.setter
def legendwidth(self, val):
self["legendwidth"] = val
@property
def line(self):
"""
The 'line' property is an instance of Line
that may be specified as:
- An instance of :class:`plotly.graph_objs.parcats.Line`
- A dict of string/value properties that will be passed
to the Line constructor
Returns
-------
plotly.graph_objs.parcats.Line
"""
return self["line"]
@line.setter
def line(self, val):
self["line"] = val
@property
def meta(self):
"""
Assigns extra meta information associated with this trace that
can be used in various text attributes. Attributes such as
trace `name`, graph, axis and colorbar `title.text`, annotation
`text` `rangeselector`, `updatemenues` and `sliders` `label`
text all support `meta`. To access the trace `meta` values in
an attribute in the same trace, simply use `%{meta[i]}` where
`i` is the index or key of the `meta` item in question. To
access trace `meta` in layout attributes, use
`%{data[n[.meta[i]}` where `i` is the index or key of the
`meta` and `n` is the trace index.
The 'meta' property accepts values of any type
Returns
-------
Any|numpy.ndarray
"""
return self["meta"]
@meta.setter
def meta(self, val):
self["meta"] = val
@property
def metasrc(self):
"""
Sets the source reference on Chart Studio Cloud for `meta`.
The 'metasrc' property must be specified as a string or
as a plotly.grid_objs.Column object
Returns
-------
str
"""
return self["metasrc"]
@metasrc.setter
def metasrc(self, val):
self["metasrc"] = val
@property
def name(self):
"""
Sets the trace name. The trace name appears as the legend item
and on hover.
The 'name' property is a string and must be specified as:
- A string
- A number that will be converted to a string
Returns
-------
str
"""
return self["name"]
@name.setter
def name(self, val):
self["name"] = val
@property
def sortpaths(self):
"""
Sets the path sorting algorithm. If `forward`, sort paths based
on dimension categories from left to right. If `backward`, sort
paths based on dimensions categories from right to left.
The 'sortpaths' property is an enumeration that may be specified as:
- One of the following enumeration values:
['forward', 'backward']
Returns
-------
Any
"""
return self["sortpaths"]
@sortpaths.setter
def sortpaths(self, val):
self["sortpaths"] = val
@property
def stream(self):
"""
The 'stream' property is an instance of Stream
that may be specified as:
- An instance of :class:`plotly.graph_objs.parcats.Stream`
- A dict of string/value properties that will be passed
to the Stream constructor
Returns
-------
plotly.graph_objs.parcats.Stream
"""
return self["stream"]
@stream.setter
def stream(self, val):
self["stream"] = val
@property
def tickfont(self):
"""
Sets the font for the `category` labels.
The 'tickfont' property is an instance of Tickfont
that may be specified as:
- An instance of :class:`plotly.graph_objs.parcats.Tickfont`
- A dict of string/value properties that will be passed
to the Tickfont constructor
Returns
-------
plotly.graph_objs.parcats.Tickfont
"""
return self["tickfont"]
@tickfont.setter
def tickfont(self, val):
self["tickfont"] = val
@property
def uid(self):
"""
Assign an id to this trace, Use this to provide object
constancy between traces during animations and transitions.
The 'uid' property is a string and must be specified as:
- A string
- A number that will be converted to a string
Returns
-------
str
"""
return self["uid"]
@uid.setter
def uid(self, val):
self["uid"] = val
@property
def uirevision(self):
"""
Controls persistence of some user-driven changes to the trace:
`constraintrange` in `parcoords` traces, as well as some
`editable: true` modifications such as `name` and
`colorbar.title`. Defaults to `layout.uirevision`. Note that
other user-driven trace attribute changes are controlled by
`layout` attributes: `trace.visible` is controlled by
`layout.legend.uirevision`, `selectedpoints` is controlled by
`layout.selectionrevision`, and `colorbar.(x|y)` (accessible
with `config: {editable: true}`) is controlled by
`layout.editrevision`. Trace changes are tracked by `uid`,
which only falls back on trace index if no `uid` is provided.
So if your app can add/remove traces before the end of the
`data` array, such that the same trace has a different index,
you can still preserve user-driven changes if you give each
trace a `uid` that stays with it as it moves.
The 'uirevision' property accepts values of any type
Returns
-------
Any
"""
return self["uirevision"]
@uirevision.setter
def uirevision(self, val):
self["uirevision"] = val
@property
def visible(self):
"""
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).
The 'visible' property is an enumeration that may be specified as:
- One of the following enumeration values:
[True, False, 'legendonly']
Returns
-------
Any
"""
return self["visible"]
@visible.setter
def visible(self, val):
self["visible"] = val
@property
def type(self):
return self._props["type"]
@property
def _prop_descriptions(self):
return """\
arrangement
Sets the drag interaction mode for categories and
dimensions. If `perpendicular`, the categories can only
move along a line perpendicular to the paths. If
`freeform`, the categories can freely move on the
plane. If `fixed`, the categories and dimensions are
stationary.
bundlecolors
Sort paths so that like colors are bundled together
within each category.
counts
The number of observations represented by each state.
Defaults to 1 so that each state represents one
observation
countssrc
Sets the source reference on Chart Studio Cloud for
`counts`.
dimensions
The dimensions (variables) of the parallel categories
diagram.
dimensiondefaults
When used in a template (as
layout.template.data.parcats.dimensiondefaults), sets
the default property values to use for elements of
parcats.dimensions
domain
:class:`plotly.graph_objects.parcats.Domain` instance
or dict with compatible properties
hoverinfo
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.
hoveron
Sets the hover interaction mode for the parcats
diagram. If `category`, hover interaction take place
per category. If `color`, hover interactions take place
per color per category. If `dimension`, hover
interactions take place across all categories per
dimension.
hovertemplate
Template string used for rendering the information that
appear on hover box. Note that this will override
`hoverinfo`. Variables are inserted using %{variable},
for example "y: %{y}" as well as %{xother}, {%_xother},
{%_xother_}, {%xother_}. When showing info for several
points, "xother" will be added to those with different
x positions from the first point. An underscore before
or after "(x|y)other" will add a space on that side,
only when this field is shown. Numbers are formatted
using d3-format's syntax %{variable:d3-format}, for
example "Price: %{y:$.2f}".
https://github.com/d3/d3-format/tree/v1.4.5#d3-format
for details on the formatting syntax. Dates are
formatted using d3-time-format's syntax
%{variable|d3-time-format}, for example "Day:
%{2019-01-01|%A}". https://github.com/d3/d3-time-
format/tree/v2.2.3#locale_format for details on the
date formatting syntax. The variables available in
`hovertemplate` are the ones emitted as event data
described at this link
https://plotly.com/javascript/plotlyjs-events/#event-
data. Additionally, every attributes that can be
specified per-point (the ones that are `arrayOk: true`)
are available. This value here applies when hovering
over dimensions. Note that `*categorycount`,
"colorcount" and "bandcolorcount" are only available
when `hoveron` contains the "color" flagFinally, the
template string has access to variables `count`,
`probability`, `category`, `categorycount`,
`colorcount` and `bandcolorcount`. Anything contained
in tag `<extra>` is displayed in the secondary box, for
example `<extra>%{fullData.name}</extra>`. To hide the
secondary box completely, use an empty tag
`<extra></extra>`.
labelfont
Sets the font for the `dimension` labels.
legendgrouptitle
:class:`plotly.graph_objects.parcats.Legendgrouptitle`
instance or dict with compatible properties
legendwidth
Sets the width (in px or fraction) of the legend for
this trace.
line
:class:`plotly.graph_objects.parcats.Line` instance or
dict with compatible properties
meta
Assigns extra meta information associated with this
trace that can be used in various text attributes.
Attributes such as trace `name`, graph, axis and
colorbar `title.text`, annotation `text`
`rangeselector`, `updatemenues` and `sliders` `label`
text all support `meta`. To access the trace `meta`
values in an attribute in the same trace, simply use
`%{meta[i]}` where `i` is the index or key of the
`meta` item in question. To access trace `meta` in
layout attributes, use `%{data[n[.meta[i]}` where `i`
is the index or key of the `meta` and `n` is the trace
index.
metasrc
Sets the source reference on Chart Studio Cloud for
`meta`.
name
Sets the trace name. The trace name appears as the
legend item and on hover.
sortpaths
Sets the path sorting algorithm. If `forward`, sort
paths based on dimension categories from left to right.
If `backward`, sort paths based on dimensions
categories from right to left.
stream
:class:`plotly.graph_objects.parcats.Stream` instance
or dict with compatible properties
tickfont
Sets the font for the `category` labels.
uid
Assign an id to this trace, Use this to provide object
constancy between traces during animations and
transitions.
uirevision
Controls persistence of some user-driven changes to the
trace: `constraintrange` in `parcoords` traces, as well
as some `editable: true` modifications such as `name`
and `colorbar.title`. Defaults to `layout.uirevision`.
Note that other user-driven trace attribute changes are
controlled by `layout` attributes: `trace.visible` is
controlled by `layout.legend.uirevision`,
`selectedpoints` is controlled by
`layout.selectionrevision`, and `colorbar.(x|y)`
(accessible with `config: {editable: true}`) is
controlled by `layout.editrevision`. Trace changes are
tracked by `uid`, which only falls back on trace index
if no `uid` is provided. So if your app can add/remove
traces before the end of the `data` array, such that
the same trace has a different index, you can still
preserve user-driven changes if you give each trace a
`uid` that stays with it as it moves.
visible
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).
"""
def __init__(
self,
arg=None,
arrangement=None,
bundlecolors=None,
counts=None,
countssrc=None,
dimensions=None,
dimensiondefaults=None,
domain=None,
hoverinfo=None,
hoveron=None,
hovertemplate=None,
labelfont=None,
legendgrouptitle=None,
legendwidth=None,
line=None,
meta=None,
metasrc=None,
name=None,
sortpaths=None,
stream=None,
tickfont=None,
uid=None,
uirevision=None,
visible=None,
**kwargs,
):
"""
Construct a new Parcats object
Parallel categories diagram for multidimensional categorical
data.
Parameters
----------
arg
dict of properties compatible with this constructor or
an instance of :class:`plotly.graph_objs.Parcats`
arrangement
Sets the drag interaction mode for categories and
dimensions. If `perpendicular`, the categories can only
move along a line perpendicular to the paths. If
`freeform`, the categories can freely move on the
plane. If `fixed`, the categories and dimensions are
stationary.
bundlecolors
Sort paths so that like colors are bundled together
within each category.
counts
The number of observations represented by each state.
Defaults to 1 so that each state represents one
observation
countssrc
Sets the source reference on Chart Studio Cloud for
`counts`.
dimensions
The dimensions (variables) of the parallel categories
diagram.
dimensiondefaults
When used in a template (as
layout.template.data.parcats.dimensiondefaults), sets
the default property values to use for elements of
parcats.dimensions
domain
:class:`plotly.graph_objects.parcats.Domain` instance
or dict with compatible properties
hoverinfo
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.
hoveron
Sets the hover interaction mode for the parcats
diagram. If `category`, hover interaction take place
per category. If `color`, hover interactions take place
per color per category. If `dimension`, hover
interactions take place across all categories per
dimension.
hovertemplate
Template string used for rendering the information that
appear on hover box. Note that this will override
`hoverinfo`. Variables are inserted using %{variable},
for example "y: %{y}" as well as %{xother}, {%_xother},
{%_xother_}, {%xother_}. When showing info for several
points, "xother" will be added to those with different
x positions from the first point. An underscore before
or after "(x|y)other" will add a space on that side,
only when this field is shown. Numbers are formatted
using d3-format's syntax %{variable:d3-format}, for
example "Price: %{y:$.2f}".
https://github.com/d3/d3-format/tree/v1.4.5#d3-format
for details on the formatting syntax. Dates are
formatted using d3-time-format's syntax
%{variable|d3-time-format}, for example "Day:
%{2019-01-01|%A}". https://github.com/d3/d3-time-
format/tree/v2.2.3#locale_format for details on the
date formatting syntax. The variables available in
`hovertemplate` are the ones emitted as event data
described at this link
https://plotly.com/javascript/plotlyjs-events/#event-
data. Additionally, every attributes that can be
specified per-point (the ones that are `arrayOk: true`)
are available. This value here applies when hovering
over dimensions. Note that `*categorycount`,
"colorcount" and "bandcolorcount" are only available
when `hoveron` contains the "color" flagFinally, the
template string has access to variables `count`,
`probability`, `category`, `categorycount`,
`colorcount` and `bandcolorcount`. Anything contained
in tag `<extra>` is displayed in the secondary box, for
example `<extra>%{fullData.name}</extra>`. To hide the
secondary box completely, use an empty tag
`<extra></extra>`.
labelfont
Sets the font for the `dimension` labels.
legendgrouptitle
:class:`plotly.graph_objects.parcats.Legendgrouptitle`
instance or dict with compatible properties
legendwidth
Sets the width (in px or fraction) of the legend for
this trace.
line
:class:`plotly.graph_objects.parcats.Line` instance or
dict with compatible properties
meta
Assigns extra meta information associated with this
trace that can be used in various text attributes.
Attributes such as trace `name`, graph, axis and
colorbar `title.text`, annotation `text`
`rangeselector`, `updatemenues` and `sliders` `label`
text all support `meta`. To access the trace `meta`
values in an attribute in the same trace, simply use
`%{meta[i]}` where `i` is the index or key of the
`meta` item in question. To access trace `meta` in
layout attributes, use `%{data[n[.meta[i]}` where `i`
is the index or key of the `meta` and `n` is the trace
index.
metasrc
Sets the source reference on Chart Studio Cloud for
`meta`.
name
Sets the trace name. The trace name appears as the
legend item and on hover.
sortpaths
Sets the path sorting algorithm. If `forward`, sort
paths based on dimension categories from left to right.
If `backward`, sort paths based on dimensions
categories from right to left.
stream
:class:`plotly.graph_objects.parcats.Stream` instance
or dict with compatible properties
tickfont
Sets the font for the `category` labels.
uid
Assign an id to this trace, Use this to provide object
constancy between traces during animations and
transitions.
uirevision
Controls persistence of some user-driven changes to the
trace: `constraintrange` in `parcoords` traces, as well
as some `editable: true` modifications such as `name`
and `colorbar.title`. Defaults to `layout.uirevision`.
Note that other user-driven trace attribute changes are
controlled by `layout` attributes: `trace.visible` is
controlled by `layout.legend.uirevision`,
`selectedpoints` is controlled by
`layout.selectionrevision`, and `colorbar.(x|y)`
(accessible with `config: {editable: true}`) is
controlled by `layout.editrevision`. Trace changes are
tracked by `uid`, which only falls back on trace index
if no `uid` is provided. So if your app can add/remove
traces before the end of the `data` array, such that
the same trace has a different index, you can still
preserve user-driven changes if you give each trace a
`uid` that stays with it as it moves.
visible
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).
Returns
-------
Parcats
"""
super().__init__("parcats")
if "_parent" in kwargs:
self._parent = kwargs["_parent"]
return
if arg is None:
arg = {}
elif isinstance(arg, self.__class__):
arg = arg.to_plotly_json()
elif isinstance(arg, dict):
arg = _copy.copy(arg)
else:
raise ValueError("""\
The first argument to the plotly.graph_objs.Parcats
constructor must be a dict or
an instance of :class:`plotly.graph_objs.Parcats`""")
self._skip_invalid = kwargs.pop("skip_invalid", False)
self._validate = kwargs.pop("_validate", True)
self._set_property("arrangement", arg, arrangement)
self._set_property("bundlecolors", arg, bundlecolors)
self._set_property("counts", arg, counts)
self._set_property("countssrc", arg, countssrc)
self._set_property("dimensions", arg, dimensions)
self._set_property("dimensiondefaults", arg, dimensiondefaults)
self._set_property("domain", arg, domain)
self._set_property("hoverinfo", arg, hoverinfo)
self._set_property("hoveron", arg, hoveron)
self._set_property("hovertemplate", arg, hovertemplate)
self._set_property("labelfont", arg, labelfont)
self._set_property("legendgrouptitle", arg, legendgrouptitle)
self._set_property("legendwidth", arg, legendwidth)
self._set_property("line", arg, line)
self._set_property("meta", arg, meta)
self._set_property("metasrc", arg, metasrc)
self._set_property("name", arg, name)
self._set_property("sortpaths", arg, sortpaths)
self._set_property("stream", arg, stream)
self._set_property("tickfont", arg, tickfont)
self._set_property("uid", arg, uid)
self._set_property("uirevision", arg, uirevision)
self._set_property("visible", arg, visible)
self._props["type"] = "parcats"
arg.pop("type", None)
self._process_kwargs(**dict(arg, **kwargs))
self._skip_invalid = False

View File

@ -0,0 +1,919 @@
# --- THIS FILE IS AUTO-GENERATED ---
# Modifications will be overwitten the next time code generation run.
from plotly.basedatatypes import BaseTraceType as _BaseTraceType
import copy as _copy
class Parcoords(_BaseTraceType):
_parent_path_str = ""
_path_str = "parcoords"
_valid_props = {
"customdata",
"customdatasrc",
"dimensiondefaults",
"dimensions",
"domain",
"ids",
"idssrc",
"labelangle",
"labelfont",
"labelside",
"legend",
"legendgrouptitle",
"legendrank",
"legendwidth",
"line",
"meta",
"metasrc",
"name",
"rangefont",
"stream",
"tickfont",
"type",
"uid",
"uirevision",
"unselected",
"visible",
}
@property
def customdata(self):
"""
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
The 'customdata' property is an array that may be specified as a tuple,
list, numpy array, or pandas Series
Returns
-------
numpy.ndarray
"""
return self["customdata"]
@customdata.setter
def customdata(self, val):
self["customdata"] = val
@property
def customdatasrc(self):
"""
Sets the source reference on Chart Studio Cloud for
`customdata`.
The 'customdatasrc' property must be specified as a string or
as a plotly.grid_objs.Column object
Returns
-------
str
"""
return self["customdatasrc"]
@customdatasrc.setter
def customdatasrc(self, val):
self["customdatasrc"] = val
@property
def dimensions(self):
"""
The dimensions (variables) of the parallel coordinates chart.
2..60 dimensions are supported.
The 'dimensions' property is a tuple of instances of
Dimension that may be specified as:
- A list or tuple of instances of plotly.graph_objs.parcoords.Dimension
- A list or tuple of dicts of string/value properties that
will be passed to the Dimension constructor
Returns
-------
tuple[plotly.graph_objs.parcoords.Dimension]
"""
return self["dimensions"]
@dimensions.setter
def dimensions(self, val):
self["dimensions"] = val
@property
def dimensiondefaults(self):
"""
When used in a template (as
layout.template.data.parcoords.dimensiondefaults), sets the
default property values to use for elements of
parcoords.dimensions
The 'dimensiondefaults' property is an instance of Dimension
that may be specified as:
- An instance of :class:`plotly.graph_objs.parcoords.Dimension`
- A dict of string/value properties that will be passed
to the Dimension constructor
Returns
-------
plotly.graph_objs.parcoords.Dimension
"""
return self["dimensiondefaults"]
@dimensiondefaults.setter
def dimensiondefaults(self, val):
self["dimensiondefaults"] = val
@property
def domain(self):
"""
The 'domain' property is an instance of Domain
that may be specified as:
- An instance of :class:`plotly.graph_objs.parcoords.Domain`
- A dict of string/value properties that will be passed
to the Domain constructor
Returns
-------
plotly.graph_objs.parcoords.Domain
"""
return self["domain"]
@domain.setter
def domain(self, val):
self["domain"] = val
@property
def ids(self):
"""
Assigns id labels to each datum. These ids for object constancy
of data points during animation. Should be an array of strings,
not numbers or any other type.
The 'ids' property is an array that may be specified as a tuple,
list, numpy array, or pandas Series
Returns
-------
numpy.ndarray
"""
return self["ids"]
@ids.setter
def ids(self, val):
self["ids"] = val
@property
def idssrc(self):
"""
Sets the source reference on Chart Studio Cloud for `ids`.
The 'idssrc' property must be specified as a string or
as a plotly.grid_objs.Column object
Returns
-------
str
"""
return self["idssrc"]
@idssrc.setter
def idssrc(self, val):
self["idssrc"] = val
@property
def labelangle(self):
"""
Sets the angle of the labels with respect to the horizontal.
For example, a `tickangle` of -90 draws the labels vertically.
Tilted labels with "labelangle" may be positioned better inside
margins when `labelposition` is set to "bottom".
The 'labelangle' 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).
Returns
-------
int|float
"""
return self["labelangle"]
@labelangle.setter
def labelangle(self, val):
self["labelangle"] = val
@property
def labelfont(self):
"""
Sets the font for the `dimension` labels.
The 'labelfont' property is an instance of Labelfont
that may be specified as:
- An instance of :class:`plotly.graph_objs.parcoords.Labelfont`
- A dict of string/value properties that will be passed
to the Labelfont constructor
Returns
-------
plotly.graph_objs.parcoords.Labelfont
"""
return self["labelfont"]
@labelfont.setter
def labelfont(self, val):
self["labelfont"] = val
@property
def labelside(self):
"""
Specifies the location of the `label`. "top" positions labels
above, next to the title "bottom" positions labels below the
graph Tilted labels with "labelangle" may be positioned better
inside margins when `labelposition` is set to "bottom".
The 'labelside' property is an enumeration that may be specified as:
- One of the following enumeration values:
['top', 'bottom']
Returns
-------
Any
"""
return self["labelside"]
@labelside.setter
def labelside(self, val):
self["labelside"] = val
@property
def legend(self):
"""
Sets the reference to a legend to show this trace in.
References to these legends are "legend", "legend2", "legend3",
etc. Settings for these legends are set in the layout, under
`layout.legend`, `layout.legend2`, etc.
The 'legend' property is an identifier of a particular
subplot, of type 'legend', that may be specified as the string 'legend'
optionally followed by an integer >= 1
(e.g. 'legend', 'legend1', 'legend2', 'legend3', etc.)
Returns
-------
str
"""
return self["legend"]
@legend.setter
def legend(self, val):
self["legend"] = val
@property
def legendgrouptitle(self):
"""
The 'legendgrouptitle' property is an instance of Legendgrouptitle
that may be specified as:
- An instance of :class:`plotly.graph_objs.parcoords.Legendgrouptitle`
- A dict of string/value properties that will be passed
to the Legendgrouptitle constructor
Returns
-------
plotly.graph_objs.parcoords.Legendgrouptitle
"""
return self["legendgrouptitle"]
@legendgrouptitle.setter
def legendgrouptitle(self, val):
self["legendgrouptitle"] = val
@property
def legendrank(self):
"""
Sets the legend rank for this trace. Items and groups with
smaller ranks are presented on top/left side while with
"reversed" `legend.traceorder` they are on bottom/right side.
The default legendrank is 1000, so that you can use ranks less
than 1000 to place certain items before all unranked items, and
ranks greater than 1000 to go after all unranked items. When
having unranked or equal rank items shapes would be displayed
after traces i.e. according to their order in data and layout.
The 'legendrank' property is a number and may be specified as:
- An int or float
Returns
-------
int|float
"""
return self["legendrank"]
@legendrank.setter
def legendrank(self, val):
self["legendrank"] = val
@property
def legendwidth(self):
"""
Sets the width (in px or fraction) of the legend for this
trace.
The 'legendwidth' property is a number and may be specified as:
- An int or float in the interval [0, inf]
Returns
-------
int|float
"""
return self["legendwidth"]
@legendwidth.setter
def legendwidth(self, val):
self["legendwidth"] = val
@property
def line(self):
"""
The 'line' property is an instance of Line
that may be specified as:
- An instance of :class:`plotly.graph_objs.parcoords.Line`
- A dict of string/value properties that will be passed
to the Line constructor
Returns
-------
plotly.graph_objs.parcoords.Line
"""
return self["line"]
@line.setter
def line(self, val):
self["line"] = val
@property
def meta(self):
"""
Assigns extra meta information associated with this trace that
can be used in various text attributes. Attributes such as
trace `name`, graph, axis and colorbar `title.text`, annotation
`text` `rangeselector`, `updatemenues` and `sliders` `label`
text all support `meta`. To access the trace `meta` values in
an attribute in the same trace, simply use `%{meta[i]}` where
`i` is the index or key of the `meta` item in question. To
access trace `meta` in layout attributes, use
`%{data[n[.meta[i]}` where `i` is the index or key of the
`meta` and `n` is the trace index.
The 'meta' property accepts values of any type
Returns
-------
Any|numpy.ndarray
"""
return self["meta"]
@meta.setter
def meta(self, val):
self["meta"] = val
@property
def metasrc(self):
"""
Sets the source reference on Chart Studio Cloud for `meta`.
The 'metasrc' property must be specified as a string or
as a plotly.grid_objs.Column object
Returns
-------
str
"""
return self["metasrc"]
@metasrc.setter
def metasrc(self, val):
self["metasrc"] = val
@property
def name(self):
"""
Sets the trace name. The trace name appears as the legend item
and on hover.
The 'name' property is a string and must be specified as:
- A string
- A number that will be converted to a string
Returns
-------
str
"""
return self["name"]
@name.setter
def name(self, val):
self["name"] = val
@property
def rangefont(self):
"""
Sets the font for the `dimension` range values.
The 'rangefont' property is an instance of Rangefont
that may be specified as:
- An instance of :class:`plotly.graph_objs.parcoords.Rangefont`
- A dict of string/value properties that will be passed
to the Rangefont constructor
Returns
-------
plotly.graph_objs.parcoords.Rangefont
"""
return self["rangefont"]
@rangefont.setter
def rangefont(self, val):
self["rangefont"] = val
@property
def stream(self):
"""
The 'stream' property is an instance of Stream
that may be specified as:
- An instance of :class:`plotly.graph_objs.parcoords.Stream`
- A dict of string/value properties that will be passed
to the Stream constructor
Returns
-------
plotly.graph_objs.parcoords.Stream
"""
return self["stream"]
@stream.setter
def stream(self, val):
self["stream"] = val
@property
def tickfont(self):
"""
Sets the font for the `dimension` tick values.
The 'tickfont' property is an instance of Tickfont
that may be specified as:
- An instance of :class:`plotly.graph_objs.parcoords.Tickfont`
- A dict of string/value properties that will be passed
to the Tickfont constructor
Returns
-------
plotly.graph_objs.parcoords.Tickfont
"""
return self["tickfont"]
@tickfont.setter
def tickfont(self, val):
self["tickfont"] = val
@property
def uid(self):
"""
Assign an id to this trace, Use this to provide object
constancy between traces during animations and transitions.
The 'uid' property is a string and must be specified as:
- A string
- A number that will be converted to a string
Returns
-------
str
"""
return self["uid"]
@uid.setter
def uid(self, val):
self["uid"] = val
@property
def uirevision(self):
"""
Controls persistence of some user-driven changes to the trace:
`constraintrange` in `parcoords` traces, as well as some
`editable: true` modifications such as `name` and
`colorbar.title`. Defaults to `layout.uirevision`. Note that
other user-driven trace attribute changes are controlled by
`layout` attributes: `trace.visible` is controlled by
`layout.legend.uirevision`, `selectedpoints` is controlled by
`layout.selectionrevision`, and `colorbar.(x|y)` (accessible
with `config: {editable: true}`) is controlled by
`layout.editrevision`. Trace changes are tracked by `uid`,
which only falls back on trace index if no `uid` is provided.
So if your app can add/remove traces before the end of the
`data` array, such that the same trace has a different index,
you can still preserve user-driven changes if you give each
trace a `uid` that stays with it as it moves.
The 'uirevision' property accepts values of any type
Returns
-------
Any
"""
return self["uirevision"]
@uirevision.setter
def uirevision(self, val):
self["uirevision"] = val
@property
def unselected(self):
"""
The 'unselected' property is an instance of Unselected
that may be specified as:
- An instance of :class:`plotly.graph_objs.parcoords.Unselected`
- A dict of string/value properties that will be passed
to the Unselected constructor
Returns
-------
plotly.graph_objs.parcoords.Unselected
"""
return self["unselected"]
@unselected.setter
def unselected(self, val):
self["unselected"] = val
@property
def visible(self):
"""
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).
The 'visible' property is an enumeration that may be specified as:
- One of the following enumeration values:
[True, False, 'legendonly']
Returns
-------
Any
"""
return self["visible"]
@visible.setter
def visible(self, val):
self["visible"] = val
@property
def type(self):
return self._props["type"]
@property
def _prop_descriptions(self):
return """\
customdata
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
customdatasrc
Sets the source reference on Chart Studio Cloud for
`customdata`.
dimensions
The dimensions (variables) of the parallel coordinates
chart. 2..60 dimensions are supported.
dimensiondefaults
When used in a template (as
layout.template.data.parcoords.dimensiondefaults), sets
the default property values to use for elements of
parcoords.dimensions
domain
:class:`plotly.graph_objects.parcoords.Domain` instance
or dict with compatible properties
ids
Assigns id labels to each datum. These ids for object
constancy of data points during animation. Should be an
array of strings, not numbers or any other type.
idssrc
Sets the source reference on Chart Studio Cloud for
`ids`.
labelangle
Sets the angle of the labels with respect to the
horizontal. For example, a `tickangle` of -90 draws the
labels vertically. Tilted labels with "labelangle" may
be positioned better inside margins when
`labelposition` is set to "bottom".
labelfont
Sets the font for the `dimension` labels.
labelside
Specifies the location of the `label`. "top" positions
labels above, next to the title "bottom" positions
labels below the graph Tilted labels with "labelangle"
may be positioned better inside margins when
`labelposition` is set to "bottom".
legend
Sets the reference to a legend to show this trace in.
References to these legends are "legend", "legend2",
"legend3", etc. Settings for these legends are set in
the layout, under `layout.legend`, `layout.legend2`,
etc.
legendgrouptitle
:class:`plotly.graph_objects.parcoords.Legendgrouptitle
` instance or dict with compatible properties
legendrank
Sets the legend rank for this trace. Items and groups
with smaller ranks are presented on top/left side while
with "reversed" `legend.traceorder` they are on
bottom/right side. The default legendrank is 1000, so
that you can use ranks less than 1000 to place certain
items before all unranked items, and ranks greater than
1000 to go after all unranked items. When having
unranked or equal rank items shapes would be displayed
after traces i.e. according to their order in data and
layout.
legendwidth
Sets the width (in px or fraction) of the legend for
this trace.
line
:class:`plotly.graph_objects.parcoords.Line` instance
or dict with compatible properties
meta
Assigns extra meta information associated with this
trace that can be used in various text attributes.
Attributes such as trace `name`, graph, axis and
colorbar `title.text`, annotation `text`
`rangeselector`, `updatemenues` and `sliders` `label`
text all support `meta`. To access the trace `meta`
values in an attribute in the same trace, simply use
`%{meta[i]}` where `i` is the index or key of the
`meta` item in question. To access trace `meta` in
layout attributes, use `%{data[n[.meta[i]}` where `i`
is the index or key of the `meta` and `n` is the trace
index.
metasrc
Sets the source reference on Chart Studio Cloud for
`meta`.
name
Sets the trace name. The trace name appears as the
legend item and on hover.
rangefont
Sets the font for the `dimension` range values.
stream
:class:`plotly.graph_objects.parcoords.Stream` instance
or dict with compatible properties
tickfont
Sets the font for the `dimension` tick values.
uid
Assign an id to this trace, Use this to provide object
constancy between traces during animations and
transitions.
uirevision
Controls persistence of some user-driven changes to the
trace: `constraintrange` in `parcoords` traces, as well
as some `editable: true` modifications such as `name`
and `colorbar.title`. Defaults to `layout.uirevision`.
Note that other user-driven trace attribute changes are
controlled by `layout` attributes: `trace.visible` is
controlled by `layout.legend.uirevision`,
`selectedpoints` is controlled by
`layout.selectionrevision`, and `colorbar.(x|y)`
(accessible with `config: {editable: true}`) is
controlled by `layout.editrevision`. Trace changes are
tracked by `uid`, which only falls back on trace index
if no `uid` is provided. So if your app can add/remove
traces before the end of the `data` array, such that
the same trace has a different index, you can still
preserve user-driven changes if you give each trace a
`uid` that stays with it as it moves.
unselected
:class:`plotly.graph_objects.parcoords.Unselected`
instance or dict with compatible properties
visible
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).
"""
def __init__(
self,
arg=None,
customdata=None,
customdatasrc=None,
dimensions=None,
dimensiondefaults=None,
domain=None,
ids=None,
idssrc=None,
labelangle=None,
labelfont=None,
labelside=None,
legend=None,
legendgrouptitle=None,
legendrank=None,
legendwidth=None,
line=None,
meta=None,
metasrc=None,
name=None,
rangefont=None,
stream=None,
tickfont=None,
uid=None,
uirevision=None,
unselected=None,
visible=None,
**kwargs,
):
"""
Construct a new Parcoords object
Parallel coordinates for multidimensional exploratory data
analysis. The samples are specified in `dimensions`. The colors
are set in `line.color`.
Parameters
----------
arg
dict of properties compatible with this constructor or
an instance of :class:`plotly.graph_objs.Parcoords`
customdata
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
customdatasrc
Sets the source reference on Chart Studio Cloud for
`customdata`.
dimensions
The dimensions (variables) of the parallel coordinates
chart. 2..60 dimensions are supported.
dimensiondefaults
When used in a template (as
layout.template.data.parcoords.dimensiondefaults), sets
the default property values to use for elements of
parcoords.dimensions
domain
:class:`plotly.graph_objects.parcoords.Domain` instance
or dict with compatible properties
ids
Assigns id labels to each datum. These ids for object
constancy of data points during animation. Should be an
array of strings, not numbers or any other type.
idssrc
Sets the source reference on Chart Studio Cloud for
`ids`.
labelangle
Sets the angle of the labels with respect to the
horizontal. For example, a `tickangle` of -90 draws the
labels vertically. Tilted labels with "labelangle" may
be positioned better inside margins when
`labelposition` is set to "bottom".
labelfont
Sets the font for the `dimension` labels.
labelside
Specifies the location of the `label`. "top" positions
labels above, next to the title "bottom" positions
labels below the graph Tilted labels with "labelangle"
may be positioned better inside margins when
`labelposition` is set to "bottom".
legend
Sets the reference to a legend to show this trace in.
References to these legends are "legend", "legend2",
"legend3", etc. Settings for these legends are set in
the layout, under `layout.legend`, `layout.legend2`,
etc.
legendgrouptitle
:class:`plotly.graph_objects.parcoords.Legendgrouptitle
` instance or dict with compatible properties
legendrank
Sets the legend rank for this trace. Items and groups
with smaller ranks are presented on top/left side while
with "reversed" `legend.traceorder` they are on
bottom/right side. The default legendrank is 1000, so
that you can use ranks less than 1000 to place certain
items before all unranked items, and ranks greater than
1000 to go after all unranked items. When having
unranked or equal rank items shapes would be displayed
after traces i.e. according to their order in data and
layout.
legendwidth
Sets the width (in px or fraction) of the legend for
this trace.
line
:class:`plotly.graph_objects.parcoords.Line` instance
or dict with compatible properties
meta
Assigns extra meta information associated with this
trace that can be used in various text attributes.
Attributes such as trace `name`, graph, axis and
colorbar `title.text`, annotation `text`
`rangeselector`, `updatemenues` and `sliders` `label`
text all support `meta`. To access the trace `meta`
values in an attribute in the same trace, simply use
`%{meta[i]}` where `i` is the index or key of the
`meta` item in question. To access trace `meta` in
layout attributes, use `%{data[n[.meta[i]}` where `i`
is the index or key of the `meta` and `n` is the trace
index.
metasrc
Sets the source reference on Chart Studio Cloud for
`meta`.
name
Sets the trace name. The trace name appears as the
legend item and on hover.
rangefont
Sets the font for the `dimension` range values.
stream
:class:`plotly.graph_objects.parcoords.Stream` instance
or dict with compatible properties
tickfont
Sets the font for the `dimension` tick values.
uid
Assign an id to this trace, Use this to provide object
constancy between traces during animations and
transitions.
uirevision
Controls persistence of some user-driven changes to the
trace: `constraintrange` in `parcoords` traces, as well
as some `editable: true` modifications such as `name`
and `colorbar.title`. Defaults to `layout.uirevision`.
Note that other user-driven trace attribute changes are
controlled by `layout` attributes: `trace.visible` is
controlled by `layout.legend.uirevision`,
`selectedpoints` is controlled by
`layout.selectionrevision`, and `colorbar.(x|y)`
(accessible with `config: {editable: true}`) is
controlled by `layout.editrevision`. Trace changes are
tracked by `uid`, which only falls back on trace index
if no `uid` is provided. So if your app can add/remove
traces before the end of the `data` array, such that
the same trace has a different index, you can still
preserve user-driven changes if you give each trace a
`uid` that stays with it as it moves.
unselected
:class:`plotly.graph_objects.parcoords.Unselected`
instance or dict with compatible properties
visible
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).
Returns
-------
Parcoords
"""
super().__init__("parcoords")
if "_parent" in kwargs:
self._parent = kwargs["_parent"]
return
if arg is None:
arg = {}
elif isinstance(arg, self.__class__):
arg = arg.to_plotly_json()
elif isinstance(arg, dict):
arg = _copy.copy(arg)
else:
raise ValueError("""\
The first argument to the plotly.graph_objs.Parcoords
constructor must be a dict or
an instance of :class:`plotly.graph_objs.Parcoords`""")
self._skip_invalid = kwargs.pop("skip_invalid", False)
self._validate = kwargs.pop("_validate", True)
self._set_property("customdata", arg, customdata)
self._set_property("customdatasrc", arg, customdatasrc)
self._set_property("dimensions", arg, dimensions)
self._set_property("dimensiondefaults", arg, dimensiondefaults)
self._set_property("domain", arg, domain)
self._set_property("ids", arg, ids)
self._set_property("idssrc", arg, idssrc)
self._set_property("labelangle", arg, labelangle)
self._set_property("labelfont", arg, labelfont)
self._set_property("labelside", arg, labelside)
self._set_property("legend", arg, legend)
self._set_property("legendgrouptitle", arg, legendgrouptitle)
self._set_property("legendrank", arg, legendrank)
self._set_property("legendwidth", arg, legendwidth)
self._set_property("line", arg, line)
self._set_property("meta", arg, meta)
self._set_property("metasrc", arg, metasrc)
self._set_property("name", arg, name)
self._set_property("rangefont", arg, rangefont)
self._set_property("stream", arg, stream)
self._set_property("tickfont", arg, tickfont)
self._set_property("uid", arg, uid)
self._set_property("uirevision", arg, uirevision)
self._set_property("unselected", arg, unselected)
self._set_property("visible", arg, visible)
self._props["type"] = "parcoords"
arg.pop("type", None)
self._process_kwargs(**dict(arg, **kwargs))
self._skip_invalid = False

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,966 @@
# --- THIS FILE IS AUTO-GENERATED ---
# Modifications will be overwitten the next time code generation run.
from plotly.basedatatypes import BaseTraceType as _BaseTraceType
import copy as _copy
class Sankey(_BaseTraceType):
_parent_path_str = ""
_path_str = "sankey"
_valid_props = {
"arrangement",
"customdata",
"customdatasrc",
"domain",
"hoverinfo",
"hoverlabel",
"ids",
"idssrc",
"legend",
"legendgrouptitle",
"legendrank",
"legendwidth",
"link",
"meta",
"metasrc",
"name",
"node",
"orientation",
"selectedpoints",
"stream",
"textfont",
"type",
"uid",
"uirevision",
"valueformat",
"valuesuffix",
"visible",
}
@property
def arrangement(self):
"""
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.
The 'arrangement' property is an enumeration that may be specified as:
- One of the following enumeration values:
['snap', 'perpendicular', 'freeform', 'fixed']
Returns
-------
Any
"""
return self["arrangement"]
@arrangement.setter
def arrangement(self, val):
self["arrangement"] = val
@property
def customdata(self):
"""
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
The 'customdata' property is an array that may be specified as a tuple,
list, numpy array, or pandas Series
Returns
-------
numpy.ndarray
"""
return self["customdata"]
@customdata.setter
def customdata(self, val):
self["customdata"] = val
@property
def customdatasrc(self):
"""
Sets the source reference on Chart Studio Cloud for
`customdata`.
The 'customdatasrc' property must be specified as a string or
as a plotly.grid_objs.Column object
Returns
-------
str
"""
return self["customdatasrc"]
@customdatasrc.setter
def customdatasrc(self, val):
self["customdatasrc"] = val
@property
def domain(self):
"""
The 'domain' property is an instance of Domain
that may be specified as:
- An instance of :class:`plotly.graph_objs.sankey.Domain`
- A dict of string/value properties that will be passed
to the Domain constructor
Returns
-------
plotly.graph_objs.sankey.Domain
"""
return self["domain"]
@domain.setter
def domain(self, val):
self["domain"] = val
@property
def hoverinfo(self):
"""
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.
Note that this attribute is superseded by `node.hoverinfo` and
`node.hoverinfo` for nodes and links respectively.
The 'hoverinfo' property is a flaglist and may be specified
as a string containing:
- Any combination of [] joined with '+' characters
(e.g. '')
OR exactly one of ['all', 'none', 'skip'] (e.g. 'skip')
Returns
-------
Any
"""
return self["hoverinfo"]
@hoverinfo.setter
def hoverinfo(self, val):
self["hoverinfo"] = val
@property
def hoverlabel(self):
"""
The 'hoverlabel' property is an instance of Hoverlabel
that may be specified as:
- An instance of :class:`plotly.graph_objs.sankey.Hoverlabel`
- A dict of string/value properties that will be passed
to the Hoverlabel constructor
Returns
-------
plotly.graph_objs.sankey.Hoverlabel
"""
return self["hoverlabel"]
@hoverlabel.setter
def hoverlabel(self, val):
self["hoverlabel"] = val
@property
def ids(self):
"""
Assigns id labels to each datum. These ids for object constancy
of data points during animation. Should be an array of strings,
not numbers or any other type.
The 'ids' property is an array that may be specified as a tuple,
list, numpy array, or pandas Series
Returns
-------
numpy.ndarray
"""
return self["ids"]
@ids.setter
def ids(self, val):
self["ids"] = val
@property
def idssrc(self):
"""
Sets the source reference on Chart Studio Cloud for `ids`.
The 'idssrc' property must be specified as a string or
as a plotly.grid_objs.Column object
Returns
-------
str
"""
return self["idssrc"]
@idssrc.setter
def idssrc(self, val):
self["idssrc"] = val
@property
def legend(self):
"""
Sets the reference to a legend to show this trace in.
References to these legends are "legend", "legend2", "legend3",
etc. Settings for these legends are set in the layout, under
`layout.legend`, `layout.legend2`, etc.
The 'legend' property is an identifier of a particular
subplot, of type 'legend', that may be specified as the string 'legend'
optionally followed by an integer >= 1
(e.g. 'legend', 'legend1', 'legend2', 'legend3', etc.)
Returns
-------
str
"""
return self["legend"]
@legend.setter
def legend(self, val):
self["legend"] = val
@property
def legendgrouptitle(self):
"""
The 'legendgrouptitle' property is an instance of Legendgrouptitle
that may be specified as:
- An instance of :class:`plotly.graph_objs.sankey.Legendgrouptitle`
- A dict of string/value properties that will be passed
to the Legendgrouptitle constructor
Returns
-------
plotly.graph_objs.sankey.Legendgrouptitle
"""
return self["legendgrouptitle"]
@legendgrouptitle.setter
def legendgrouptitle(self, val):
self["legendgrouptitle"] = val
@property
def legendrank(self):
"""
Sets the legend rank for this trace. Items and groups with
smaller ranks are presented on top/left side while with
"reversed" `legend.traceorder` they are on bottom/right side.
The default legendrank is 1000, so that you can use ranks less
than 1000 to place certain items before all unranked items, and
ranks greater than 1000 to go after all unranked items. When
having unranked or equal rank items shapes would be displayed
after traces i.e. according to their order in data and layout.
The 'legendrank' property is a number and may be specified as:
- An int or float
Returns
-------
int|float
"""
return self["legendrank"]
@legendrank.setter
def legendrank(self, val):
self["legendrank"] = val
@property
def legendwidth(self):
"""
Sets the width (in px or fraction) of the legend for this
trace.
The 'legendwidth' property is a number and may be specified as:
- An int or float in the interval [0, inf]
Returns
-------
int|float
"""
return self["legendwidth"]
@legendwidth.setter
def legendwidth(self, val):
self["legendwidth"] = val
@property
def link(self):
"""
The links of the Sankey plot.
The 'link' property is an instance of Link
that may be specified as:
- An instance of :class:`plotly.graph_objs.sankey.Link`
- A dict of string/value properties that will be passed
to the Link constructor
Returns
-------
plotly.graph_objs.sankey.Link
"""
return self["link"]
@link.setter
def link(self, val):
self["link"] = val
@property
def meta(self):
"""
Assigns extra meta information associated with this trace that
can be used in various text attributes. Attributes such as
trace `name`, graph, axis and colorbar `title.text`, annotation
`text` `rangeselector`, `updatemenues` and `sliders` `label`
text all support `meta`. To access the trace `meta` values in
an attribute in the same trace, simply use `%{meta[i]}` where
`i` is the index or key of the `meta` item in question. To
access trace `meta` in layout attributes, use
`%{data[n[.meta[i]}` where `i` is the index or key of the
`meta` and `n` is the trace index.
The 'meta' property accepts values of any type
Returns
-------
Any|numpy.ndarray
"""
return self["meta"]
@meta.setter
def meta(self, val):
self["meta"] = val
@property
def metasrc(self):
"""
Sets the source reference on Chart Studio Cloud for `meta`.
The 'metasrc' property must be specified as a string or
as a plotly.grid_objs.Column object
Returns
-------
str
"""
return self["metasrc"]
@metasrc.setter
def metasrc(self, val):
self["metasrc"] = val
@property
def name(self):
"""
Sets the trace name. The trace name appears as the legend item
and on hover.
The 'name' property is a string and must be specified as:
- A string
- A number that will be converted to a string
Returns
-------
str
"""
return self["name"]
@name.setter
def name(self, val):
self["name"] = val
@property
def node(self):
"""
The nodes of the Sankey plot.
The 'node' property is an instance of Node
that may be specified as:
- An instance of :class:`plotly.graph_objs.sankey.Node`
- A dict of string/value properties that will be passed
to the Node constructor
Returns
-------
plotly.graph_objs.sankey.Node
"""
return self["node"]
@node.setter
def node(self, val):
self["node"] = val
@property
def orientation(self):
"""
Sets the orientation of the Sankey diagram.
The 'orientation' property is an enumeration that may be specified as:
- One of the following enumeration values:
['v', 'h']
Returns
-------
Any
"""
return self["orientation"]
@orientation.setter
def orientation(self, val):
self["orientation"] = val
@property
def selectedpoints(self):
"""
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.
The 'selectedpoints' property accepts values of any type
Returns
-------
Any
"""
return self["selectedpoints"]
@selectedpoints.setter
def selectedpoints(self, val):
self["selectedpoints"] = val
@property
def stream(self):
"""
The 'stream' property is an instance of Stream
that may be specified as:
- An instance of :class:`plotly.graph_objs.sankey.Stream`
- A dict of string/value properties that will be passed
to the Stream constructor
Returns
-------
plotly.graph_objs.sankey.Stream
"""
return self["stream"]
@stream.setter
def stream(self, val):
self["stream"] = val
@property
def textfont(self):
"""
Sets the font for node labels
The 'textfont' property is an instance of Textfont
that may be specified as:
- An instance of :class:`plotly.graph_objs.sankey.Textfont`
- A dict of string/value properties that will be passed
to the Textfont constructor
Returns
-------
plotly.graph_objs.sankey.Textfont
"""
return self["textfont"]
@textfont.setter
def textfont(self, val):
self["textfont"] = val
@property
def uid(self):
"""
Assign an id to this trace, Use this to provide object
constancy between traces during animations and transitions.
The 'uid' property is a string and must be specified as:
- A string
- A number that will be converted to a string
Returns
-------
str
"""
return self["uid"]
@uid.setter
def uid(self, val):
self["uid"] = val
@property
def uirevision(self):
"""
Controls persistence of some user-driven changes to the trace:
`constraintrange` in `parcoords` traces, as well as some
`editable: true` modifications such as `name` and
`colorbar.title`. Defaults to `layout.uirevision`. Note that
other user-driven trace attribute changes are controlled by
`layout` attributes: `trace.visible` is controlled by
`layout.legend.uirevision`, `selectedpoints` is controlled by
`layout.selectionrevision`, and `colorbar.(x|y)` (accessible
with `config: {editable: true}`) is controlled by
`layout.editrevision`. Trace changes are tracked by `uid`,
which only falls back on trace index if no `uid` is provided.
So if your app can add/remove traces before the end of the
`data` array, such that the same trace has a different index,
you can still preserve user-driven changes if you give each
trace a `uid` that stays with it as it moves.
The 'uirevision' property accepts values of any type
Returns
-------
Any
"""
return self["uirevision"]
@uirevision.setter
def uirevision(self, val):
self["uirevision"] = val
@property
def valueformat(self):
"""
Sets the value formatting rule using d3 formatting mini-
languages which are very similar to those in Python. For
numbers, see:
https://github.com/d3/d3-format/tree/v1.4.5#d3-format.
The 'valueformat' property is a string and must be specified as:
- A string
- A number that will be converted to a string
Returns
-------
str
"""
return self["valueformat"]
@valueformat.setter
def valueformat(self, val):
self["valueformat"] = val
@property
def valuesuffix(self):
"""
Adds a unit to follow the value in the hover tooltip. Add a
space if a separation is necessary from the value.
The 'valuesuffix' property is a string and must be specified as:
- A string
- A number that will be converted to a string
Returns
-------
str
"""
return self["valuesuffix"]
@valuesuffix.setter
def valuesuffix(self, val):
self["valuesuffix"] = val
@property
def visible(self):
"""
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).
The 'visible' property is an enumeration that may be specified as:
- One of the following enumeration values:
[True, False, 'legendonly']
Returns
-------
Any
"""
return self["visible"]
@visible.setter
def visible(self, val):
self["visible"] = val
@property
def type(self):
return self._props["type"]
@property
def _prop_descriptions(self):
return """\
arrangement
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.
customdata
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
customdatasrc
Sets the source reference on Chart Studio Cloud for
`customdata`.
domain
:class:`plotly.graph_objects.sankey.Domain` instance or
dict with compatible properties
hoverinfo
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. Note that this attribute is
superseded by `node.hoverinfo` and `node.hoverinfo` for
nodes and links respectively.
hoverlabel
:class:`plotly.graph_objects.sankey.Hoverlabel`
instance or dict with compatible properties
ids
Assigns id labels to each datum. These ids for object
constancy of data points during animation. Should be an
array of strings, not numbers or any other type.
idssrc
Sets the source reference on Chart Studio Cloud for
`ids`.
legend
Sets the reference to a legend to show this trace in.
References to these legends are "legend", "legend2",
"legend3", etc. Settings for these legends are set in
the layout, under `layout.legend`, `layout.legend2`,
etc.
legendgrouptitle
:class:`plotly.graph_objects.sankey.Legendgrouptitle`
instance or dict with compatible properties
legendrank
Sets the legend rank for this trace. Items and groups
with smaller ranks are presented on top/left side while
with "reversed" `legend.traceorder` they are on
bottom/right side. The default legendrank is 1000, so
that you can use ranks less than 1000 to place certain
items before all unranked items, and ranks greater than
1000 to go after all unranked items. When having
unranked or equal rank items shapes would be displayed
after traces i.e. according to their order in data and
layout.
legendwidth
Sets the width (in px or fraction) of the legend for
this trace.
link
The links of the Sankey plot.
meta
Assigns extra meta information associated with this
trace that can be used in various text attributes.
Attributes such as trace `name`, graph, axis and
colorbar `title.text`, annotation `text`
`rangeselector`, `updatemenues` and `sliders` `label`
text all support `meta`. To access the trace `meta`
values in an attribute in the same trace, simply use
`%{meta[i]}` where `i` is the index or key of the
`meta` item in question. To access trace `meta` in
layout attributes, use `%{data[n[.meta[i]}` where `i`
is the index or key of the `meta` and `n` is the trace
index.
metasrc
Sets the source reference on Chart Studio Cloud for
`meta`.
name
Sets the trace name. The trace name appears as the
legend item and on hover.
node
The nodes of the Sankey plot.
orientation
Sets the orientation of the Sankey diagram.
selectedpoints
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.
stream
:class:`plotly.graph_objects.sankey.Stream` instance or
dict with compatible properties
textfont
Sets the font for node labels
uid
Assign an id to this trace, Use this to provide object
constancy between traces during animations and
transitions.
uirevision
Controls persistence of some user-driven changes to the
trace: `constraintrange` in `parcoords` traces, as well
as some `editable: true` modifications such as `name`
and `colorbar.title`. Defaults to `layout.uirevision`.
Note that other user-driven trace attribute changes are
controlled by `layout` attributes: `trace.visible` is
controlled by `layout.legend.uirevision`,
`selectedpoints` is controlled by
`layout.selectionrevision`, and `colorbar.(x|y)`
(accessible with `config: {editable: true}`) is
controlled by `layout.editrevision`. Trace changes are
tracked by `uid`, which only falls back on trace index
if no `uid` is provided. So if your app can add/remove
traces before the end of the `data` array, such that
the same trace has a different index, you can still
preserve user-driven changes if you give each trace a
`uid` that stays with it as it moves.
valueformat
Sets the value formatting rule using d3 formatting
mini-languages which are very similar to those in
Python. For numbers, see:
https://github.com/d3/d3-format/tree/v1.4.5#d3-format.
valuesuffix
Adds a unit to follow the value in the hover tooltip.
Add a space if a separation is necessary from the
value.
visible
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).
"""
def __init__(
self,
arg=None,
arrangement=None,
customdata=None,
customdatasrc=None,
domain=None,
hoverinfo=None,
hoverlabel=None,
ids=None,
idssrc=None,
legend=None,
legendgrouptitle=None,
legendrank=None,
legendwidth=None,
link=None,
meta=None,
metasrc=None,
name=None,
node=None,
orientation=None,
selectedpoints=None,
stream=None,
textfont=None,
uid=None,
uirevision=None,
valueformat=None,
valuesuffix=None,
visible=None,
**kwargs,
):
"""
Construct a new Sankey object
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.
Parameters
----------
arg
dict of properties compatible with this constructor or
an instance of :class:`plotly.graph_objs.Sankey`
arrangement
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.
customdata
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
customdatasrc
Sets the source reference on Chart Studio Cloud for
`customdata`.
domain
:class:`plotly.graph_objects.sankey.Domain` instance or
dict with compatible properties
hoverinfo
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. Note that this attribute is
superseded by `node.hoverinfo` and `node.hoverinfo` for
nodes and links respectively.
hoverlabel
:class:`plotly.graph_objects.sankey.Hoverlabel`
instance or dict with compatible properties
ids
Assigns id labels to each datum. These ids for object
constancy of data points during animation. Should be an
array of strings, not numbers or any other type.
idssrc
Sets the source reference on Chart Studio Cloud for
`ids`.
legend
Sets the reference to a legend to show this trace in.
References to these legends are "legend", "legend2",
"legend3", etc. Settings for these legends are set in
the layout, under `layout.legend`, `layout.legend2`,
etc.
legendgrouptitle
:class:`plotly.graph_objects.sankey.Legendgrouptitle`
instance or dict with compatible properties
legendrank
Sets the legend rank for this trace. Items and groups
with smaller ranks are presented on top/left side while
with "reversed" `legend.traceorder` they are on
bottom/right side. The default legendrank is 1000, so
that you can use ranks less than 1000 to place certain
items before all unranked items, and ranks greater than
1000 to go after all unranked items. When having
unranked or equal rank items shapes would be displayed
after traces i.e. according to their order in data and
layout.
legendwidth
Sets the width (in px or fraction) of the legend for
this trace.
link
The links of the Sankey plot.
meta
Assigns extra meta information associated with this
trace that can be used in various text attributes.
Attributes such as trace `name`, graph, axis and
colorbar `title.text`, annotation `text`
`rangeselector`, `updatemenues` and `sliders` `label`
text all support `meta`. To access the trace `meta`
values in an attribute in the same trace, simply use
`%{meta[i]}` where `i` is the index or key of the
`meta` item in question. To access trace `meta` in
layout attributes, use `%{data[n[.meta[i]}` where `i`
is the index or key of the `meta` and `n` is the trace
index.
metasrc
Sets the source reference on Chart Studio Cloud for
`meta`.
name
Sets the trace name. The trace name appears as the
legend item and on hover.
node
The nodes of the Sankey plot.
orientation
Sets the orientation of the Sankey diagram.
selectedpoints
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.
stream
:class:`plotly.graph_objects.sankey.Stream` instance or
dict with compatible properties
textfont
Sets the font for node labels
uid
Assign an id to this trace, Use this to provide object
constancy between traces during animations and
transitions.
uirevision
Controls persistence of some user-driven changes to the
trace: `constraintrange` in `parcoords` traces, as well
as some `editable: true` modifications such as `name`
and `colorbar.title`. Defaults to `layout.uirevision`.
Note that other user-driven trace attribute changes are
controlled by `layout` attributes: `trace.visible` is
controlled by `layout.legend.uirevision`,
`selectedpoints` is controlled by
`layout.selectionrevision`, and `colorbar.(x|y)`
(accessible with `config: {editable: true}`) is
controlled by `layout.editrevision`. Trace changes are
tracked by `uid`, which only falls back on trace index
if no `uid` is provided. So if your app can add/remove
traces before the end of the `data` array, such that
the same trace has a different index, you can still
preserve user-driven changes if you give each trace a
`uid` that stays with it as it moves.
valueformat
Sets the value formatting rule using d3 formatting
mini-languages which are very similar to those in
Python. For numbers, see:
https://github.com/d3/d3-format/tree/v1.4.5#d3-format.
valuesuffix
Adds a unit to follow the value in the hover tooltip.
Add a space if a separation is necessary from the
value.
visible
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).
Returns
-------
Sankey
"""
super().__init__("sankey")
if "_parent" in kwargs:
self._parent = kwargs["_parent"]
return
if arg is None:
arg = {}
elif isinstance(arg, self.__class__):
arg = arg.to_plotly_json()
elif isinstance(arg, dict):
arg = _copy.copy(arg)
else:
raise ValueError("""\
The first argument to the plotly.graph_objs.Sankey
constructor must be a dict or
an instance of :class:`plotly.graph_objs.Sankey`""")
self._skip_invalid = kwargs.pop("skip_invalid", False)
self._validate = kwargs.pop("_validate", True)
self._set_property("arrangement", arg, arrangement)
self._set_property("customdata", arg, customdata)
self._set_property("customdatasrc", arg, customdatasrc)
self._set_property("domain", arg, domain)
self._set_property("hoverinfo", arg, hoverinfo)
self._set_property("hoverlabel", arg, hoverlabel)
self._set_property("ids", arg, ids)
self._set_property("idssrc", arg, idssrc)
self._set_property("legend", arg, legend)
self._set_property("legendgrouptitle", arg, legendgrouptitle)
self._set_property("legendrank", arg, legendrank)
self._set_property("legendwidth", arg, legendwidth)
self._set_property("link", arg, link)
self._set_property("meta", arg, meta)
self._set_property("metasrc", arg, metasrc)
self._set_property("name", arg, name)
self._set_property("node", arg, node)
self._set_property("orientation", arg, orientation)
self._set_property("selectedpoints", arg, selectedpoints)
self._set_property("stream", arg, stream)
self._set_property("textfont", arg, textfont)
self._set_property("uid", arg, uid)
self._set_property("uirevision", arg, uirevision)
self._set_property("valueformat", arg, valueformat)
self._set_property("valuesuffix", arg, valuesuffix)
self._set_property("visible", arg, visible)
self._props["type"] = "sankey"
arg.pop("type", None)
self._process_kwargs(**dict(arg, **kwargs))
self._skip_invalid = False

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,908 @@
# --- THIS FILE IS AUTO-GENERATED ---
# Modifications will be overwitten the next time code generation run.
from plotly.basedatatypes import BaseTraceType as _BaseTraceType
import copy as _copy
class Table(_BaseTraceType):
_parent_path_str = ""
_path_str = "table"
_valid_props = {
"cells",
"columnorder",
"columnordersrc",
"columnwidth",
"columnwidthsrc",
"customdata",
"customdatasrc",
"domain",
"header",
"hoverinfo",
"hoverinfosrc",
"hoverlabel",
"ids",
"idssrc",
"legend",
"legendgrouptitle",
"legendrank",
"legendwidth",
"meta",
"metasrc",
"name",
"stream",
"type",
"uid",
"uirevision",
"visible",
}
@property
def cells(self):
"""
The 'cells' property is an instance of Cells
that may be specified as:
- An instance of :class:`plotly.graph_objs.table.Cells`
- A dict of string/value properties that will be passed
to the Cells constructor
Returns
-------
plotly.graph_objs.table.Cells
"""
return self["cells"]
@cells.setter
def cells(self, val):
self["cells"] = val
@property
def columnorder(self):
"""
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.
The 'columnorder' property is an array that may be specified as a tuple,
list, numpy array, or pandas Series
Returns
-------
numpy.ndarray
"""
return self["columnorder"]
@columnorder.setter
def columnorder(self, val):
self["columnorder"] = val
@property
def columnordersrc(self):
"""
Sets the source reference on Chart Studio Cloud for
`columnorder`.
The 'columnordersrc' property must be specified as a string or
as a plotly.grid_objs.Column object
Returns
-------
str
"""
return self["columnordersrc"]
@columnordersrc.setter
def columnordersrc(self, val):
self["columnordersrc"] = val
@property
def columnwidth(self):
"""
The width of columns expressed as a ratio. Columns fill the
available width in proportion of their specified column widths.
The 'columnwidth' property is a number and may be specified as:
- An int or float
- A tuple, list, or one-dimensional numpy array of the above
Returns
-------
int|float|numpy.ndarray
"""
return self["columnwidth"]
@columnwidth.setter
def columnwidth(self, val):
self["columnwidth"] = val
@property
def columnwidthsrc(self):
"""
Sets the source reference on Chart Studio Cloud for
`columnwidth`.
The 'columnwidthsrc' property must be specified as a string or
as a plotly.grid_objs.Column object
Returns
-------
str
"""
return self["columnwidthsrc"]
@columnwidthsrc.setter
def columnwidthsrc(self, val):
self["columnwidthsrc"] = val
@property
def customdata(self):
"""
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
The 'customdata' property is an array that may be specified as a tuple,
list, numpy array, or pandas Series
Returns
-------
numpy.ndarray
"""
return self["customdata"]
@customdata.setter
def customdata(self, val):
self["customdata"] = val
@property
def customdatasrc(self):
"""
Sets the source reference on Chart Studio Cloud for
`customdata`.
The 'customdatasrc' property must be specified as a string or
as a plotly.grid_objs.Column object
Returns
-------
str
"""
return self["customdatasrc"]
@customdatasrc.setter
def customdatasrc(self, val):
self["customdatasrc"] = val
@property
def domain(self):
"""
The 'domain' property is an instance of Domain
that may be specified as:
- An instance of :class:`plotly.graph_objs.table.Domain`
- A dict of string/value properties that will be passed
to the Domain constructor
Returns
-------
plotly.graph_objs.table.Domain
"""
return self["domain"]
@domain.setter
def domain(self, val):
self["domain"] = val
@property
def header(self):
"""
The 'header' property is an instance of Header
that may be specified as:
- An instance of :class:`plotly.graph_objs.table.Header`
- A dict of string/value properties that will be passed
to the Header constructor
Returns
-------
plotly.graph_objs.table.Header
"""
return self["header"]
@header.setter
def header(self, val):
self["header"] = val
@property
def hoverinfo(self):
"""
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.
The 'hoverinfo' property is a flaglist and may be specified
as a string containing:
- Any combination of ['x', 'y', 'z', 'text', 'name'] joined with '+' characters
(e.g. 'x+y')
OR exactly one of ['all', 'none', 'skip'] (e.g. 'skip')
- A list or array of the above
Returns
-------
Any|numpy.ndarray
"""
return self["hoverinfo"]
@hoverinfo.setter
def hoverinfo(self, val):
self["hoverinfo"] = val
@property
def hoverinfosrc(self):
"""
Sets the source reference on Chart Studio Cloud for
`hoverinfo`.
The 'hoverinfosrc' property must be specified as a string or
as a plotly.grid_objs.Column object
Returns
-------
str
"""
return self["hoverinfosrc"]
@hoverinfosrc.setter
def hoverinfosrc(self, val):
self["hoverinfosrc"] = val
@property
def hoverlabel(self):
"""
The 'hoverlabel' property is an instance of Hoverlabel
that may be specified as:
- An instance of :class:`plotly.graph_objs.table.Hoverlabel`
- A dict of string/value properties that will be passed
to the Hoverlabel constructor
Returns
-------
plotly.graph_objs.table.Hoverlabel
"""
return self["hoverlabel"]
@hoverlabel.setter
def hoverlabel(self, val):
self["hoverlabel"] = val
@property
def ids(self):
"""
Assigns id labels to each datum. These ids for object constancy
of data points during animation. Should be an array of strings,
not numbers or any other type.
The 'ids' property is an array that may be specified as a tuple,
list, numpy array, or pandas Series
Returns
-------
numpy.ndarray
"""
return self["ids"]
@ids.setter
def ids(self, val):
self["ids"] = val
@property
def idssrc(self):
"""
Sets the source reference on Chart Studio Cloud for `ids`.
The 'idssrc' property must be specified as a string or
as a plotly.grid_objs.Column object
Returns
-------
str
"""
return self["idssrc"]
@idssrc.setter
def idssrc(self, val):
self["idssrc"] = val
@property
def legend(self):
"""
Sets the reference to a legend to show this trace in.
References to these legends are "legend", "legend2", "legend3",
etc. Settings for these legends are set in the layout, under
`layout.legend`, `layout.legend2`, etc.
The 'legend' property is an identifier of a particular
subplot, of type 'legend', that may be specified as the string 'legend'
optionally followed by an integer >= 1
(e.g. 'legend', 'legend1', 'legend2', 'legend3', etc.)
Returns
-------
str
"""
return self["legend"]
@legend.setter
def legend(self, val):
self["legend"] = val
@property
def legendgrouptitle(self):
"""
The 'legendgrouptitle' property is an instance of Legendgrouptitle
that may be specified as:
- An instance of :class:`plotly.graph_objs.table.Legendgrouptitle`
- A dict of string/value properties that will be passed
to the Legendgrouptitle constructor
Returns
-------
plotly.graph_objs.table.Legendgrouptitle
"""
return self["legendgrouptitle"]
@legendgrouptitle.setter
def legendgrouptitle(self, val):
self["legendgrouptitle"] = val
@property
def legendrank(self):
"""
Sets the legend rank for this trace. Items and groups with
smaller ranks are presented on top/left side while with
"reversed" `legend.traceorder` they are on bottom/right side.
The default legendrank is 1000, so that you can use ranks less
than 1000 to place certain items before all unranked items, and
ranks greater than 1000 to go after all unranked items. When
having unranked or equal rank items shapes would be displayed
after traces i.e. according to their order in data and layout.
The 'legendrank' property is a number and may be specified as:
- An int or float
Returns
-------
int|float
"""
return self["legendrank"]
@legendrank.setter
def legendrank(self, val):
self["legendrank"] = val
@property
def legendwidth(self):
"""
Sets the width (in px or fraction) of the legend for this
trace.
The 'legendwidth' property is a number and may be specified as:
- An int or float in the interval [0, inf]
Returns
-------
int|float
"""
return self["legendwidth"]
@legendwidth.setter
def legendwidth(self, val):
self["legendwidth"] = val
@property
def meta(self):
"""
Assigns extra meta information associated with this trace that
can be used in various text attributes. Attributes such as
trace `name`, graph, axis and colorbar `title.text`, annotation
`text` `rangeselector`, `updatemenues` and `sliders` `label`
text all support `meta`. To access the trace `meta` values in
an attribute in the same trace, simply use `%{meta[i]}` where
`i` is the index or key of the `meta` item in question. To
access trace `meta` in layout attributes, use
`%{data[n[.meta[i]}` where `i` is the index or key of the
`meta` and `n` is the trace index.
The 'meta' property accepts values of any type
Returns
-------
Any|numpy.ndarray
"""
return self["meta"]
@meta.setter
def meta(self, val):
self["meta"] = val
@property
def metasrc(self):
"""
Sets the source reference on Chart Studio Cloud for `meta`.
The 'metasrc' property must be specified as a string or
as a plotly.grid_objs.Column object
Returns
-------
str
"""
return self["metasrc"]
@metasrc.setter
def metasrc(self, val):
self["metasrc"] = val
@property
def name(self):
"""
Sets the trace name. The trace name appears as the legend item
and on hover.
The 'name' property is a string and must be specified as:
- A string
- A number that will be converted to a string
Returns
-------
str
"""
return self["name"]
@name.setter
def name(self, val):
self["name"] = val
@property
def stream(self):
"""
The 'stream' property is an instance of Stream
that may be specified as:
- An instance of :class:`plotly.graph_objs.table.Stream`
- A dict of string/value properties that will be passed
to the Stream constructor
Returns
-------
plotly.graph_objs.table.Stream
"""
return self["stream"]
@stream.setter
def stream(self, val):
self["stream"] = val
@property
def uid(self):
"""
Assign an id to this trace, Use this to provide object
constancy between traces during animations and transitions.
The 'uid' property is a string and must be specified as:
- A string
- A number that will be converted to a string
Returns
-------
str
"""
return self["uid"]
@uid.setter
def uid(self, val):
self["uid"] = val
@property
def uirevision(self):
"""
Controls persistence of some user-driven changes to the trace:
`constraintrange` in `parcoords` traces, as well as some
`editable: true` modifications such as `name` and
`colorbar.title`. Defaults to `layout.uirevision`. Note that
other user-driven trace attribute changes are controlled by
`layout` attributes: `trace.visible` is controlled by
`layout.legend.uirevision`, `selectedpoints` is controlled by
`layout.selectionrevision`, and `colorbar.(x|y)` (accessible
with `config: {editable: true}`) is controlled by
`layout.editrevision`. Trace changes are tracked by `uid`,
which only falls back on trace index if no `uid` is provided.
So if your app can add/remove traces before the end of the
`data` array, such that the same trace has a different index,
you can still preserve user-driven changes if you give each
trace a `uid` that stays with it as it moves.
The 'uirevision' property accepts values of any type
Returns
-------
Any
"""
return self["uirevision"]
@uirevision.setter
def uirevision(self, val):
self["uirevision"] = val
@property
def visible(self):
"""
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).
The 'visible' property is an enumeration that may be specified as:
- One of the following enumeration values:
[True, False, 'legendonly']
Returns
-------
Any
"""
return self["visible"]
@visible.setter
def visible(self, val):
self["visible"] = val
@property
def type(self):
return self._props["type"]
@property
def _prop_descriptions(self):
return """\
cells
:class:`plotly.graph_objects.table.Cells` instance or
dict with compatible properties
columnorder
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.
columnordersrc
Sets the source reference on Chart Studio Cloud for
`columnorder`.
columnwidth
The width of columns expressed as a ratio. Columns fill
the available width in proportion of their specified
column widths.
columnwidthsrc
Sets the source reference on Chart Studio Cloud for
`columnwidth`.
customdata
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
customdatasrc
Sets the source reference on Chart Studio Cloud for
`customdata`.
domain
:class:`plotly.graph_objects.table.Domain` instance or
dict with compatible properties
header
:class:`plotly.graph_objects.table.Header` instance or
dict with compatible properties
hoverinfo
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.
hoverinfosrc
Sets the source reference on Chart Studio Cloud for
`hoverinfo`.
hoverlabel
:class:`plotly.graph_objects.table.Hoverlabel` instance
or dict with compatible properties
ids
Assigns id labels to each datum. These ids for object
constancy of data points during animation. Should be an
array of strings, not numbers or any other type.
idssrc
Sets the source reference on Chart Studio Cloud for
`ids`.
legend
Sets the reference to a legend to show this trace in.
References to these legends are "legend", "legend2",
"legend3", etc. Settings for these legends are set in
the layout, under `layout.legend`, `layout.legend2`,
etc.
legendgrouptitle
:class:`plotly.graph_objects.table.Legendgrouptitle`
instance or dict with compatible properties
legendrank
Sets the legend rank for this trace. Items and groups
with smaller ranks are presented on top/left side while
with "reversed" `legend.traceorder` they are on
bottom/right side. The default legendrank is 1000, so
that you can use ranks less than 1000 to place certain
items before all unranked items, and ranks greater than
1000 to go after all unranked items. When having
unranked or equal rank items shapes would be displayed
after traces i.e. according to their order in data and
layout.
legendwidth
Sets the width (in px or fraction) of the legend for
this trace.
meta
Assigns extra meta information associated with this
trace that can be used in various text attributes.
Attributes such as trace `name`, graph, axis and
colorbar `title.text`, annotation `text`
`rangeselector`, `updatemenues` and `sliders` `label`
text all support `meta`. To access the trace `meta`
values in an attribute in the same trace, simply use
`%{meta[i]}` where `i` is the index or key of the
`meta` item in question. To access trace `meta` in
layout attributes, use `%{data[n[.meta[i]}` where `i`
is the index or key of the `meta` and `n` is the trace
index.
metasrc
Sets the source reference on Chart Studio Cloud for
`meta`.
name
Sets the trace name. The trace name appears as the
legend item and on hover.
stream
:class:`plotly.graph_objects.table.Stream` instance or
dict with compatible properties
uid
Assign an id to this trace, Use this to provide object
constancy between traces during animations and
transitions.
uirevision
Controls persistence of some user-driven changes to the
trace: `constraintrange` in `parcoords` traces, as well
as some `editable: true` modifications such as `name`
and `colorbar.title`. Defaults to `layout.uirevision`.
Note that other user-driven trace attribute changes are
controlled by `layout` attributes: `trace.visible` is
controlled by `layout.legend.uirevision`,
`selectedpoints` is controlled by
`layout.selectionrevision`, and `colorbar.(x|y)`
(accessible with `config: {editable: true}`) is
controlled by `layout.editrevision`. Trace changes are
tracked by `uid`, which only falls back on trace index
if no `uid` is provided. So if your app can add/remove
traces before the end of the `data` array, such that
the same trace has a different index, you can still
preserve user-driven changes if you give each trace a
`uid` that stays with it as it moves.
visible
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).
"""
def __init__(
self,
arg=None,
cells=None,
columnorder=None,
columnordersrc=None,
columnwidth=None,
columnwidthsrc=None,
customdata=None,
customdatasrc=None,
domain=None,
header=None,
hoverinfo=None,
hoverinfosrc=None,
hoverlabel=None,
ids=None,
idssrc=None,
legend=None,
legendgrouptitle=None,
legendrank=None,
legendwidth=None,
meta=None,
metasrc=None,
name=None,
stream=None,
uid=None,
uirevision=None,
visible=None,
**kwargs,
):
"""
Construct a new Table object
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.
Parameters
----------
arg
dict of properties compatible with this constructor or
an instance of :class:`plotly.graph_objs.Table`
cells
:class:`plotly.graph_objects.table.Cells` instance or
dict with compatible properties
columnorder
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.
columnordersrc
Sets the source reference on Chart Studio Cloud for
`columnorder`.
columnwidth
The width of columns expressed as a ratio. Columns fill
the available width in proportion of their specified
column widths.
columnwidthsrc
Sets the source reference on Chart Studio Cloud for
`columnwidth`.
customdata
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
customdatasrc
Sets the source reference on Chart Studio Cloud for
`customdata`.
domain
:class:`plotly.graph_objects.table.Domain` instance or
dict with compatible properties
header
:class:`plotly.graph_objects.table.Header` instance or
dict with compatible properties
hoverinfo
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.
hoverinfosrc
Sets the source reference on Chart Studio Cloud for
`hoverinfo`.
hoverlabel
:class:`plotly.graph_objects.table.Hoverlabel` instance
or dict with compatible properties
ids
Assigns id labels to each datum. These ids for object
constancy of data points during animation. Should be an
array of strings, not numbers or any other type.
idssrc
Sets the source reference on Chart Studio Cloud for
`ids`.
legend
Sets the reference to a legend to show this trace in.
References to these legends are "legend", "legend2",
"legend3", etc. Settings for these legends are set in
the layout, under `layout.legend`, `layout.legend2`,
etc.
legendgrouptitle
:class:`plotly.graph_objects.table.Legendgrouptitle`
instance or dict with compatible properties
legendrank
Sets the legend rank for this trace. Items and groups
with smaller ranks are presented on top/left side while
with "reversed" `legend.traceorder` they are on
bottom/right side. The default legendrank is 1000, so
that you can use ranks less than 1000 to place certain
items before all unranked items, and ranks greater than
1000 to go after all unranked items. When having
unranked or equal rank items shapes would be displayed
after traces i.e. according to their order in data and
layout.
legendwidth
Sets the width (in px or fraction) of the legend for
this trace.
meta
Assigns extra meta information associated with this
trace that can be used in various text attributes.
Attributes such as trace `name`, graph, axis and
colorbar `title.text`, annotation `text`
`rangeselector`, `updatemenues` and `sliders` `label`
text all support `meta`. To access the trace `meta`
values in an attribute in the same trace, simply use
`%{meta[i]}` where `i` is the index or key of the
`meta` item in question. To access trace `meta` in
layout attributes, use `%{data[n[.meta[i]}` where `i`
is the index or key of the `meta` and `n` is the trace
index.
metasrc
Sets the source reference on Chart Studio Cloud for
`meta`.
name
Sets the trace name. The trace name appears as the
legend item and on hover.
stream
:class:`plotly.graph_objects.table.Stream` instance or
dict with compatible properties
uid
Assign an id to this trace, Use this to provide object
constancy between traces during animations and
transitions.
uirevision
Controls persistence of some user-driven changes to the
trace: `constraintrange` in `parcoords` traces, as well
as some `editable: true` modifications such as `name`
and `colorbar.title`. Defaults to `layout.uirevision`.
Note that other user-driven trace attribute changes are
controlled by `layout` attributes: `trace.visible` is
controlled by `layout.legend.uirevision`,
`selectedpoints` is controlled by
`layout.selectionrevision`, and `colorbar.(x|y)`
(accessible with `config: {editable: true}`) is
controlled by `layout.editrevision`. Trace changes are
tracked by `uid`, which only falls back on trace index
if no `uid` is provided. So if your app can add/remove
traces before the end of the `data` array, such that
the same trace has a different index, you can still
preserve user-driven changes if you give each trace a
`uid` that stays with it as it moves.
visible
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).
Returns
-------
Table
"""
super().__init__("table")
if "_parent" in kwargs:
self._parent = kwargs["_parent"]
return
if arg is None:
arg = {}
elif isinstance(arg, self.__class__):
arg = arg.to_plotly_json()
elif isinstance(arg, dict):
arg = _copy.copy(arg)
else:
raise ValueError("""\
The first argument to the plotly.graph_objs.Table
constructor must be a dict or
an instance of :class:`plotly.graph_objs.Table`""")
self._skip_invalid = kwargs.pop("skip_invalid", False)
self._validate = kwargs.pop("_validate", True)
self._set_property("cells", arg, cells)
self._set_property("columnorder", arg, columnorder)
self._set_property("columnordersrc", arg, columnordersrc)
self._set_property("columnwidth", arg, columnwidth)
self._set_property("columnwidthsrc", arg, columnwidthsrc)
self._set_property("customdata", arg, customdata)
self._set_property("customdatasrc", arg, customdatasrc)
self._set_property("domain", arg, domain)
self._set_property("header", arg, header)
self._set_property("hoverinfo", arg, hoverinfo)
self._set_property("hoverinfosrc", arg, hoverinfosrc)
self._set_property("hoverlabel", arg, hoverlabel)
self._set_property("ids", arg, ids)
self._set_property("idssrc", arg, idssrc)
self._set_property("legend", arg, legend)
self._set_property("legendgrouptitle", arg, legendgrouptitle)
self._set_property("legendrank", arg, legendrank)
self._set_property("legendwidth", arg, legendwidth)
self._set_property("meta", arg, meta)
self._set_property("metasrc", arg, metasrc)
self._set_property("name", arg, name)
self._set_property("stream", arg, stream)
self._set_property("uid", arg, uid)
self._set_property("uirevision", arg, uirevision)
self._set_property("visible", arg, visible)
self._props["type"] = "table"
arg.pop("type", None)
self._process_kwargs(**dict(arg, **kwargs))
self._skip_invalid = False

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,40 @@
import sys
from typing import TYPE_CHECKING
if TYPE_CHECKING:
from ._error_x import ErrorX
from ._error_y import ErrorY
from ._hoverlabel import Hoverlabel
from ._insidetextfont import Insidetextfont
from ._legendgrouptitle import Legendgrouptitle
from ._marker import Marker
from ._outsidetextfont import Outsidetextfont
from ._selected import Selected
from ._stream import Stream
from ._textfont import Textfont
from ._unselected import Unselected
from . import hoverlabel
from . import legendgrouptitle
from . import marker
from . import selected
from . import unselected
else:
from _plotly_utils.importers import relative_import
__all__, __getattr__, __dir__ = relative_import(
__name__,
[".hoverlabel", ".legendgrouptitle", ".marker", ".selected", ".unselected"],
[
"._error_x.ErrorX",
"._error_y.ErrorY",
"._hoverlabel.Hoverlabel",
"._insidetextfont.Insidetextfont",
"._legendgrouptitle.Legendgrouptitle",
"._marker.Marker",
"._outsidetextfont.Outsidetextfont",
"._selected.Selected",
"._stream.Stream",
"._textfont.Textfont",
"._unselected.Unselected",
],
)

View File

@ -0,0 +1,502 @@
# --- THIS FILE IS AUTO-GENERATED ---
# Modifications will be overwitten the next time code generation run.
from plotly.basedatatypes import BaseTraceHierarchyType as _BaseTraceHierarchyType
import copy as _copy
class ErrorX(_BaseTraceHierarchyType):
_parent_path_str = "bar"
_path_str = "bar.error_x"
_valid_props = {
"array",
"arrayminus",
"arrayminussrc",
"arraysrc",
"color",
"copy_ystyle",
"symmetric",
"thickness",
"traceref",
"tracerefminus",
"type",
"value",
"valueminus",
"visible",
"width",
}
@property
def array(self):
"""
Sets the data corresponding the length of each error bar.
Values are plotted relative to the underlying data.
The 'array' property is an array that may be specified as a tuple,
list, numpy array, or pandas Series
Returns
-------
numpy.ndarray
"""
return self["array"]
@array.setter
def array(self, val):
self["array"] = val
@property
def arrayminus(self):
"""
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.
The 'arrayminus' property is an array that may be specified as a tuple,
list, numpy array, or pandas Series
Returns
-------
numpy.ndarray
"""
return self["arrayminus"]
@arrayminus.setter
def arrayminus(self, val):
self["arrayminus"] = val
@property
def arrayminussrc(self):
"""
Sets the source reference on Chart Studio Cloud for
`arrayminus`.
The 'arrayminussrc' property must be specified as a string or
as a plotly.grid_objs.Column object
Returns
-------
str
"""
return self["arrayminussrc"]
@arrayminussrc.setter
def arrayminussrc(self, val):
self["arrayminussrc"] = val
@property
def arraysrc(self):
"""
Sets the source reference on Chart Studio Cloud for `array`.
The 'arraysrc' property must be specified as a string or
as a plotly.grid_objs.Column object
Returns
-------
str
"""
return self["arraysrc"]
@arraysrc.setter
def arraysrc(self, val):
self["arraysrc"] = val
@property
def color(self):
"""
Sets the stroke color of the error bars.
The 'color' 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: see https://plotly.com/python/css-colors/ for a list
Returns
-------
str
"""
return self["color"]
@color.setter
def color(self, val):
self["color"] = val
@property
def copy_ystyle(self):
"""
The 'copy_ystyle' property must be specified as a bool
(either True, or False)
Returns
-------
bool
"""
return self["copy_ystyle"]
@copy_ystyle.setter
def copy_ystyle(self, val):
self["copy_ystyle"] = val
@property
def symmetric(self):
"""
Determines whether or not the error bars have the same length
in both direction (top/bottom for vertical bars, left/right for
horizontal bars.
The 'symmetric' property must be specified as a bool
(either True, or False)
Returns
-------
bool
"""
return self["symmetric"]
@symmetric.setter
def symmetric(self, val):
self["symmetric"] = val
@property
def thickness(self):
"""
Sets the thickness (in px) of the error bars.
The 'thickness' property is a number and may be specified as:
- An int or float in the interval [0, inf]
Returns
-------
int|float
"""
return self["thickness"]
@thickness.setter
def thickness(self, val):
self["thickness"] = val
@property
def traceref(self):
"""
The 'traceref' property is a integer and may be specified as:
- An int (or float that will be cast to an int)
in the interval [0, 9223372036854775807]
Returns
-------
int
"""
return self["traceref"]
@traceref.setter
def traceref(self, val):
self["traceref"] = val
@property
def tracerefminus(self):
"""
The 'tracerefminus' property is a integer and may be specified as:
- An int (or float that will be cast to an int)
in the interval [0, 9223372036854775807]
Returns
-------
int
"""
return self["tracerefminus"]
@tracerefminus.setter
def tracerefminus(self, val):
self["tracerefminus"] = val
@property
def type(self):
"""
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 square of
the underlying data. If "data", the bar lengths are set with
data set `array`.
The 'type' property is an enumeration that may be specified as:
- One of the following enumeration values:
['percent', 'constant', 'sqrt', 'data']
Returns
-------
Any
"""
return self["type"]
@type.setter
def type(self, val):
self["type"] = val
@property
def value(self):
"""
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.
The 'value' property is a number and may be specified as:
- An int or float in the interval [0, inf]
Returns
-------
int|float
"""
return self["value"]
@value.setter
def value(self, val):
self["value"] = val
@property
def valueminus(self):
"""
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
The 'valueminus' property is a number and may be specified as:
- An int or float in the interval [0, inf]
Returns
-------
int|float
"""
return self["valueminus"]
@valueminus.setter
def valueminus(self, val):
self["valueminus"] = val
@property
def visible(self):
"""
Determines whether or not this set of error bars is visible.
The 'visible' property must be specified as a bool
(either True, or False)
Returns
-------
bool
"""
return self["visible"]
@visible.setter
def visible(self, val):
self["visible"] = val
@property
def width(self):
"""
Sets the width (in px) of the cross-bar at both ends of the
error bars.
The 'width' property is a number and may be specified as:
- An int or float in the interval [0, inf]
Returns
-------
int|float
"""
return self["width"]
@width.setter
def width(self, val):
self["width"] = val
@property
def _prop_descriptions(self):
return """\
array
Sets the data corresponding the length of each error
bar. Values are plotted relative to the underlying
data.
arrayminus
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.
arrayminussrc
Sets the source reference on Chart Studio Cloud for
`arrayminus`.
arraysrc
Sets the source reference on Chart Studio Cloud for
`array`.
color
Sets the stroke color of the error bars.
copy_ystyle
symmetric
Determines whether or not the error bars have the same
length in both direction (top/bottom for vertical bars,
left/right for horizontal bars.
thickness
Sets the thickness (in px) of the error bars.
traceref
tracerefminus
type
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 square of the underlying
data. If "data", the bar lengths are set with data set
`array`.
value
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
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
visible
Determines whether or not this set of error bars is
visible.
width
Sets the width (in px) of the cross-bar at both ends of
the error bars.
"""
def __init__(
self,
arg=None,
array=None,
arrayminus=None,
arrayminussrc=None,
arraysrc=None,
color=None,
copy_ystyle=None,
symmetric=None,
thickness=None,
traceref=None,
tracerefminus=None,
type=None,
value=None,
valueminus=None,
visible=None,
width=None,
**kwargs,
):
"""
Construct a new ErrorX object
Parameters
----------
arg
dict of properties compatible with this constructor or
an instance of :class:`plotly.graph_objs.bar.ErrorX`
array
Sets the data corresponding the length of each error
bar. Values are plotted relative to the underlying
data.
arrayminus
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.
arrayminussrc
Sets the source reference on Chart Studio Cloud for
`arrayminus`.
arraysrc
Sets the source reference on Chart Studio Cloud for
`array`.
color
Sets the stroke color of the error bars.
copy_ystyle
symmetric
Determines whether or not the error bars have the same
length in both direction (top/bottom for vertical bars,
left/right for horizontal bars.
thickness
Sets the thickness (in px) of the error bars.
traceref
tracerefminus
type
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 square of the underlying
data. If "data", the bar lengths are set with data set
`array`.
value
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
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
visible
Determines whether or not this set of error bars is
visible.
width
Sets the width (in px) of the cross-bar at both ends of
the error bars.
Returns
-------
ErrorX
"""
super().__init__("error_x")
if "_parent" in kwargs:
self._parent = kwargs["_parent"]
return
if arg is None:
arg = {}
elif isinstance(arg, self.__class__):
arg = arg.to_plotly_json()
elif isinstance(arg, dict):
arg = _copy.copy(arg)
else:
raise ValueError("""\
The first argument to the plotly.graph_objs.bar.ErrorX
constructor must be a dict or
an instance of :class:`plotly.graph_objs.bar.ErrorX`""")
self._skip_invalid = kwargs.pop("skip_invalid", False)
self._validate = kwargs.pop("_validate", True)
self._set_property("array", arg, array)
self._set_property("arrayminus", arg, arrayminus)
self._set_property("arrayminussrc", arg, arrayminussrc)
self._set_property("arraysrc", arg, arraysrc)
self._set_property("color", arg, color)
self._set_property("copy_ystyle", arg, copy_ystyle)
self._set_property("symmetric", arg, symmetric)
self._set_property("thickness", arg, thickness)
self._set_property("traceref", arg, traceref)
self._set_property("tracerefminus", arg, tracerefminus)
self._set_property("type", arg, type)
self._set_property("value", arg, value)
self._set_property("valueminus", arg, valueminus)
self._set_property("visible", arg, visible)
self._set_property("width", arg, width)
self._process_kwargs(**dict(arg, **kwargs))
self._skip_invalid = False

Some files were not shown because too many files have changed in this diff Show More