|
# Copyright 2015 Bloomberg Finance L.P.
|
|
#
|
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
# you may not use this file except in compliance with the License.
|
|
# You may obtain a copy of the License at
|
|
#
|
|
# http://www.apache.org/licenses/LICENSE-2.0
|
|
#
|
|
# Unless required by applicable law or agreed to in writing, software
|
|
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
# See the License for the specific language governing permissions and
|
|
# limitations under the License.
|
|
|
|
r"""
|
|
|
|
======
|
|
Figure
|
|
======
|
|
|
|
.. currentmodule:: bqplot.figure
|
|
|
|
.. autosummary::
|
|
:toctree: _generate/
|
|
|
|
Figure
|
|
"""
|
|
|
|
from traitlets import (
|
|
Unicode, Instance, List, Dict, Enum, Float, Int, TraitError, default,
|
|
validate
|
|
)
|
|
from ipywidgets import DOMWidget, register, widget_serialization
|
|
from ipywidgets.widgets.widget_layout import LayoutTraitType
|
|
|
|
from .scales import Scale, LinearScale
|
|
from .interacts import Interaction
|
|
from .marks import Mark
|
|
from .axes import Axis
|
|
from ._version import __frontend_version__
|
|
|
|
|
|
@register
|
|
class Figure(DOMWidget):
|
|
|
|
"""Main canvas for drawing a chart.
|
|
|
|
The Figure object holds the list of Marks and Axes. It also holds an
|
|
optional Interaction object that is responsible for figure-level mouse
|
|
interactions, the "interaction layer".
|
|
|
|
Besides, the Figure object has two reference scales, for positioning items
|
|
in an absolute fashion in the figure canvas.
|
|
|
|
Attributes
|
|
----------
|
|
title: string (default: '')
|
|
title of the figure
|
|
axes: List of Axes (default: [])
|
|
list containing the instances of the axes for the figure
|
|
marks: List of Marks (default: [])
|
|
list containing the marks which are to be appended to the figure
|
|
interaction: Interaction or None (default: None)
|
|
optional interaction layer for the figure
|
|
scale_x: Scale
|
|
Scale representing the x values of the figure
|
|
scale_y: Scale
|
|
Scale representing the y values of the figure
|
|
padding_x: Float (default: 0.0)
|
|
Padding to be applied in the horizontal direction of the figure
|
|
around the data points, proportion of the horizontal length
|
|
padding_y: Float (default: 0.025)
|
|
Padding to be applied in the vertical direction of the figure
|
|
around the data points, proportion of the vertical length
|
|
legend_location: {'top-right', 'top', 'top-left', 'left',
|
|
'bottom-left', 'bottom', 'bottom-right', 'right'}
|
|
location of the legend relative to the center of the figure
|
|
background_style: Dict (default: {})
|
|
CSS style to be applied to the background of the figure
|
|
legend_style: Dict (default: {})
|
|
CSS style to be applied to the SVG legend e.g, {'fill': 'white'}
|
|
legend_text: Dict (default: {})
|
|
CSS style to be applied to the legend text e.g., {'font-size': 20}
|
|
title_style: Dict (default: {})
|
|
CSS style to be applied to the title of the figure
|
|
animation_duration: nonnegative int (default: 0)
|
|
Duration of transition on change of data attributes, in milliseconds.
|
|
pixel_ratio:
|
|
Pixel ratio of the WebGL canvas (2 on retina screens). Set to 1 for better performance,
|
|
but less crisp edges. If set to None it will use the browser's window.devicePixelRatio.
|
|
|
|
Layout Attributes
|
|
|
|
fig_margin: dict (default: {top=60, bottom=60, left=60, right=60})
|
|
Dictionary containing the top, bottom, left and right margins. The user
|
|
is responsible for making sure that the width and height are greater
|
|
than the sum of the margins.
|
|
min_aspect_ratio: float
|
|
minimum width / height ratio of the figure
|
|
max_aspect_ratio: float
|
|
maximum width / height ratio of the figure
|
|
|
|
Methods
|
|
-------
|
|
|
|
save_png:
|
|
Saves the figure as a PNG file
|
|
save_svg:
|
|
Saves the figure as an SVG file
|
|
|
|
Note
|
|
----
|
|
|
|
The aspect ratios stand for width / height ratios.
|
|
|
|
- If the available space is within bounds in terms of min and max aspect
|
|
ratio, we use the entire available space.
|
|
- If the available space is too oblong horizontally, we use the client
|
|
height and the width that corresponds max_aspect_ratio (maximize width
|
|
under the constraints).
|
|
- If the available space is too oblong vertically, we use the client width
|
|
and the height that corresponds to min_aspect_ratio (maximize height
|
|
under the constraint).
|
|
This corresponds to maximizing the area under the constraints.
|
|
|
|
Default min and max aspect ratio are both equal to 16 / 9.
|
|
"""
|
|
title = Unicode().tag(sync=True, display_name='Title')
|
|
axes = List(Instance(Axis)).tag(sync=True, **widget_serialization)
|
|
marks = List(Instance(Mark)).tag(sync=True, **widget_serialization)
|
|
interaction = Instance(Interaction, default_value=None,
|
|
allow_none=True).tag(sync=True,
|
|
**widget_serialization)
|
|
scale_x = Instance(Scale).tag(sync=True, **widget_serialization)
|
|
scale_y = Instance(Scale).tag(sync=True, **widget_serialization)
|
|
title_style = Dict(trait=Unicode()).tag(sync=True)
|
|
background_style = Dict().tag(sync=True)
|
|
legend_style = Dict().tag(sync=True)
|
|
legend_text = Dict().tag(sync=True)
|
|
theme = Enum(['classic', 'gg'], default_value='classic').tag(sync=True)
|
|
|
|
min_aspect_ratio = Float(0.01).tag(sync=True)
|
|
max_aspect_ratio = Float(100).tag(sync=True)
|
|
pixel_ratio = Float(None, allow_none=True).tag(sync=True)
|
|
|
|
fig_margin = Dict(dict(top=60, bottom=60, left=60, right=60))\
|
|
.tag(sync=True)
|
|
padding_x = Float(0.0, min=0.0, max=1.0).tag(sync=True)
|
|
padding_y = Float(0.025, min=0.0, max=1.0).tag(sync=True)
|
|
legend_location = Enum(['top-right', 'top', 'top-left', 'left',
|
|
'bottom-left', 'bottom', 'bottom-right', 'right'],
|
|
default_value='top-right')\
|
|
.tag(sync=True, display_name='Legend position')
|
|
animation_duration = Int().tag(sync=True,
|
|
display_name='Animation duration')
|
|
|
|
@default('scale_x')
|
|
def _default_scale_x(self):
|
|
return LinearScale(min=0, max=1, allow_padding=False)
|
|
|
|
@default('scale_y')
|
|
def _default_scale_y(self):
|
|
return LinearScale(min=0, max=1, allow_padding=False)
|
|
|
|
def save_png(self, filename='bqplot.png', scale=None):
|
|
'''
|
|
Saves the Figure as a PNG file
|
|
|
|
Parameters
|
|
----------
|
|
filename: str (default: 'bqplot.png')
|
|
name of the saved file
|
|
scale: float (default: None)
|
|
Scale up the png resolution when scale > 1, when not given base this on the screen pixel ratio.
|
|
'''
|
|
self.send({'type': 'save_png', 'filename': filename, 'scale': scale})
|
|
|
|
def save_svg(self, filename='bqplot.svg'):
|
|
'''
|
|
Saves the Figure as an SVG file
|
|
|
|
Parameters
|
|
----------
|
|
filename: str (default: 'bqplot.svg')
|
|
name of the saved file
|
|
'''
|
|
self.send({"type": "save_svg", "filename": filename})
|
|
|
|
@validate('min_aspect_ratio', 'max_aspect_ratio')
|
|
def _validate_aspect_ratio(self, proposal):
|
|
value = proposal['value']
|
|
if proposal['trait'].name == 'min_aspect_ratio' and \
|
|
value > self.max_aspect_ratio:
|
|
raise TraitError('setting min_aspect_ratio > max_aspect_ratio')
|
|
if proposal['trait'].name == 'max_aspect_ratio' and \
|
|
value < self.min_aspect_ratio:
|
|
raise TraitError('setting max_aspect_ratio < min_aspect_ratio')
|
|
return value
|
|
|
|
_view_name = Unicode('Figure').tag(sync=True)
|
|
_model_name = Unicode('FigureModel').tag(sync=True)
|
|
_view_module = Unicode('bqplot').tag(sync=True)
|
|
_model_module = Unicode('bqplot').tag(sync=True)
|
|
_view_module_version = Unicode(__frontend_version__).tag(sync=True)
|
|
_model_module_version = Unicode(__frontend_version__).tag(sync=True)
|