lets-plot 4.5.3a1__cp313-cp313-win_amd64.whl → 4.6.0__cp313-cp313-win_amd64.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of lets-plot might be problematic. Click here for more details.
- lets_plot/_kbridge.py +99 -1
- lets_plot/_version.py +1 -1
- lets_plot/bistro/_plot2d_common.py +7 -0
- lets_plot/bistro/im.py +38 -7
- lets_plot/bistro/joint.py +3 -3
- lets_plot/bistro/residual.py +3 -3
- lets_plot/package_data/lets-plot.min.js +2 -2
- lets_plot/plot/__init__.py +2 -0
- lets_plot/plot/core.py +1 -1
- lets_plot/plot/geom.py +379 -81
- lets_plot/plot/ggbunch_.py +96 -0
- lets_plot/plot/gggrid_.py +3 -18
- lets_plot/plot/plot.py +7 -0
- lets_plot/plot/pos.py +10 -3
- lets_plot/plot/scale.py +45 -20
- lets_plot/plot/subplots.py +1 -1
- lets_plot/plot/subplots_util.py +24 -0
- lets_plot/plot/theme_.py +105 -17
- {lets_plot-4.5.3a1.dist-info → lets_plot-4.6.0.dist-info}/METADATA +34 -32
- {lets_plot-4.5.3a1.dist-info → lets_plot-4.6.0.dist-info}/RECORD +24 -22
- {lets_plot-4.5.3a1.dist-info → lets_plot-4.6.0.dist-info}/WHEEL +1 -1
- lets_plot_kotlin_bridge.cp313-win_amd64.pyd +0 -0
- {lets_plot-4.5.3a1.dist-info → lets_plot-4.6.0.dist-info}/LICENSE +0 -0
- {lets_plot-4.5.3a1.dist-info → lets_plot-4.6.0.dist-info}/top_level.txt +0 -0
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
# Copyright (c) 2025. JetBrains s.r.o.
|
|
2
|
+
# Use of this source code is governed by the MIT license that can be found in the LICENSE file.
|
|
3
|
+
|
|
4
|
+
from numbers import Number
|
|
5
|
+
from typing import List, Tuple
|
|
6
|
+
|
|
7
|
+
from ._global_theme import _get_global_theme
|
|
8
|
+
from .subplots import SupPlotsLayoutSpec
|
|
9
|
+
from .subplots import SupPlotsSpec
|
|
10
|
+
from .subplots_util import _strip_theme_if_global
|
|
11
|
+
|
|
12
|
+
__all__ = ['ggbunch']
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
def ggbunch(plots: List,
|
|
16
|
+
regions: List[Tuple[float, float, float, float, float, float]]
|
|
17
|
+
) -> SupPlotsSpec:
|
|
18
|
+
"""
|
|
19
|
+
Combine several plots into a single figure with custom layout.
|
|
20
|
+
|
|
21
|
+
Parameters
|
|
22
|
+
----------
|
|
23
|
+
plots : List
|
|
24
|
+
A list where each element is one of:
|
|
25
|
+
|
|
26
|
+
- a plot specification
|
|
27
|
+
- a subplots specification
|
|
28
|
+
- None
|
|
29
|
+
|
|
30
|
+
regions : List[Tuple]
|
|
31
|
+
Layout parameters for each plot. Each region is specified as
|
|
32
|
+
(x, y, width, height, dx, dy) where:
|
|
33
|
+
|
|
34
|
+
- x, y: Position of the plot's top-left corner in relative coordinates ([0,0] is top-left corner, [1,1] is bottom-right corner of the container).
|
|
35
|
+
- width, height: Size of the plot relative to container dimensions (1 equal to the full container width/height).
|
|
36
|
+
- dx, dy: Pixel offsets to move the region (defaults to 0).
|
|
37
|
+
|
|
38
|
+
Returns
|
|
39
|
+
-------
|
|
40
|
+
`SupPlotsSpec`
|
|
41
|
+
A specification describing the combined figure with all plots and their layout.
|
|
42
|
+
|
|
43
|
+
Examples
|
|
44
|
+
--------
|
|
45
|
+
.. jupyter-execute::
|
|
46
|
+
:linenos:
|
|
47
|
+
:emphasize-lines: 10-14
|
|
48
|
+
|
|
49
|
+
import numpy as np
|
|
50
|
+
from lets_plot import *
|
|
51
|
+
LetsPlot.setup_html()
|
|
52
|
+
np.random.seed(42)
|
|
53
|
+
data = {'x': np.random.gamma(2.0, size=100)}
|
|
54
|
+
p1 = ggplot(data, aes(x='x')) + \\
|
|
55
|
+
geom_histogram(aes(color='x', fill='x'))
|
|
56
|
+
p2 = ggplot(data, aes(x='x')) + \\
|
|
57
|
+
geom_density() + theme_bw() + theme(axis='blank', panel_grid='blank')
|
|
58
|
+
ggbunch(
|
|
59
|
+
[p1, p2],
|
|
60
|
+
[(0, 0, 1, 1),
|
|
61
|
+
(0.5, 0.1, 0.3, 0.3)]
|
|
62
|
+
) + ggsize(400, 300)
|
|
63
|
+
|
|
64
|
+
"""
|
|
65
|
+
|
|
66
|
+
if not len(plots):
|
|
67
|
+
raise ValueError("Supplots list is empty.")
|
|
68
|
+
|
|
69
|
+
# Validate provided regions
|
|
70
|
+
for i, region in enumerate(regions):
|
|
71
|
+
if len(region) not in (4, 6):
|
|
72
|
+
raise ValueError(f"Region {i} must have 4 or 6 values, got {len(region)}")
|
|
73
|
+
if not all(isinstance(x, Number) for x in region):
|
|
74
|
+
raise ValueError(f"Region {i} contains non-numeric values: {region}")
|
|
75
|
+
|
|
76
|
+
# Validate size is positive
|
|
77
|
+
if any(x <= 0 for x in region[2:4]):
|
|
78
|
+
raise ValueError(f"Region {i} sizes must be positive: {region}")
|
|
79
|
+
|
|
80
|
+
# Convert regions tuples to lists
|
|
81
|
+
regions_list = [list(r) for r in regions]
|
|
82
|
+
layout = SupPlotsLayoutSpec(
|
|
83
|
+
name="free",
|
|
84
|
+
regions=regions_list
|
|
85
|
+
)
|
|
86
|
+
|
|
87
|
+
figures = [_strip_theme_if_global(fig) for fig in plots]
|
|
88
|
+
|
|
89
|
+
figure_spec = SupPlotsSpec(figures=figures, layout=layout)
|
|
90
|
+
|
|
91
|
+
# Apply global theme if defined
|
|
92
|
+
global_theme_options = _get_global_theme()
|
|
93
|
+
if global_theme_options is not None:
|
|
94
|
+
figure_spec += global_theme_options
|
|
95
|
+
|
|
96
|
+
return figure_spec
|
lets_plot/plot/gggrid_.py
CHANGED
|
@@ -3,10 +3,10 @@
|
|
|
3
3
|
# Use of this source code is governed by the MIT license that can be found in the LICENSE file.
|
|
4
4
|
#
|
|
5
5
|
|
|
6
|
-
from lets_plot.plot.core import PlotSpec
|
|
7
6
|
from ._global_theme import _get_global_theme
|
|
8
7
|
from .subplots import SupPlotsLayoutSpec
|
|
9
8
|
from .subplots import SupPlotsSpec
|
|
9
|
+
from .subplots_util import _strip_theme_if_global
|
|
10
10
|
|
|
11
11
|
__all__ = ['gggrid']
|
|
12
12
|
|
|
@@ -114,27 +114,12 @@ def gggrid(plots: list, ncol: int = None, *,
|
|
|
114
114
|
align=align
|
|
115
115
|
)
|
|
116
116
|
|
|
117
|
-
# Global Theme
|
|
118
|
-
global_theme_options = _get_global_theme()
|
|
119
|
-
|
|
120
|
-
def _strip_theme_if_global(fig):
|
|
121
|
-
# Strip global theme options from plots in grid (see issue: #966).
|
|
122
|
-
if global_theme_options is not None and fig is not None and 'theme' in fig.props() and fig.props()[
|
|
123
|
-
'theme'] == global_theme_options.props():
|
|
124
|
-
if isinstance(fig, PlotSpec):
|
|
125
|
-
fig = PlotSpec.duplicate(fig)
|
|
126
|
-
fig.props().pop('theme')
|
|
127
|
-
return fig
|
|
128
|
-
elif isinstance(fig, SupPlotsSpec):
|
|
129
|
-
fig = SupPlotsSpec.duplicate(fig)
|
|
130
|
-
fig.props().pop('theme')
|
|
131
|
-
return fig
|
|
132
|
-
return fig
|
|
133
|
-
|
|
134
117
|
figures = [_strip_theme_if_global(fig) for fig in plots]
|
|
135
118
|
|
|
136
119
|
figure_spec = SupPlotsSpec(figures=figures, layout=layout)
|
|
137
120
|
|
|
121
|
+
# Apply global theme if defined
|
|
122
|
+
global_theme_options = _get_global_theme()
|
|
138
123
|
if global_theme_options is not None:
|
|
139
124
|
figure_spec += global_theme_options
|
|
140
125
|
|
lets_plot/plot/plot.py
CHANGED
|
@@ -142,6 +142,9 @@ def ggsize(width, height):
|
|
|
142
142
|
|
|
143
143
|
class GGBunch(FeatureSpec):
|
|
144
144
|
"""
|
|
145
|
+
Class `GGBunch` is deprecated and will be removed in future releases.
|
|
146
|
+
Please, use function `ggbunch()` to combine several plots into a single figure with custom layout.
|
|
147
|
+
|
|
145
148
|
Collection of plots created by ggplot function.
|
|
146
149
|
Use method `add_plot()` to add plot to 'bunch'.
|
|
147
150
|
Each plot can have arbitrary location and size.
|
|
@@ -176,6 +179,10 @@ class GGBunch(FeatureSpec):
|
|
|
176
179
|
"""
|
|
177
180
|
super().__init__('ggbunch', None)
|
|
178
181
|
self.items = []
|
|
182
|
+
print("\n(!) WARN: class GGBunch is deprecated and will be removed in future releases.\n\n"
|
|
183
|
+
" Please, use function ggbunch() to combine several plots into\n"
|
|
184
|
+
" a single figure with custom layout.\n")
|
|
185
|
+
|
|
179
186
|
|
|
180
187
|
def add_plot(self, plot_spec: PlotSpec, x, y, width=None, height=None):
|
|
181
188
|
"""
|
lets_plot/plot/pos.py
CHANGED
|
@@ -146,7 +146,7 @@ def position_jitter(width=None, height=None, seed=None):
|
|
|
146
146
|
return _pos('jitter', width=width, height=height, seed=seed)
|
|
147
147
|
|
|
148
148
|
|
|
149
|
-
def position_nudge(x=None, y=None):
|
|
149
|
+
def position_nudge(x=None, y=None, unit=None):
|
|
150
150
|
"""
|
|
151
151
|
Adjust position by nudging a given offset.
|
|
152
152
|
|
|
@@ -156,6 +156,13 @@ def position_nudge(x=None, y=None):
|
|
|
156
156
|
Nudging width.
|
|
157
157
|
y : float
|
|
158
158
|
Nudging height.
|
|
159
|
+
unit : {'identity', 'size', 'px'}, default='identity'
|
|
160
|
+
Units for x and y nudging.
|
|
161
|
+
Possible values:
|
|
162
|
+
|
|
163
|
+
- 'identity': a unit of 1 corresponds to a difference of 1 in data space;
|
|
164
|
+
- 'size': a unit of 1 corresponds to the diameter of a point with `size=1`;
|
|
165
|
+
- 'px': the unit is measured in screen pixels.
|
|
159
166
|
|
|
160
167
|
Returns
|
|
161
168
|
-------
|
|
@@ -182,10 +189,10 @@ def position_nudge(x=None, y=None):
|
|
|
182
189
|
t = np.random.choice(list('abcdefghijk'), size=n)
|
|
183
190
|
ggplot({'x': x, 'y': y, 't': t}, aes('x', 'y')) + \\
|
|
184
191
|
geom_point(size=5, shape=21, color='black', fill='red') + \\
|
|
185
|
-
geom_text(aes(label='t'), position=position_nudge(y=.05))
|
|
192
|
+
geom_text(aes(label='t'), position=position_nudge(y=.05, unit='identity'))
|
|
186
193
|
|
|
187
194
|
"""
|
|
188
|
-
return _pos('nudge', x=x, y=y)
|
|
195
|
+
return _pos('nudge', x=x, y=y, unit=unit)
|
|
189
196
|
|
|
190
197
|
|
|
191
198
|
def position_jitterdodge(dodge_width=None, jitter_width=None, jitter_height=None, seed=None):
|
lets_plot/plot/scale.py
CHANGED
|
@@ -90,10 +90,8 @@ def scale_shape(solid=True, name=None, breaks=None, labels=None, lablim=None, li
|
|
|
90
90
|
labels=labels,
|
|
91
91
|
lablim=lablim,
|
|
92
92
|
limits=limits,
|
|
93
|
-
expand=None,
|
|
94
93
|
na_value=na_value,
|
|
95
94
|
guide=guide,
|
|
96
|
-
trans=None,
|
|
97
95
|
format=format,
|
|
98
96
|
#
|
|
99
97
|
solid=solid)
|
|
@@ -192,10 +190,8 @@ def scale_manual(aesthetic, values, *,
|
|
|
192
190
|
labels=labels,
|
|
193
191
|
lablim=lablim,
|
|
194
192
|
limits=limits,
|
|
195
|
-
expand=None,
|
|
196
193
|
na_value=na_value,
|
|
197
194
|
guide=guide,
|
|
198
|
-
trans=None,
|
|
199
195
|
format=format,
|
|
200
196
|
#
|
|
201
197
|
values=values)
|
|
@@ -668,7 +664,7 @@ def _is_color_scale(aesthetic):
|
|
|
668
664
|
|
|
669
665
|
def scale_continuous(aesthetic, *,
|
|
670
666
|
name=None, breaks=None, labels=None, lablim=None,
|
|
671
|
-
limits=None, na_value=None, guide=None, trans=None, format=None,
|
|
667
|
+
limits=None, expand=None, na_value=None, guide=None, trans=None, format=None,
|
|
672
668
|
scale_mapper_kind=None,
|
|
673
669
|
**kwargs):
|
|
674
670
|
"""
|
|
@@ -691,6 +687,10 @@ def scale_continuous(aesthetic, *,
|
|
|
691
687
|
The maximum label length (in characters) before trimming is applied.
|
|
692
688
|
limits : list
|
|
693
689
|
A numeric vector of length two providing limits of the scale.
|
|
690
|
+
expand : list
|
|
691
|
+
A numeric vector of length two giving multiplicative and additive expansion constants.
|
|
692
|
+
The vector size == 1 => only multiplicative expand (and additive expand by default).
|
|
693
|
+
Defaults: multiplicative = 0.05, additive = 0.
|
|
694
694
|
na_value
|
|
695
695
|
Missing values will be replaced with this value.
|
|
696
696
|
guide
|
|
@@ -737,6 +737,22 @@ def scale_continuous(aesthetic, *,
|
|
|
737
737
|
coord_cartesian() + \\
|
|
738
738
|
ggsize(600, 200)
|
|
739
739
|
|
|
740
|
+
|
|
|
741
|
+
|
|
742
|
+
.. jupyter-execute::
|
|
743
|
+
:linenos:
|
|
744
|
+
:emphasize-lines: 9
|
|
745
|
+
|
|
746
|
+
from lets_plot import *
|
|
747
|
+
LetsPlot.setup_html()
|
|
748
|
+
data = {
|
|
749
|
+
'x': [0, 1, 2],
|
|
750
|
+
'y': [0, 1, 2]
|
|
751
|
+
}
|
|
752
|
+
ggplot(data) + \\
|
|
753
|
+
geom_point(aes(x='x', y='y'), size=15) + \\
|
|
754
|
+
scale_continuous(['x','y'], expand=[0, 0]) # no expansion - points right on the edges
|
|
755
|
+
|
|
740
756
|
"""
|
|
741
757
|
if _is_color_scale(aesthetic):
|
|
742
758
|
scale_mapper_kind = 'color_gradient' if scale_mapper_kind is None else scale_mapper_kind
|
|
@@ -747,7 +763,7 @@ def scale_continuous(aesthetic, *,
|
|
|
747
763
|
labels=labels,
|
|
748
764
|
lablim=lablim,
|
|
749
765
|
limits=limits,
|
|
750
|
-
expand=
|
|
766
|
+
expand=expand,
|
|
751
767
|
na_value=na_value,
|
|
752
768
|
guide=guide,
|
|
753
769
|
trans=trans,
|
|
@@ -992,7 +1008,6 @@ def scale_gradient(aesthetic, *,
|
|
|
992
1008
|
labels=labels,
|
|
993
1009
|
lablim=lablim,
|
|
994
1010
|
limits=limits,
|
|
995
|
-
expand=None,
|
|
996
1011
|
na_value=na_value,
|
|
997
1012
|
guide=guide,
|
|
998
1013
|
trans=trans,
|
|
@@ -1242,7 +1257,6 @@ def scale_gradient2(aesthetic, *,
|
|
|
1242
1257
|
labels=labels,
|
|
1243
1258
|
lablim=lablim,
|
|
1244
1259
|
limits=limits,
|
|
1245
|
-
expand=None,
|
|
1246
1260
|
na_value=na_value,
|
|
1247
1261
|
guide=guide,
|
|
1248
1262
|
trans=trans,
|
|
@@ -1498,7 +1512,6 @@ def scale_gradientn(aesthetic, *,
|
|
|
1498
1512
|
labels=labels,
|
|
1499
1513
|
lablim=lablim,
|
|
1500
1514
|
limits=limits,
|
|
1501
|
-
expand=None,
|
|
1502
1515
|
na_value=na_value,
|
|
1503
1516
|
guide=guide,
|
|
1504
1517
|
trans=trans,
|
|
@@ -1746,7 +1759,6 @@ def scale_hue(aesthetic, *,
|
|
|
1746
1759
|
labels=labels,
|
|
1747
1760
|
lablim=lablim,
|
|
1748
1761
|
limits=limits,
|
|
1749
|
-
expand=None,
|
|
1750
1762
|
na_value=na_value,
|
|
1751
1763
|
guide=guide,
|
|
1752
1764
|
trans=trans,
|
|
@@ -1933,7 +1945,8 @@ def scale_color_hue(h=None, c=None, l=None, h_start=None, direction=None, name=N
|
|
|
1933
1945
|
|
|
1934
1946
|
def scale_discrete(aesthetic, *,
|
|
1935
1947
|
direction=None,
|
|
1936
|
-
name=None, breaks=None, labels=None, lablim=None,
|
|
1948
|
+
name=None, breaks=None, labels=None, lablim=None,
|
|
1949
|
+
limits=None, expand=None, na_value=None, guide=None, format=None,
|
|
1937
1950
|
scale_mapper_kind=None,
|
|
1938
1951
|
**kwargs):
|
|
1939
1952
|
"""
|
|
@@ -1960,6 +1973,10 @@ def scale_discrete(aesthetic, *,
|
|
|
1960
1973
|
limits : list
|
|
1961
1974
|
A vector specifying the data range for the scale
|
|
1962
1975
|
and the default order of their display in guides.
|
|
1976
|
+
expand : list
|
|
1977
|
+
A numeric vector of length two giving multiplicative and additive expansion constants.
|
|
1978
|
+
The vector size == 1 => only multiplicative expand (and additive expand by default).
|
|
1979
|
+
Defaults: multiplicative = 0.05, additive = 0.
|
|
1963
1980
|
na_value
|
|
1964
1981
|
Missing values will be replaced with this value.
|
|
1965
1982
|
guide
|
|
@@ -2006,6 +2023,22 @@ def scale_discrete(aesthetic, *,
|
|
|
2006
2023
|
ggplot() + geom_point(aes(x, y, color=z, fill=z), shape=21, size=4) + \\
|
|
2007
2024
|
scale_discrete(aesthetic=['color', 'fill'], guide='none')
|
|
2008
2025
|
|
|
2026
|
+
|
|
|
2027
|
+
|
|
2028
|
+
.. jupyter-execute::
|
|
2029
|
+
:linenos:
|
|
2030
|
+
:emphasize-lines: 9
|
|
2031
|
+
|
|
2032
|
+
from lets_plot import *
|
|
2033
|
+
LetsPlot.setup_html()
|
|
2034
|
+
data = {
|
|
2035
|
+
'x': [0, 1, 2],
|
|
2036
|
+
'y': [0, 1, 2]
|
|
2037
|
+
}
|
|
2038
|
+
ggplot(data) + \\
|
|
2039
|
+
geom_point(aes(x='x', y='y'), size=15) + \\
|
|
2040
|
+
scale_discrete(['x','y'], expand=[0, 0]) # no expansion - points right on the edges
|
|
2041
|
+
|
|
2009
2042
|
"""
|
|
2010
2043
|
return _scale(aesthetic=aesthetic,
|
|
2011
2044
|
name=name,
|
|
@@ -2013,7 +2046,7 @@ def scale_discrete(aesthetic, *,
|
|
|
2013
2046
|
labels=labels,
|
|
2014
2047
|
lablim=lablim,
|
|
2015
2048
|
limits=limits,
|
|
2016
|
-
expand=
|
|
2049
|
+
expand=expand,
|
|
2017
2050
|
na_value=na_value,
|
|
2018
2051
|
guide=guide,
|
|
2019
2052
|
format=format,
|
|
@@ -2266,7 +2299,6 @@ def scale_grey(aesthetic, *,
|
|
|
2266
2299
|
labels=labels,
|
|
2267
2300
|
lablim=lablim,
|
|
2268
2301
|
limits=limits,
|
|
2269
|
-
expand=None,
|
|
2270
2302
|
na_value=na_value,
|
|
2271
2303
|
guide=guide,
|
|
2272
2304
|
trans=trans,
|
|
@@ -2550,7 +2582,6 @@ def scale_brewer(aesthetic, *,
|
|
|
2550
2582
|
labels=labels,
|
|
2551
2583
|
lablim=lablim,
|
|
2552
2584
|
limits=limits,
|
|
2553
|
-
expand=None,
|
|
2554
2585
|
na_value=na_value,
|
|
2555
2586
|
guide=guide,
|
|
2556
2587
|
trans=trans,
|
|
@@ -2858,7 +2889,6 @@ def scale_viridis(aesthetic, *,
|
|
|
2858
2889
|
labels=labels,
|
|
2859
2890
|
lablim=lablim,
|
|
2860
2891
|
limits=limits,
|
|
2861
|
-
expand=None,
|
|
2862
2892
|
na_value=na_value,
|
|
2863
2893
|
guide=guide,
|
|
2864
2894
|
trans=trans,
|
|
@@ -3146,7 +3176,6 @@ def scale_alpha(range=None, name=None, breaks=None, labels=None, lablim=None, li
|
|
|
3146
3176
|
labels=labels,
|
|
3147
3177
|
lablim=lablim,
|
|
3148
3178
|
limits=limits,
|
|
3149
|
-
expand=None,
|
|
3150
3179
|
na_value=na_value,
|
|
3151
3180
|
guide=guide,
|
|
3152
3181
|
trans=trans,
|
|
@@ -3221,7 +3250,6 @@ def scale_size(range=None, name=None, breaks=None, labels=None, lablim=None, lim
|
|
|
3221
3250
|
labels=labels,
|
|
3222
3251
|
lablim=lablim,
|
|
3223
3252
|
limits=limits,
|
|
3224
|
-
expand=None,
|
|
3225
3253
|
na_value=na_value,
|
|
3226
3254
|
guide=guide,
|
|
3227
3255
|
trans=trans,
|
|
@@ -3300,7 +3328,6 @@ def scale_size_area(max_size=None, name=None, breaks=None, labels=None, lablim=N
|
|
|
3300
3328
|
labels=labels,
|
|
3301
3329
|
lablim=lablim,
|
|
3302
3330
|
limits=limits,
|
|
3303
|
-
expand=None,
|
|
3304
3331
|
na_value=na_value,
|
|
3305
3332
|
guide=guide,
|
|
3306
3333
|
trans=trans,
|
|
@@ -3375,7 +3402,6 @@ def scale_linewidth(range=None, name=None, breaks=None, labels=None, lablim=None
|
|
|
3375
3402
|
labels=labels,
|
|
3376
3403
|
lablim=lablim,
|
|
3377
3404
|
limits=limits,
|
|
3378
|
-
expand=None,
|
|
3379
3405
|
na_value=na_value,
|
|
3380
3406
|
guide=guide,
|
|
3381
3407
|
trans=trans,
|
|
@@ -3449,7 +3475,6 @@ def scale_stroke(range=None, name=None, breaks=None, labels=None, lablim=None, l
|
|
|
3449
3475
|
labels=labels,
|
|
3450
3476
|
lablim=lablim,
|
|
3451
3477
|
limits=limits,
|
|
3452
|
-
expand=None,
|
|
3453
3478
|
na_value=na_value,
|
|
3454
3479
|
guide=guide,
|
|
3455
3480
|
trans=trans,
|
lets_plot/plot/subplots.py
CHANGED
|
@@ -67,7 +67,7 @@ class SupPlotsSpec(FeatureSpec):
|
|
|
67
67
|
supplots = supplots.__add__(spec)
|
|
68
68
|
return supplots
|
|
69
69
|
|
|
70
|
-
elif isinstance(other, FeatureSpec) and other.kind in ["ggsize", "theme", "ggtoolbar"]:
|
|
70
|
+
elif isinstance(other, FeatureSpec) and other.kind in ["ggsize", "theme", "ggtitle", "caption", "ggtoolbar"]:
|
|
71
71
|
|
|
72
72
|
supplots = SupPlotsSpec.duplicate(self)
|
|
73
73
|
# ToDo: duplication!
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
# Copyright (c) 2025. JetBrains s.r.o.
|
|
2
|
+
# Use of this source code is governed by the MIT license that can be found in the LICENSE file.
|
|
3
|
+
|
|
4
|
+
from lets_plot.plot.core import PlotSpec
|
|
5
|
+
from ._global_theme import _get_global_theme
|
|
6
|
+
from .subplots import SupPlotsSpec
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
def _strip_theme_if_global(fig):
|
|
10
|
+
# Strip this global theme if defined
|
|
11
|
+
global_theme_options = _get_global_theme()
|
|
12
|
+
|
|
13
|
+
# Strip global theme options from plots in grid (see issue: #966).
|
|
14
|
+
if global_theme_options is not None and fig is not None and 'theme' in fig.props() and fig.props()[
|
|
15
|
+
'theme'] == global_theme_options.props():
|
|
16
|
+
if isinstance(fig, PlotSpec):
|
|
17
|
+
fig = PlotSpec.duplicate(fig)
|
|
18
|
+
fig.props().pop('theme')
|
|
19
|
+
return fig
|
|
20
|
+
elif isinstance(fig, SupPlotsSpec):
|
|
21
|
+
fig = SupPlotsSpec.duplicate(fig)
|
|
22
|
+
fig.props().pop('theme')
|
|
23
|
+
return fig
|
|
24
|
+
return fig
|
lets_plot/plot/theme_.py
CHANGED
|
@@ -10,6 +10,7 @@ __all__ = [
|
|
|
10
10
|
"element_line",
|
|
11
11
|
'element_rect',
|
|
12
12
|
'element_text',
|
|
13
|
+
'element_markdown',
|
|
13
14
|
'margin',
|
|
14
15
|
'element_geom',
|
|
15
16
|
]
|
|
@@ -48,12 +49,11 @@ def theme(*,
|
|
|
48
49
|
legend_key_size=None, legend_key_width=None, legend_key_height=None,
|
|
49
50
|
legend_key_spacing=None, legend_key_spacing_x=None, legend_key_spacing_y=None,
|
|
50
51
|
legend_box=None, legend_box_just=None, legend_box_spacing=None,
|
|
51
|
-
|
|
52
|
+
legend_ticks=None, legend_ticks_length=None,
|
|
52
53
|
|
|
53
54
|
panel_background=None,
|
|
54
55
|
panel_border=None,
|
|
55
56
|
panel_border_ontop=None,
|
|
56
|
-
# ToDo: other panel options...
|
|
57
57
|
|
|
58
58
|
panel_grid=None,
|
|
59
59
|
panel_grid_ontop=None,
|
|
@@ -99,20 +99,20 @@ def theme(*,
|
|
|
99
99
|
Parameters
|
|
100
100
|
----------
|
|
101
101
|
exponent_format : {'e', 'pow', 'pow_full'} or tuple, default='e'
|
|
102
|
-
|
|
102
|
+
Controls the appearance of numbers formatted with 'e' or 'g' types.
|
|
103
103
|
|
|
104
|
-
-
|
|
105
|
-
|
|
106
|
-
|
|
104
|
+
Value is either a string - style, or a tuple: (style, lower_exp_bound, upper_exp_bound)
|
|
105
|
+
where style can be:
|
|
106
|
+
|
|
107
|
+
- 'e' : e-notation (e.g., 1e+6)
|
|
108
|
+
- 'pow' : superscript powers of 10 in shortened form (e.g., 10^6)
|
|
109
|
+
- 'pow_full' : superscript powers of 10 with coefficient (e.g., 1×10^6)
|
|
107
110
|
|
|
108
|
-
|
|
111
|
+
For 'g' type formatting, scientific notation is applied when the number's exponent
|
|
112
|
+
is less than or equal to the lower_exp_bound (-7 by default) or greater than or equal
|
|
113
|
+
to the upper_exp_bound (6 by default, but can be affected by `precision` in format specifier).
|
|
109
114
|
|
|
110
|
-
|
|
111
|
-
- the second element is minimum exponent value from which to use scientific notation (default is -7);
|
|
112
|
-
- the third element is maximum exponent value from which to use scientific notation (default is taken from `precision` of the current formatting, see `Formatting <https://lets-plot.org/python/pages/formats.html>`__).
|
|
113
|
-
|
|
114
|
-
Minimum and maximum exponent values are only taken into account when "g" format is used,
|
|
115
|
-
see `Formatting <https://lets-plot.org/python/pages/formats.html>`__.
|
|
115
|
+
See `Formatting <https://lets-plot.org/python/pages/formats.html>`__.
|
|
116
116
|
|
|
117
117
|
Superscript is not supported when exporting to PNG/PDF.
|
|
118
118
|
line : str or dict
|
|
@@ -221,6 +221,14 @@ def theme(*,
|
|
|
221
221
|
Justification of each legend within the overall bounding box, when there are multiple legends.
|
|
222
222
|
legend_box_spacing : float
|
|
223
223
|
Spacing between plotting area and legend box.
|
|
224
|
+
legend_ticks : str or dict
|
|
225
|
+
Tick marks in colorbars.
|
|
226
|
+
Set 'blank' or result of `element_blank()` to draw nothing and assign no space.
|
|
227
|
+
Set `element_line()` to specify all tick mark parameters.
|
|
228
|
+
`legend_ticks_*` DOES NOT inherit from `line`.
|
|
229
|
+
By default, the colorbar tick marks are drawn with the same color as the colorbar background.
|
|
230
|
+
legend_ticks_length : float
|
|
231
|
+
Length of colorbar tick marks in px.
|
|
224
232
|
panel_background : str or dict
|
|
225
233
|
Background of plotting area.
|
|
226
234
|
Set 'blank' or result of `element_blank()` to draw nothing.
|
|
@@ -576,7 +584,7 @@ def element_text(
|
|
|
576
584
|
face : str
|
|
577
585
|
Font face ("plain", "italic", "bold", "bold_italic").
|
|
578
586
|
size : int
|
|
579
|
-
Text size in
|
|
587
|
+
Text size in px.
|
|
580
588
|
angle : float
|
|
581
589
|
Angle to rotate the text (in degrees).
|
|
582
590
|
hjust : float
|
|
@@ -593,12 +601,11 @@ def element_text(
|
|
|
593
601
|
Can be used with values out of range, but behaviour is not specified.
|
|
594
602
|
margin : number or list of numbers
|
|
595
603
|
Margins around the text.
|
|
596
|
-
|
|
597
604
|
The margin may be specified using a number or a list of numbers:
|
|
605
|
+
|
|
598
606
|
- a number or list of one number - the same margin it applied to all four sides;
|
|
599
607
|
- a list of two numbers - the first margin applies to the top and bottom, the second - to the left and right;
|
|
600
|
-
- a list of three numbers -
|
|
601
|
-
the third - to the bottom;
|
|
608
|
+
- a list of three numbers - the first margin applies to the top, the second - to the right and left, the third - to the bottom;
|
|
602
609
|
- a list of four numbers - the margins are applied to the top, right, bottom and left in that order.
|
|
603
610
|
|
|
604
611
|
It is acceptable to use None for any side; in this case, the default side value for this element will be used.
|
|
@@ -628,6 +635,87 @@ def element_text(
|
|
|
628
635
|
return locals()
|
|
629
636
|
|
|
630
637
|
|
|
638
|
+
def element_markdown(
|
|
639
|
+
color=None,
|
|
640
|
+
family=None,
|
|
641
|
+
face=None,
|
|
642
|
+
size=None,
|
|
643
|
+
angle=None,
|
|
644
|
+
# ToDo: lineheight
|
|
645
|
+
hjust=None,
|
|
646
|
+
vjust=None,
|
|
647
|
+
margin=None,
|
|
648
|
+
blank=False,
|
|
649
|
+
) -> dict:
|
|
650
|
+
"""
|
|
651
|
+
Specify how non-data components of the plot are drawn.
|
|
652
|
+
This theme element draws texts with Markdown support.
|
|
653
|
+
|
|
654
|
+
Parameters
|
|
655
|
+
----------
|
|
656
|
+
color : str
|
|
657
|
+
Text color.
|
|
658
|
+
family : str
|
|
659
|
+
Font family.
|
|
660
|
+
face : {'plain', 'italic', 'bold', 'bold_italic'}, default='plain'
|
|
661
|
+
Font face.
|
|
662
|
+
size : int
|
|
663
|
+
Text size in px.
|
|
664
|
+
angle : float
|
|
665
|
+
Angle to rotate the text (in degrees).
|
|
666
|
+
hjust : float
|
|
667
|
+
Horizontal justification (in [0, 1]).
|
|
668
|
+
0 - left-justified;
|
|
669
|
+
1 - right-justified;
|
|
670
|
+
0.5 - center-justified.
|
|
671
|
+
Can be used with values out of range, but behaviour is not specified.
|
|
672
|
+
vjust : float
|
|
673
|
+
Vertical justification (in [0, 1]).
|
|
674
|
+
0 - bottom-justified;
|
|
675
|
+
1 - top-justified;
|
|
676
|
+
0.5 - middle-justified.
|
|
677
|
+
Can be used with values out of range, but behaviour is not specified.
|
|
678
|
+
margin : number or list of numbers
|
|
679
|
+
Margins around the text.
|
|
680
|
+
The margin may be specified using a number or a list of numbers:
|
|
681
|
+
|
|
682
|
+
- a number or list of one number - the same margin it applied to all four sides;
|
|
683
|
+
- a list of two numbers - the first margin applies to the top and bottom, the second - to the left and right;
|
|
684
|
+
- a list of three numbers - the first margin applies to the top, the second - to the right and left, the third - to the bottom;
|
|
685
|
+
- a list of four numbers - the margins are applied to the top, right, bottom and left in that order.
|
|
686
|
+
|
|
687
|
+
It is acceptable to use None for any side; in this case, the default side value for this element will be used.
|
|
688
|
+
blank : bool, default=False
|
|
689
|
+
If True - draws nothing, and assigns no space.
|
|
690
|
+
|
|
691
|
+
Returns
|
|
692
|
+
-------
|
|
693
|
+
`dict`
|
|
694
|
+
Theme element specification.
|
|
695
|
+
|
|
696
|
+
Examples
|
|
697
|
+
--------
|
|
698
|
+
.. jupyter-execute::
|
|
699
|
+
:linenos:
|
|
700
|
+
:emphasize-lines: 12
|
|
701
|
+
|
|
702
|
+
from lets_plot import *
|
|
703
|
+
LetsPlot.setup_html()
|
|
704
|
+
ggplot() + \\
|
|
705
|
+
geom_blank() + \\
|
|
706
|
+
labs(
|
|
707
|
+
title='*Hello*, **world**',
|
|
708
|
+
subtitle='_Simple plot_',
|
|
709
|
+
caption='*Powered by **lets-plot***',
|
|
710
|
+
x='Title **X**',
|
|
711
|
+
y='Title **Y**'
|
|
712
|
+
) + \\
|
|
713
|
+
theme(title=element_markdown())
|
|
714
|
+
|
|
715
|
+
"""
|
|
716
|
+
return {'markdown': True, **locals()}
|
|
717
|
+
|
|
718
|
+
|
|
631
719
|
def margin(t=None, r=None, b=None, l=None):
|
|
632
720
|
"""
|
|
633
721
|
Function `margin()` is deprecated.
|