lets-plot 4.6.1__cp312-cp312-win_amd64.whl → 4.7.0rc1__cp312-cp312-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.

Files changed (35) hide show
  1. lets_plot/_global_settings.py +5 -0
  2. lets_plot/_kbridge.py +7 -0
  3. lets_plot/_type_utils.py +29 -6
  4. lets_plot/_version.py +1 -1
  5. lets_plot/bistro/im.py +2 -2
  6. lets_plot/bistro/waterfall.py +93 -12
  7. lets_plot/export/ggsave_.py +23 -15
  8. lets_plot/frontend_context/_configuration.py +8 -1
  9. lets_plot/geo_data/__init__.py +2 -1
  10. lets_plot/package_data/lets-plot.min.js +2 -1
  11. lets_plot/plot/annotation.py +75 -18
  12. lets_plot/plot/core.py +147 -30
  13. lets_plot/plot/geom.py +730 -89
  14. lets_plot/plot/geom_function_.py +1 -1
  15. lets_plot/plot/geom_imshow_.py +42 -51
  16. lets_plot/plot/geom_livemap_.py +2 -22
  17. lets_plot/plot/ggtb_.py +0 -1
  18. lets_plot/plot/pos.py +13 -44
  19. lets_plot/plot/scale_position.py +9 -3
  20. lets_plot/plot/series_meta.py +179 -105
  21. lets_plot/plot/stat.py +4 -4
  22. lets_plot/plot/subplots.py +4 -4
  23. lets_plot/plot/theme_.py +55 -52
  24. lets_plot/plot/util.py +15 -4
  25. lets_plot/tilesets.py +69 -4
  26. {lets_plot-4.6.1.dist-info → lets_plot-4.7.0rc1.dist-info}/METADATA +28 -20
  27. {lets_plot-4.6.1.dist-info → lets_plot-4.7.0rc1.dist-info}/RECORD +35 -31
  28. {lets_plot-4.6.1.dist-info → lets_plot-4.7.0rc1.dist-info}/WHEEL +1 -1
  29. lets_plot-4.7.0rc1.dist-info/licenses/licenses/LICENSE.FreeType +166 -0
  30. lets_plot-4.7.0rc1.dist-info/licenses/licenses/LICENSE.ImageMagick +106 -0
  31. lets_plot-4.7.0rc1.dist-info/licenses/licenses/LICENSE.expat +21 -0
  32. lets_plot-4.7.0rc1.dist-info/licenses/licenses/LICENSE.fontconfig +200 -0
  33. lets_plot_kotlin_bridge.cp312-win_amd64.pyd +0 -0
  34. {lets_plot-4.6.1.dist-info → lets_plot-4.7.0rc1.dist-info/licenses}/LICENSE +0 -0
  35. {lets_plot-4.6.1.dist-info → lets_plot-4.7.0rc1.dist-info}/top_level.txt +0 -0
@@ -14,7 +14,24 @@ __all__ = ['layer_labels']
14
14
 
15
15
  class layer_labels(FeatureSpec):
16
16
  """
17
- Configure annotations (for pie and bar charts).
17
+ Configure annotations for geometry layers.
18
+
19
+ Annotations are currently supported for bar, pie, and crossbar geometry
20
+ layers. This class provides methods to customize the appearance and
21
+ content of text labels displayed on these geometries.
22
+
23
+ Notes
24
+ -----
25
+ By default, annotation text color is automatically selected for optimal
26
+ contrast: white text appears on darker filled geometries, and black text
27
+ appears on lighter filled geometries.
28
+
29
+ The text color can be manually specified using:
30
+ ``theme(label_text=element_text(color=...))``
31
+
32
+ Alternatively, the ``inherit_color()`` method can be used to override both
33
+ automatic and manual color settings, making the annotation text use the
34
+ geometry's ``color`` aesthetic instead.
18
35
 
19
36
  Examples
20
37
  --------
@@ -24,9 +41,9 @@ class layer_labels(FeatureSpec):
24
41
 
25
42
  from lets_plot import *
26
43
  LetsPlot.setup_html()
27
- data = {'name': ['a', 'b', 'c', 'd', 'b'], 'value': [40, 90, 10, 50, 20 ] }
44
+ data = {'name': ['a', 'b', 'c', 'd', 'b'], 'value': [40, 90, 10, 50, 20 ]}
28
45
  ggplot(data) + geom_pie(aes(slice='value', fill='name'), size=15, hole=0.4, \\
29
- stat='identity', tooltips = 'none', \\
46
+ stat='identity', tooltips='none', \\
30
47
  labels=layer_labels().line('@value'))
31
48
 
32
49
  """
