in python-package/lets_plot/plot/core.py [0:0]
def __add__(self, other):
"""
Allow to add different specs to the ``PlotSpec`` object.
Examples
--------
.. jupyter-execute::
:linenos:
:emphasize-lines: 7
from lets_plot import *
LetsPlot.setup_html()
p = ggplot({'x': [0, 1, 2], 'y': [0, 1, 2]}, aes('x', 'y'))
l = layer('point', mapping=aes(color='x'))
s = scale_color_discrete()
t = theme(axis_title='blank')
p + l + s + t
"""
"""
plot + other_plot -> fail
plot + layer -> plot[layers] += layer
plot + geom -> plot[layers] += new layer(geom)
plot + scale -> plot[scales] += scale
plot + metainfo -> plot[metainfo_list] += metainfo
plot + [feature] -> plot + each feature in []
plot + theme + theme -> merged theme
"""
if isinstance(other, PlotSpec):
# pass and fail
pass
if isinstance(other, DummySpec):
# nothing
return self
elif isinstance(other, FeatureSpec):
plot = PlotSpec.duplicate(self)
if other.kind == 'layer':
if other.props()['geom'] == 'livemap':
plot.__is_livemap = True
from lets_plot.plot.util import is_geo_data_frame # local import to break circular reference
if is_geo_data_frame(other.props().get('data')) \
or is_geo_data_frame(other.props().get('map')):
if plot.__crs_initialized:
if plot.__crs != other.props().get('use_crs'):
raise ValueError(
'All geoms with map parameter should either use same `use_crs` or not use it at all')
else:
plot.__crs_initialized = True
plot.__crs = other.props().get('use_crs')
if plot.__is_livemap and plot.__crs is not None:
raise ValueError("livemap doesn't support `use_crs`")
other.before_append(plot.__is_livemap)
plot.__layers.append(other)
return plot
if other.kind == 'scale':
plot.__scales.append(other)
return plot
if other.kind == 'theme':
new_theme_options = {k: v for k, v in other.props().items() if v is not None}
if 'name' in new_theme_options:
# keep the previously specified flavor
if plot.props().get('theme', {}).get('flavor', None) is not None:
new_theme_options.update({'flavor': plot.props()['theme']['flavor']})
# pre-configured theme overrides existing theme altogether.
plot.props()['theme'] = new_theme_options
else:
# merge themes
old_theme_options = plot.props().get('theme', {})
plot.props()['theme'] = _theme_dicts_merge(old_theme_options, new_theme_options)
return plot
if other.kind == 'metainfo':
plot.__metainfo_list.append(other)
return plot
if isinstance(other, FeatureSpecArray):
for spec in other.elements():
plot = plot.__add__(spec)
return plot
if other.kind == 'guides':
existing_options = plot.props().get('guides', {})
plot.props()['guides'] = _merge_dicts_recursively(existing_options, other.as_dict())
return plot
if other.kind == 'mapping': # +aes(..)
# existing_spec = plot.props().get('mapping', aes())
# merged_mapping = {**existing_spec.as_dict(), **other.as_dict()}
# plot.props()['mapping'] = aes(**merged_mapping)
from lets_plot.plot.util import update_plot_aes_mapping # local import to break circular reference
update_plot_aes_mapping(plot, other)
return plot
# add feature to properties
plot.props()[other.kind] = other
return plot
return super().__add__(other)