lets-plot 4.6.2__cp312-cp312-macosx_10_15_x86_64.whl → 4.7.0rc1__cp312-cp312-macosx_10_15_x86_64.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/_global_settings.py +5 -0
- lets_plot/_kbridge.py +7 -0
- lets_plot/_type_utils.py +29 -6
- lets_plot/_version.py +1 -1
- lets_plot/bistro/im.py +2 -2
- lets_plot/bistro/waterfall.py +93 -12
- lets_plot/export/ggsave_.py +22 -14
- lets_plot/package_data/lets-plot.min.js +2 -1
- lets_plot/plot/annotation.py +75 -18
- lets_plot/plot/core.py +147 -30
- lets_plot/plot/geom.py +730 -89
- lets_plot/plot/geom_function_.py +1 -1
- lets_plot/plot/geom_imshow_.py +42 -51
- lets_plot/plot/pos.py +13 -44
- lets_plot/plot/scale_position.py +9 -3
- lets_plot/plot/series_meta.py +179 -105
- lets_plot/plot/stat.py +4 -4
- lets_plot/plot/subplots.py +4 -4
- lets_plot/plot/theme_.py +55 -52
- lets_plot/plot/util.py +15 -4
- {lets_plot-4.6.2.dist-info → lets_plot-4.7.0rc1.dist-info}/METADATA +5 -3
- {lets_plot-4.6.2.dist-info → lets_plot-4.7.0rc1.dist-info}/RECORD +30 -26
- {lets_plot-4.6.2.dist-info → lets_plot-4.7.0rc1.dist-info}/WHEEL +1 -1
- lets_plot-4.7.0rc1.dist-info/licenses/licenses/LICENSE.FreeType +166 -0
- lets_plot-4.7.0rc1.dist-info/licenses/licenses/LICENSE.ImageMagick +106 -0
- lets_plot-4.7.0rc1.dist-info/licenses/licenses/LICENSE.expat +21 -0
- lets_plot-4.7.0rc1.dist-info/licenses/licenses/LICENSE.fontconfig +200 -0
- lets_plot_kotlin_bridge.cpython-312-darwin.so +0 -0
- {lets_plot-4.6.2.dist-info → lets_plot-4.7.0rc1.dist-info}/licenses/LICENSE +0 -0
- {lets_plot-4.6.2.dist-info → lets_plot-4.7.0rc1.dist-info}/top_level.txt +0 -0
lets_plot/_global_settings.py
CHANGED
|
@@ -18,6 +18,7 @@ ENV_OFFLINE = 'LETS_PLOT_OFFLINE' # bool
|
|
|
18
18
|
ENV_NO_JS = 'LETS_PLOT_NO_JS' # bool
|
|
19
19
|
ENV_MAX_WIDTH = 'LETS_PLOT_MAX_WIDTH'
|
|
20
20
|
ENV_MAX_HEIGHT = 'LETS_PLOT_MAX_HEIGHT'
|
|
21
|
+
ENV_MAGICK_EXPORT = 'LETS_PLOT_MAGICK_EXPORT' # bool
|
|
21
22
|
ENV_MAPTILES_KIND = 'LETS_PLOT_MAPTILES_KIND'
|
|
22
23
|
ENV_MAPTILES_URL = 'LETS_PLOT_MAPTILES_URL'
|
|
23
24
|
ENV_MAPTILES_THEME = 'LETS_PLOT_MAPTILES_THEME'
|
|
@@ -29,6 +30,7 @@ ENV_DEV_OFFLINE = 'LETS_PLOT_DEV_OFFLINE' # bool
|
|
|
29
30
|
ENV_DEV_NO_JS = 'LETS_PLOT_DEV_NO_JS' # bool
|
|
30
31
|
ENV_DEV_MAX_WIDTH = 'LETS_PLOT_DEV_MAX_WIDTH'
|
|
31
32
|
ENV_DEV_MAX_HEIGHT = 'LETS_PLOT_DEV_MAX_HEIGHT'
|
|
33
|
+
ENV_DEV_MAGICK_EXPORT = 'LETS_PLOT_DEV_MAGICK_EXPORT' # bool
|
|
32
34
|
ENV_DEV_MAPTILES_KIND = 'LETS_PLOT_DEV_MAPTILES_KIND'
|
|
33
35
|
ENV_DEV_MAPTILES_URL = 'LETS_PLOT_DEV_MAPTILES_URL'
|
|
34
36
|
ENV_DEV_MAPTILES_THEME = 'LETS_PLOT_DEV_MAPTILES_THEME'
|
|
@@ -45,6 +47,7 @@ JS_NAME = 'js_name'
|
|
|
45
47
|
JS_URL_MANUAL = 'js_url_manual'
|
|
46
48
|
MAX_WIDTH = 'max_width'
|
|
47
49
|
MAX_HEIGHT = 'max_height'
|
|
50
|
+
MAGICK_EXPORT = 'magick_export'
|
|
48
51
|
|
|
49
52
|
MAPTILES_KIND = 'maptiles_kind'
|
|
50
53
|
MAPTILES_URL = 'maptiles_url'
|
|
@@ -82,6 +85,7 @@ def _get_env_val(actual_name: str) -> Any:
|
|
|
82
85
|
_settings = {
|
|
83
86
|
OFFLINE: _init_value(OFFLINE, False), # default: download from CDN
|
|
84
87
|
NO_JS: _init_value(NO_JS, False),
|
|
88
|
+
MAGICK_EXPORT: _init_value(MAGICK_EXPORT, True), # default: use cairo for export
|
|
85
89
|
# JS_BASE_URL: 'https://dl.bintray.com/jetbrains/lets-plot',
|
|
86
90
|
# JS_BASE_URL: "https://cdnjs.cloudflare.com/ajax/libs/lets-plot",
|
|
87
91
|
JS_BASE_URL: "https://cdn.jsdelivr.net/gh/JetBrains/lets-plot@v{version}".format(version=__version__),
|
|
@@ -97,6 +101,7 @@ _settings = {
|
|
|
97
101
|
|
|
98
102
|
'dev_' + OFFLINE: _init_value('dev_' + OFFLINE, True), # default: embed js into the notebook
|
|
99
103
|
'dev_' + NO_JS: _init_value('dev_' + NO_JS, False),
|
|
104
|
+
'dev_' + MAGICK_EXPORT: _init_value('dev_' + MAGICK_EXPORT, True), # default: use cairo for export
|
|
100
105
|
# We don't publish "dev" version, it must be served on localhost:
|
|
101
106
|
# $ cd lets-plot
|
|
102
107
|
# ./gradlew js-package:jsBrowserDevelopmentWebpack
|
lets_plot/_kbridge.py
CHANGED
|
@@ -19,6 +19,13 @@ def _generate_svg(plot_spec: Dict, use_css_pixelated_image_rendering: bool = Tru
|
|
|
19
19
|
plot_spec = _standardize_plot_spec(plot_spec)
|
|
20
20
|
return lets_plot_kotlin_bridge.export_svg(plot_spec, use_css_pixelated_image_rendering)
|
|
21
21
|
|
|
22
|
+
def _export_png(bytestring: Dict, output_width: float, output_height: float, unit: str, dpi: int, scale: float) -> str:
|
|
23
|
+
"""
|
|
24
|
+
Export a plot to PNG format. Returns base64 encoded string of the PNG image.
|
|
25
|
+
"""
|
|
26
|
+
plot_spec = _standardize_plot_spec(bytestring)
|
|
27
|
+
return lets_plot_kotlin_bridge.export_png(plot_spec, output_width, output_height, unit, dpi, scale)
|
|
28
|
+
|
|
22
29
|
|
|
23
30
|
def _generate_static_html_page(plot_spec: Dict, iframe: bool) -> str:
|
|
24
31
|
plot_spec = _standardize_plot_spec(plot_spec)
|
lets_plot/_type_utils.py
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
#
|
|
5
5
|
import json
|
|
6
6
|
import math
|
|
7
|
-
from datetime import datetime
|
|
7
|
+
from datetime import datetime, date, time, timezone
|
|
8
8
|
|
|
9
9
|
from typing import Dict
|
|
10
10
|
|
|
@@ -83,7 +83,7 @@ def _standardize_value(v):
|
|
|
83
83
|
if math.isfinite(v):
|
|
84
84
|
return float(v)
|
|
85
85
|
# None for special values like 'nan' etc. because
|
|
86
|
-
# some
|
|
86
|
+
# some JSON parsers (like com.google.gson.Gson) do not handle them well.
|
|
87
87
|
return None
|
|
88
88
|
if is_int(v):
|
|
89
89
|
return float(v)
|
|
@@ -95,13 +95,36 @@ def _standardize_value(v):
|
|
|
95
95
|
return [_standardize_value(elem) for elem in v]
|
|
96
96
|
if isinstance(v, tuple):
|
|
97
97
|
return tuple(_standardize_value(elem) for elem in v)
|
|
98
|
-
|
|
98
|
+
|
|
99
|
+
if (numpy and isinstance(v, numpy.ndarray)):
|
|
100
|
+
# Process each array element individually.
|
|
101
|
+
# Don't use '.tolist()' because this will implicitly
|
|
102
|
+
# convert 'datetime64' values to unpredictable 'datetime' objects.
|
|
103
|
+
return [_standardize_value(x) for x in v]
|
|
104
|
+
|
|
105
|
+
if (pandas and isinstance(v, pandas.Series)) or (jnp and isinstance(v, jnp.ndarray)):
|
|
99
106
|
return _standardize_value(v.tolist())
|
|
107
|
+
|
|
108
|
+
# Universal NaT/NaN check
|
|
109
|
+
if pandas and pandas.isna(v):
|
|
110
|
+
return None
|
|
111
|
+
|
|
100
112
|
if isinstance(v, datetime):
|
|
101
|
-
|
|
113
|
+
# Datetime: to milliseconds since epoch (time zone aware)
|
|
114
|
+
return v.timestamp() * 1000
|
|
115
|
+
if isinstance(v, date):
|
|
116
|
+
# Local date: to milliseconds since epoch (midnight UTC)
|
|
117
|
+
return datetime.combine(v, time.min, tzinfo=timezone.utc).timestamp() * 1000
|
|
118
|
+
if isinstance(v, time):
|
|
119
|
+
# Local time: to milliseconds since midnight
|
|
120
|
+
return float(v.hour * 3600_000 + v.minute * 60_000 + v.second * 1000 + v.microsecond // 1000)
|
|
121
|
+
if numpy and isinstance(v, numpy.datetime64):
|
|
122
|
+
try:
|
|
123
|
+
# numpy.datetime64: to milliseconds since epoch (Unix time)
|
|
124
|
+
return float(v.astype('datetime64[ms]').astype(numpy.int64))
|
|
125
|
+
except:
|
|
102
126
|
return None
|
|
103
|
-
|
|
104
|
-
return v.timestamp() * 1000 # convert from second to millisecond
|
|
127
|
+
|
|
105
128
|
if shapely and isinstance(v, shapely.geometry.base.BaseGeometry):
|
|
106
129
|
return json.dumps(shapely.geometry.mapping(v))
|
|
107
130
|
try:
|
lets_plot/_version.py
CHANGED
lets_plot/bistro/im.py
CHANGED
lets_plot/bistro/waterfall.py
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
# Copyright (c) 2024. JetBrains s.r.o.
|
|
2
2
|
# Use of this source code is governed by the MIT license that can be found in the LICENSE file.
|
|
3
3
|
|
|
4
|
-
from lets_plot.plot.core import PlotSpec, aes
|
|
4
|
+
from lets_plot.plot.core import PlotSpec, LayerSpec, FeatureSpecArray, aes
|
|
5
5
|
from lets_plot.plot.util import as_annotated_data
|
|
6
6
|
|
|
7
7
|
__all__ = ['waterfall_plot']
|
|
@@ -17,7 +17,9 @@ def waterfall_plot(data, x, y, *,
|
|
|
17
17
|
calc_total=None, total_title=None,
|
|
18
18
|
hline=None, hline_ontop=None,
|
|
19
19
|
connector=None,
|
|
20
|
-
|
|
20
|
+
relative_labels=None, absolute_labels=None,
|
|
21
|
+
label=None, label_format=None,
|
|
22
|
+
background_layers=None) -> PlotSpec:
|
|
21
23
|
"""
|
|
22
24
|
A waterfall plot shows the cumulative effect of sequentially introduced positive or negative values.
|
|
23
25
|
|
|
@@ -31,7 +33,8 @@ def waterfall_plot(data, x, y, *,
|
|
|
31
33
|
Name of a numeric variable.
|
|
32
34
|
measure : str
|
|
33
35
|
Kind of a calculation.
|
|
34
|
-
|
|
36
|
+
It takes the name of a data column.
|
|
37
|
+
The values in the column could be:
|
|
35
38
|
|
|
36
39
|
'absolute' - the value is shown as is;
|
|
37
40
|
'relative' - the value is shown as a difference from the previous value;
|
|
@@ -43,10 +46,14 @@ def waterfall_plot(data, x, y, *,
|
|
|
43
46
|
Color of the box boundary lines.
|
|
44
47
|
For more info see `Color and Fill <https://lets-plot.org/python/pages/aesthetics.html#color-and-fill>`__.
|
|
45
48
|
Use 'flow_type' to color lines by the direction of the flow.
|
|
49
|
+
Flow type names: "Absolute", "Increase", "Decrease" and "Total".
|
|
50
|
+
You could use these names to change the default colors with the `scale_color_manual()` function.
|
|
46
51
|
fill : str
|
|
47
52
|
Fill color of the boxes.
|
|
48
53
|
For more info see `Color and Fill <https://lets-plot.org/python/pages/aesthetics.html#color-and-fill>`__.
|
|
49
54
|
Use 'flow_type' to color boxes by the direction of the flow.
|
|
55
|
+
Flow type names: "Absolute", "Increase", "Decrease" and "Total".
|
|
56
|
+
You could use these names to change the default colors with the `scale_fill_manual()` function.
|
|
50
57
|
size : float, default=0.0
|
|
51
58
|
Line width of the box boundary lines.
|
|
52
59
|
alpha : float
|
|
@@ -98,13 +105,27 @@ def waterfall_plot(data, x, y, *,
|
|
|
98
105
|
Line between neighbouring boxes connecting the end of the previous box and the beginning of the next box.
|
|
99
106
|
Set 'blank' or result of `element_blank()` to draw nothing.
|
|
100
107
|
Set `element_line()` to specify parameters.
|
|
108
|
+
relative_labels : dict
|
|
109
|
+
Result of the call to the `layer_labels()` function.
|
|
110
|
+
Specify content and formatting of annotation labels on relative change bars.
|
|
111
|
+
If specified, overrides `label_format` for relative bars.
|
|
112
|
+
See `layer_labels() <https://lets-plot.org/python/pages/api/lets_plot.layer_labels.html>`__.
|
|
113
|
+
absolute_labels : dict
|
|
114
|
+
Result of the call to the `layer_labels()` function.
|
|
115
|
+
Specify content and formatting of annotation labels on absolute value bars.
|
|
116
|
+
If specified, overrides `label_format` for absolute bars.
|
|
117
|
+
See `layer_labels() <https://lets-plot.org/python/pages/api/lets_plot.layer_labels.html>`__.
|
|
101
118
|
label : str or dict
|
|
102
|
-
|
|
119
|
+
Style configuration for labels on bars. Applied to default labels or to
|
|
120
|
+
relative/absolute labels when `relative_labels` or `absolute_labels` are specified.
|
|
103
121
|
Set 'blank' or result of `element_blank()` to draw nothing.
|
|
104
|
-
Set `element_text()` to specify parameters.
|
|
105
|
-
Use
|
|
122
|
+
Set `element_text()` to specify style parameters.
|
|
123
|
+
Use `element_text(color='inherit')` to make labels inherit the color of bar borders.
|
|
124
|
+
See `element_text() <https://lets-plot.org/python/pages/api/lets_plot.element_text.html>`__.
|
|
106
125
|
label_format : str
|
|
107
|
-
Format used to transform label
|
|
126
|
+
Format string used to transform label values to text. Applied to default labels or to
|
|
127
|
+
relative/absolute labels when `relative_labels` or `absolute_labels` are specified.
|
|
128
|
+
Can be overridden by formatting specified in `relative_labels` or `absolute_labels`.
|
|
108
129
|
Examples:
|
|
109
130
|
|
|
110
131
|
- '.2f' -> '12.45'
|
|
@@ -112,6 +133,8 @@ def waterfall_plot(data, x, y, *,
|
|
|
112
133
|
- 'TTL: {.2f}$' -> 'TTL: 12.45$'
|
|
113
134
|
|
|
114
135
|
For more info see `Formatting <https://lets-plot.org/python/pages/formats.html>`__.
|
|
136
|
+
background_layers : LayerSpec or FeatureSpecArray
|
|
137
|
+
Background layers to be added to the plot.
|
|
115
138
|
|
|
116
139
|
Returns
|
|
117
140
|
-------
|
|
@@ -152,6 +175,40 @@ def waterfall_plot(data, x, y, *,
|
|
|
152
175
|
|
|
153
176
|
|
|
|
154
177
|
|
|
178
|
+
.. jupyter-execute::
|
|
179
|
+
:linenos:
|
|
180
|
+
:emphasize-lines: 21-25
|
|
181
|
+
|
|
182
|
+
import numpy as np
|
|
183
|
+
from lets_plot import *
|
|
184
|
+
from lets_plot.bistro.waterfall import *
|
|
185
|
+
LetsPlot.setup_html()
|
|
186
|
+
categories = list("ABCDEF")
|
|
187
|
+
np.random.seed(42)
|
|
188
|
+
data = {
|
|
189
|
+
'x': categories,
|
|
190
|
+
'y': np.random.normal(size=len(categories))
|
|
191
|
+
}
|
|
192
|
+
band_data = {
|
|
193
|
+
'xmin': [-0.5, 2.5],
|
|
194
|
+
'xmax': [2.5, 5.5],
|
|
195
|
+
'name': ['Q1', 'Q2']
|
|
196
|
+
}
|
|
197
|
+
text_data = {
|
|
198
|
+
'x': [0, 3],
|
|
199
|
+
'y': [2.7, 2.7],
|
|
200
|
+
'name': ['Q1', 'Q2']
|
|
201
|
+
}
|
|
202
|
+
waterfall_plot(data, 'x', 'y', label_format='.2f',
|
|
203
|
+
background_layers=geom_band(
|
|
204
|
+
aes(xmin='xmin', xmax='xmax', fill='name', color='name'),
|
|
205
|
+
data=band_data, alpha=0.2
|
|
206
|
+
)) + \\
|
|
207
|
+
geom_text(aes(x='x', y='y', label='name'), data=text_data, size=10) + \\
|
|
208
|
+
ggtitle("Waterfall with background layers")
|
|
209
|
+
|
|
210
|
+
|
|
|
211
|
+
|
|
155
212
|
.. jupyter-execute::
|
|
156
213
|
:linenos:
|
|
157
214
|
:emphasize-lines: 12-18
|
|
@@ -172,7 +229,7 @@ def waterfall_plot(data, x, y, *,
|
|
|
172
229
|
width=.7, size=1, fill="white", color='flow_type', \\
|
|
173
230
|
hline=element_line(linetype='solid'), hline_ontop=False, \\
|
|
174
231
|
connector=element_line(linetype='dotted'), \\
|
|
175
|
-
label=element_text(color='
|
|
232
|
+
label=element_text(color='inherit'), \\
|
|
176
233
|
total_title="Result", show_legend=True)
|
|
177
234
|
|
|
178
235
|
|
|
|
@@ -206,7 +263,7 @@ def waterfall_plot(data, x, y, *,
|
|
|
206
263
|
|
|
207
264
|
.. jupyter-execute::
|
|
208
265
|
:linenos:
|
|
209
|
-
:emphasize-lines:
|
|
266
|
+
:emphasize-lines: 17-18
|
|
210
267
|
|
|
211
268
|
from lets_plot import *
|
|
212
269
|
from lets_plot.bistro.waterfall import *
|
|
@@ -214,15 +271,36 @@ def waterfall_plot(data, x, y, *,
|
|
|
214
271
|
data = {
|
|
215
272
|
'company': ["Badgersoft"] * 7 + ["AIlien Co."] * 7,
|
|
216
273
|
'accounts': ["initial", "revenue", "costs", "Q1", "revenue", "costs", "Q2"] * 2,
|
|
217
|
-
'values': [200, 200, -100, None, 250, -100, None,
|
|
274
|
+
'values': [200, 200, -100, None, 250, -100, None,
|
|
218
275
|
150, 50, -100, None, 100, -100, None],
|
|
219
276
|
'measure': ['absolute', 'relative', 'relative', 'total', 'relative', 'relative', 'total'] * 2,
|
|
220
277
|
}
|
|
221
|
-
|
|
278
|
+
colors = {
|
|
279
|
+
"Absolute": "darkseagreen",
|
|
280
|
+
"Increase": "palegoldenrod",
|
|
281
|
+
"Decrease": "paleturquoise",
|
|
282
|
+
"Total": "palegreen",
|
|
283
|
+
}
|
|
284
|
+
waterfall_plot(data, 'accounts', 'values', measure='measure', group='company',
|
|
285
|
+
size=.75, label=element_text(color="black")) + \\
|
|
286
|
+
scale_fill_manual(values=colors) + \\
|
|
222
287
|
facet_wrap(facets='company', scales='free_x')
|
|
223
288
|
|
|
224
289
|
"""
|
|
225
290
|
data, mapping, data_meta = as_annotated_data(data, aes(x=x, y=y))
|
|
291
|
+
|
|
292
|
+
if background_layers is None:
|
|
293
|
+
layers = []
|
|
294
|
+
elif isinstance(background_layers, LayerSpec):
|
|
295
|
+
layers = [background_layers]
|
|
296
|
+
elif isinstance(background_layers, FeatureSpecArray):
|
|
297
|
+
for sublayer in background_layers.elements():
|
|
298
|
+
if not isinstance(sublayer, LayerSpec):
|
|
299
|
+
raise TypeError("Invalid 'layer' type: {}".format(type(sublayer)))
|
|
300
|
+
layers = background_layers.elements()
|
|
301
|
+
else:
|
|
302
|
+
raise TypeError("Invalid 'layer' type: {}".format(type(background_layers)))
|
|
303
|
+
|
|
226
304
|
return PlotSpec(data=data, mapping=None, scales=[], layers=[], bistro={
|
|
227
305
|
'name': 'waterfall',
|
|
228
306
|
'x': x,
|
|
@@ -247,6 +325,9 @@ def waterfall_plot(data, x, y, *,
|
|
|
247
325
|
'hline': hline,
|
|
248
326
|
'hline_ontop': hline_ontop,
|
|
249
327
|
'connector': connector,
|
|
328
|
+
'relative_labels': relative_labels,
|
|
329
|
+
'absolute_labels': absolute_labels,
|
|
250
330
|
'label': label,
|
|
251
331
|
'label_format': label_format,
|
|
252
|
-
|
|
332
|
+
'background_layers': [layer.as_dict() for layer in layers]
|
|
333
|
+
}, **data_meta)
|
lets_plot/export/ggsave_.py
CHANGED
|
@@ -48,10 +48,10 @@ def ggsave(plot: Union[PlotSpec, SupPlotsSpec, GGBunch], filename: str, *, path:
|
|
|
48
48
|
h : float, default=None
|
|
49
49
|
Height of the output image in units.
|
|
50
50
|
Only applicable when exporting to PNG or PDF.
|
|
51
|
-
unit : {'in', 'cm', 'mm'}, default=
|
|
51
|
+
unit : {'in', 'cm', 'mm'}, default='in'
|
|
52
52
|
Unit of the output image. One of: 'in', 'cm', 'mm'.
|
|
53
53
|
Only applicable when exporting to PNG or PDF.
|
|
54
|
-
dpi : int, default=
|
|
54
|
+
dpi : int, default=300
|
|
55
55
|
Resolution in dots per inch.
|
|
56
56
|
Only applicable when exporting to PNG or PDF.
|
|
57
57
|
|
|
@@ -66,19 +66,27 @@ def ggsave(plot: Union[PlotSpec, SupPlotsSpec, GGBunch], filename: str, *, path:
|
|
|
66
66
|
|
|
67
67
|
For PNG and PDF formats:
|
|
68
68
|
|
|
69
|
-
|
|
69
|
+
- If `w`, `h`, `unit`, and `dpi` are all specified:
|
|
70
70
|
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
- If the aspect ratio of `w` and `h` differs from the plot's pixel aspect ratio:
|
|
71
|
+
- The plot's pixel size (default or set by `ggsize()`) is ignored.
|
|
72
|
+
- The output size is calculated using the specified `w`, `h`, `unit`, and `dpi`.
|
|
74
73
|
|
|
75
|
-
|
|
76
|
-
* It's fitted within the specified `w` x `h` area.
|
|
77
|
-
* Any extra space is left empty.
|
|
74
|
+
- The plot is resized to fit the specified `w` x `h` area, which may affect the layout, tick labels, and other elements.
|
|
78
75
|
|
|
79
|
-
|
|
76
|
+
- If only `dpi` is specified:
|
|
80
77
|
|
|
81
|
-
|
|
78
|
+
- The plot's pixel size (default or set by `ggsize()`) is converted to inches using the standard display PPI of 96.
|
|
79
|
+
- The output size is then calculated based on the specified DPI.
|
|
80
|
+
|
|
81
|
+
- The plot maintains its aspect ratio, preserving layout, tick labels, and other visual elements.
|
|
82
|
+
- Useful for printing - the plot will appear nearly the same size as on screen.
|
|
83
|
+
|
|
84
|
+
- If `w`, `h` are not specified:
|
|
85
|
+
|
|
86
|
+
- The `scale` parameter is used to determine the output size.
|
|
87
|
+
|
|
88
|
+
- The plot maintains its aspect ratio, preserving layout, tick labels, and other visual elements.
|
|
89
|
+
- Useful for generating high-resolution images suitable for publication.
|
|
82
90
|
|
|
83
91
|
Examples
|
|
84
92
|
--------
|
|
@@ -99,8 +107,8 @@ def ggsave(plot: Union[PlotSpec, SupPlotsSpec, GGBunch], filename: str, *, path:
|
|
|
99
107
|
|
|
100
108
|
from lets_plot import *
|
|
101
109
|
LetsPlot.setup_html()
|
|
102
|
-
plot = ggplot() + geom_point(x=0, y=0)
|
|
103
|
-
ggsave(plot, 'plot.png', w=
|
|
110
|
+
plot = ggplot() + geom_point(x=0, y=0)
|
|
111
|
+
ggsave(plot, 'plot.png', w=4, h=3)
|
|
104
112
|
|
|
105
113
|
"""
|
|
106
114
|
|
|
@@ -125,7 +133,7 @@ def ggsave(plot: Union[PlotSpec, SupPlotsSpec, GGBunch], filename: str, *, path:
|
|
|
125
133
|
return _to_svg(plot, pathname)
|
|
126
134
|
elif ext in ['html', 'htm']:
|
|
127
135
|
return _to_html(plot, pathname, iframe=iframe)
|
|
128
|
-
elif ext in ['png', 'pdf']:
|
|
136
|
+
elif ext in ['png', 'pdf', 'bmp']:
|
|
129
137
|
return _export_as_raster(plot, pathname, scale, export_format=ext, w=w, h=h, unit=unit, dpi=dpi)
|
|
130
138
|
else:
|
|
131
139
|
raise ValueError(
|