@@ -46,11 +63,12 @@ class layer_labels(FeatureSpec):
46
63
  self._lines: List = None
47
64
  self._variables = variables
48
65
  self._size = None
66
+ self._useLayerColor = None
49
67
  super().__init__('labels', name=None)
50
68
 
51
69
  def as_dict(self):
52
70
  """
53
- Return the dictionary of all properties of the object.
71
+ Return a dictionary of all properties of the object.
54
72
 
55
73
  Returns
56
74
  -------
@@ -76,6 +94,7 @@ class layer_labels(FeatureSpec):
76
94
  d['lines'] = self._lines
77
95
  d['variables'] = self._variables
78
96
  d['annotation_size'] = self._size
97
+ d['use_layer_color'] = self._useLayerColor
79
98
  return _filter_none(d)
80
99
 
81
100
  def format(self, field=None, format=None):
@@ -113,7 +132,7 @@ class layer_labels(FeatureSpec):
113
132
 
114
133
  from lets_plot import *
115
134
  LetsPlot.setup_html()
116
- data = {'name': ['a', 'b', 'c', 'd', 'b'], 'value': [40, 90, 10, 50, 20 ] }
135
+ data = {'name': ['a', 'b', 'c', 'd', 'b'], 'value': [40, 90, 10, 50, 20 ]}
117
136
  ggplot(data) + geom_pie(aes(fill=as_discrete('name', order_by='..count..'), weight='value'), \\
118
137
  size=15, tooltips='none', \\
119
138
  labels=layer_labels(['..proppct..']) \\
@@ -127,7 +146,7 @@ class layer_labels(FeatureSpec):
127
146
 
128
147
  from lets_plot import *
129
148
  LetsPlot.setup_html()
130
- data = {'name': ['a', 'b', 'c', 'd', 'b'], 'value': [40, 90, 10, 50, 20 ] }
149
+ data = {'name': ['a', 'b', 'c', 'd', 'b'], 'value': [40, 90, 10, 50, 20 ]}
131
150
  ggplot(data) + geom_pie(aes(fill=as_discrete('name', order_by='..count..', order=1), weight='value'), \\
132
151
  size=15, tooltips='none', \\
133
152
  labels=layer_labels() \\
@@ -146,12 +165,17 @@ class layer_labels(FeatureSpec):
146
165
 
147
166
  def line(self, value):
148
167
  """
149
- Line to show in the annotation.
168
+ Add a line of text to the multiline label annotation.
169
+
170
+ This method configures one line of text that will be displayed in a
171
+ multiline label. Multiple calls to this method can be chained to build
172
+ up a complete multiline annotation.
150
173
 
151
174
  Parameters
152
175
  ----------
153
176
  value : str
154
- Enriched string which becomes one line of the annotation.
177
+ The text content for this line of the annotation. Can include
178
+ variable and aesthetic references.
155
179
 
156
180
  Returns
157
181
  -------
@@ -162,17 +186,16 @@ class layer_labels(FeatureSpec):
162
186
  -----
163
187
  Variables and aesthetics can be accessed via special syntax:
164
188
 
165
- - ^color for aes,
189
+ - ^color for aesthetics,
166
190
  - @x for variable,
167
191
  - @{x + 1} for variable with spaces in the name,
168
192
  - @{x^2 + 1} for variable with spaces and '^' symbol in the name,
169
193
  - @x^2 for variable with '^' symbol in its name.
170
194
 
171
- A '^' symbol can be escaped with a backslash, a brace character
172
- in the literal text - by doubling:
195
+ Special characters can be escaped:
173
196
 
174
- - 'x\\\\^2' -> "x^2"
175
- - '{{x}}' -> "{x}"
197
+ - 'x\\\\^2' -> "x^2" (escape ^ with backslash)
198
+ - '{{x}}' -> "{x}" (escape braces by doubling)
176
199
 
177
200
  Examples
178
201
  --------
@@ -182,7 +205,7 @@ class layer_labels(FeatureSpec):
182
205
 
183
206
  from lets_plot import *
184
207
  LetsPlot.setup_html()
185
- data = {'name': ['a', 'b', 'c', 'd', 'b'], 'value': [40, 90, 10, 50, 20 ] }
208
+ data = {'name': ['a', 'b', 'c', 'd', 'b'], 'value': [40, 90, 10, 50, 20 ]}
186
209
  ggplot(data) + geom_pie(aes(fill='name', weight='value'), size=15, \\
187
210
  tooltips='none', \\
188
211
  labels=layer_labels()\\
@@ -200,12 +223,12 @@ class layer_labels(FeatureSpec):
200
223
 
201
224
  def size(self, value):
202
225
  """
203
- Text size in the annotation.
226
+ Set the text size for the annotation.
204
227
 
205
228
  Parameters
206
229
  ----------
207
230
  value : float
208
- Text size in the annotation.
231
+ The text size value for the annotation.
209
232
 
210
233
  Returns
211
234
  -------
@@ -221,9 +244,9 @@ class layer_labels(FeatureSpec):
221
244
 
222
245
  from lets_plot import *
223
246
  LetsPlot.setup_html()
224
- data = {'name': ['a', 'b', 'c', 'd', 'b'], 'value': [40, 90, 10, 50, 20 ] }
247
+ data = {'name': ['a', 'b', 'c', 'd', 'b'], 'value': [40, 90, 10, 50, 20 ]}
225
248
  ggplot(data) + geom_pie(aes(slice='value', fill='name'), size=15, hole=0.4, \\
226
- stat='identity', tooltips = 'none', \\
249
+ stat='identity', tooltips='none', \\
227
250
  labels=layer_labels().line('@value')
228
251
  .size(25))
229
252
 
@@ -231,3 +254,37 @@ class layer_labels(FeatureSpec):
231
254
 
232
255
  self._size = value
233
256
  return self
257
+
258
+ def inherit_color(self):
259
+ """
260
+ Use the layer's color for the annotation text.
261
+
262
+ When enabled, the annotation text will inherit the color from the
263
+ layer it's associated with, rather than using a default or
264
+ explicitly set color.
265
+
266
+ Returns
267
+ -------
268
+ `layer_labels`
269
+ Annotations specification.
270
+
271
+ Examples
272
+ --------
273
+
274
+ .. jupyter-execute::
275
+ :linenos:
276
+ :emphasize-lines: 8
277
+
278
+ from lets_plot import *
279
+ LetsPlot.setup_html()
280
+ data = {'name': ['a', 'b', 'c', 'd', 'b'], 'value': [40, 90, 10, 50, 20 ]}
281
+ ggplot(data) + geom_pie(aes(slice='value', color='name'), alpha=0, size=15, hole=0.4, \\
282
+ stroke=5, spacer_color='pen', \\
283
+ stat='identity', tooltips='none', \\
284
+ labels=layer_labels().line('@value')
285
+ .inherit_color())
286
+
287
+ """
288
+
289
+ self._useLayerColor = True
290
+ return self
lets_plot/plot/core.py CHANGED
@@ -9,7 +9,7 @@ from typing import Union
9
9
 
10
10
  __all__ = ['aes', 'layer']
11
11
 
12
- from lets_plot._global_settings import get_global_bool, has_global_value, FRAGMENTS_ENABLED
12
+ from lets_plot._global_settings import get_global_bool, has_global_value, FRAGMENTS_ENABLED, MAGICK_EXPORT
13
13
 
14
14
 
15
15
  def aes(x=None, y=None, **kwargs):
@@ -96,7 +96,7 @@ def layer(geom=None, stat=None, data=None, mapping=None, position=None, **kwargs
96
96
  mapped to plot "aesthetics".
97
97
  position : str or `FeatureSpec`
98
98
  Position adjustment.
99
- Either a position adjustment name: 'dodge', 'dodgev', 'jitter', 'nudge', 'jitterdodge', 'fill',
99
+ Either a position adjustment name: 'dodge', 'jitter', 'nudge', 'jitterdodge', 'fill',
100
100
  'stack' or 'identity', or the result of calling a position adjustment function (e.g., `position_dodge()` etc.).
101
101
  kwargs:
102
102
  Other arguments passed on to layer. These are often aesthetics settings, used to set an aesthetic to a fixed
@@ -566,10 +566,10 @@ class PlotSpec(FeatureSpec):
566
566
  h : float, default=None
567
567
  Height of the output image in units.
568
568
  Only applicable when exporting to PNG or PDF.
569
- unit : {'in', 'cm', 'mm'}, default=None
569
+ unit : {'in', 'cm', 'mm'}, default='in'
570
570
  Unit of the output image. One of: 'in', 'cm', 'mm'.
571
571
  Only applicable when exporting to PNG or PDF.
572
- dpi : int, default=None
572
+ dpi : int, default=300
573
573
  Resolution in dots per inch.
574
574
  Only applicable when exporting to PNG or PDF.
575
575
 
@@ -580,9 +580,27 @@ class PlotSpec(FeatureSpec):
580
580
 
581
581
  Notes
582
582
  -----
583
- Export to PNG file uses the CairoSVG library.
584
- CairoSVG is free and distributed under the LGPL-3.0 license.
585
- For more details visit: https://cairosvg.org/documentation/
583
+ - If `w`, `h`, `unit`, and `dpi` are all specified:
584
+
585
+ - The plot's pixel size (default or set by `ggsize()`) is ignored.
586
+ - The output size is calculated using the specified `w`, `h`, `unit`, and `dpi`.
587
+
588
+ - The plot is resized to fit the specified `w` x `h` area, which may affect the layout, tick labels, and other elements.
589
+
590
+ - If only `dpi` is specified:
591
+
592
+ - The plot's pixel size (default or set by `ggsize()`) is converted to inches using the standard display PPI of 96.
593
+ - The output size is then calculated based on the specified DPI.
594
+
595
+ - The plot maintains its aspect ratio, preserving layout, tick labels, and other visual elements.
596
+ - Useful for printing - the plot will appear nearly the same size as on screen.
597
+
598
+ - If `w`, `h` are not specified:
599
+
600
+ - The `scale` parameter is used to determine the output size.
601
+
602
+ - The plot maintains its aspect ratio, preserving layout, tick labels, and other visual elements.
603
+ - Useful for generating high-resolution images suitable for publication.
586
604
 
587
605
  Examples
588
606
  --------
@@ -600,6 +618,7 @@ class PlotSpec(FeatureSpec):
600
618
  file_like = io.BytesIO()
601
619
  p.to_png(file_like)
602
620
  display.Image(file_like.getvalue())
621
+
603
622
  """
604
623
  return _export_as_raster(self, path, scale, 'png', w=w, h=h, unit=unit, dpi=dpi)
605
624
 
@@ -623,10 +642,10 @@ class PlotSpec(FeatureSpec):
623
642
  h : float, default=None
624
643
  Height of the output image in units.
625
644
  Only applicable when exporting to PNG or PDF.
626
- unit : {'in', 'cm', 'mm'}, default=None
645
+ unit : {'in', 'cm', 'mm'}, default='in'
627
646
  Unit of the output image. One of: 'in', 'cm', 'mm'.
628
647
  Only applicable when exporting to PNG or PDF.
629
- dpi : int, default=None
648
+ dpi : int, default=300
630
649
  Resolution in dots per inch.
631
650
  Only applicable when exporting to PNG or PDF.
632
651
 
@@ -637,9 +656,27 @@ class PlotSpec(FeatureSpec):
637
656
 
638
657
  Notes
639
658
  -----
640
- Export to PDF file uses the CairoSVG library.
641
- CairoSVG is free and distributed under the LGPL-3.0 license.
642
- For more details visit: https://cairosvg.org/documentation/
659
+ - If `w`, `h`, `unit`, and `dpi` are all specified:
660
+
661
+ - The plot's pixel size (default or set by `ggsize()`) is ignored.
662
+ - The output size is calculated using the specified `w`, `h`, `unit`, and `dpi`.
663
+
664
+ - The plot is resized to fit the specified `w` x `h` area, which may affect the layout, tick labels, and other elements.
665
+
666
+ - If only `dpi` is specified:
667
+
668
+ - The plot's pixel size (default or set by `ggsize()`) is converted to inches using the standard display PPI of 96.
669
+ - The output size is then calculated based on the specified DPI.
670
+
671
+ - The plot maintains its aspect ratio, preserving layout, tick labels, and other visual elements.
672
+ - Useful for printing - the plot will appear nearly the same size as on screen.
673
+
674
+ - If `w`, `h` are not specified:
675
+
676
+ - The `scale` parameter is used to determine the output size.
677
+
678
+ - The plot maintains its aspect ratio, preserving layout, tick labels, and other visual elements.
679
+ - Useful for generating high-resolution images suitable for publication.
643
680
 
644
681
  Examples
645
682
  --------
@@ -660,6 +697,7 @@ class PlotSpec(FeatureSpec):
660
697
  p = ggplot({'x': x, 'y': y}, aes(x='x', y='y')) + geom_jitter()
661
698
  file_like = io.BytesIO()
662
699
  p.to_pdf(file_like)
700
+
663
701
  """
664
702
  return _export_as_raster(self, path, scale, 'pdf', w=w, h=h, unit=unit, dpi=dpi)
665
703
 
@@ -875,29 +913,108 @@ def _to_html(spec, path, iframe: bool) -> Union[str, None]:
875
913
  return None
876
914
 
877
915
 
878
- def _export_as_raster(spec, path, scale: float, export_format: str, w=None, h=None, unit=None, dpi=None) -> Union[
879
- str, None]:
880
- try:
881
- import cairosvg
882
- except ImportError:
883
- import sys
884
- print("\n"
885
- "To export Lets-Plot figure to a PNG or PDF file please install CairoSVG library"
886
- "to your Python environment.\n"
887
- "CairoSVG is free and distributed under the LGPL-3.0 license.\n"
888
- "For more details visit: https://cairosvg.org/documentation/\n", file=sys.stderr)
889
- return None
916
+ def _export_as_raster(spec, path, scale: float, export_format: str, w=None, h=None, unit=None, dpi=None) -> Union[str, None]:
917
+ if get_global_bool(MAGICK_EXPORT):
918
+ if w is None and h is None and unit is None and dpi is None:
919
+ def_scale = 2.0
920
+ def_dpi = -1
921
+ def_unit = ""
922
+ else:
923
+ def_scale = 1.0
924
+ def_dpi = 300
925
+ def_unit = 'in'
926
+
927
+ return _export_with_magick(
928
+ spec,
929
+ path,
930
+ scale if scale is not None else def_scale,
931
+ export_format,
932
+ w if w is not None else -1,
933
+ h if h is not None else -1,
934
+ unit if unit is not None else def_unit,
935
+ dpi if dpi is not None else def_dpi
936
+ )
937
+ else:
938
+ return _export_with_cairo(spec, path, scale, export_format, w, h, unit, dpi)
939
+
940
+
941
+ def _export_with_magick(spec, path, scale: float, export_format: str, w, h, unit, dpi) -> Union[str, None]:
942
+ import base64
943
+ from .. import _kbridge
944
+
945
+ if isinstance(path, str):
946
+ file_path = _makedirs(path)
947
+ file_like_object = None
948
+ else:
949
+ file_like_object = path
950
+ file_path = None
951
+
952
+ png_base64 = _kbridge._export_png(spec.as_dict(), float(w), float(h), unit, int(dpi), float(scale))
953
+ png = base64.b64decode(png_base64)
890
954
 
891
955
  if export_format.lower() == 'png':
892
- export_function = cairosvg.svg2png
956
+ if file_path is not None:
957
+ with open(file_path, 'wb') as f:
958
+ f.write(png)
959
+ return file_path
960
+ else:
961
+ file_like_object.write(png)
962
+ return None
893
963
  elif export_format.lower() == 'pdf':
894
- export_function = cairosvg.svg2pdf
964
+ try:
965
+ from PIL import Image
966
+ except ImportError:
967
+ import sys
968
+ print("\n"
969
+ "To export Lets-Plot figure to a PDF file please install pillow library"
970
+ "to your Python environment.\n"
971
+ "Pillow is free and distributed under the MIT-CMU license.\n"
972
+ "For more details visit: https://python-pillow.github.io/\n", file=sys.stderr)
973
+ return None
974
+
975
+
976
+ with Image.open(io.BytesIO(png)) as img:
977
+ if img.mode == 'RGBA':
978
+ img = img.convert('RGB')
979
+
980
+ dpi = dpi if dpi is not None else 96 # Default DPI if not specified
981
+ if file_path is not None:
982
+ img.save(file_path, "PDF", dpi=(dpi, dpi))
983
+ return file_path
984
+ else:
985
+ img.save(file_like_object, "PDF", dpi=(dpi, dpi))
986
+ return None
895
987
  else:
896
988
  raise ValueError("Unknown export format: {}".format(export_format))
897
989
 
990
+
991
+ def _export_with_cairo(spec, path, scale: float, export_format: str, w=None, h=None, unit=None, dpi=None) -> Union[str, None]:
898
992
  from .. import _kbridge
899
- # Use SVG image-rendering style as Cairo doesn't support CSS image-rendering style,
900
- svg = _kbridge._generate_svg(spec.as_dict(), use_css_pixelated_image_rendering=False)
993
+
994
+ input = None
995
+ export_function = None
996
+
997
+ if export_format.lower() == 'png' or export_format.lower() == 'pdf':
998
+ try:
999
+ import cairosvg
1000
+ except ImportError:
1001
+ import sys
1002
+ print("\n"
1003
+ "To export Lets-Plot figure to a PNG or PDF file please install CairoSVG library"
1004
+ "to your Python environment.\n"
1005
+ "CairoSVG is free and distributed under the LGPL-3.0 license.\n"
1006
+ "For more details visit: https://cairosvg.org/documentation/\n", file=sys.stderr)
1007
+ return None
1008
+
1009
+ if export_format.lower() == 'png':
1010
+ export_function = cairosvg.svg2png
1011
+ elif export_format.lower() == 'pdf':
1012
+ export_function = cairosvg.svg2pdf
1013
+
1014
+ # Use SVG image-rendering style as Cairo doesn't support CSS image-rendering style,
1015
+ input = _kbridge._generate_svg(spec.as_dict(), use_css_pixelated_image_rendering=False)
1016
+ else:
1017
+ raise ValueError("Unknown export format: {}".format(export_format))
901
1018
 
902
1019
  if isinstance(path, str):
903
1020
  abspath = _makedirs(path)
@@ -910,10 +1027,10 @@ def _export_as_raster(spec, path, scale: float, export_format: str, w=None, h=No
910
1027
  raise ValueError("w, h, unit, and dpi must all be specified")
911
1028
 
912
1029
  w, h = _to_inches(w, unit) * dpi, _to_inches(h, unit) * dpi
913
- export_function(bytestring=svg, write_to=path, dpi=dpi, output_width=w, output_height=h)
1030
+ export_function(bytestring=input, write_to=path, dpi=dpi, output_width=w, output_height=h)
914
1031
  else:
915
1032
  scale = scale if scale is not None else 2.0
916
- export_function(bytestring=svg, write_to=path, scale=scale)
1033
+ export_function(bytestring=input, write_to=path, scale=scale)
917
1034
 
918
1035
  return result
919
1036