lets-plot 4.3.3__cp310-cp310-win_amd64.whl → 4.4.0rc1__cp310-cp310-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.

@@ -0,0 +1,123 @@
1
+ # Copyright (c) 2024. 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
+ from datetime import datetime
4
+ from typing import Union, Dict, Iterable
5
+
6
+ from lets_plot._type_utils import is_polars_dataframe
7
+ from lets_plot.plot.util import is_pandas_data_frame
8
+
9
+ TYPE_INTEGER = 'int'
10
+ TYPE_FLOATING = 'float'
11
+ TYPE_STRING = 'str'
12
+ TYPE_BOOLEAN = 'bool'
13
+ TYPE_DATE_TIME = 'datetime'
14
+ TYPE_UNKNOWN = 'unknown'
15
+
16
+
17
+ def infer_type(data: Union[Dict, 'pandas.DataFrame', 'polars.DataFrame']) -> Dict[str, str]:
18
+ type_info = {}
19
+
20
+ if is_pandas_data_frame(data):
21
+ import pandas as pd
22
+ import numpy as np # np is a dependency of pandas, we can import it without checking
23
+
24
+ for var_name, var_content in data.items():
25
+ if data.empty:
26
+ type_info[var_name] = TYPE_UNKNOWN
27
+ continue
28
+
29
+ inferred_type = pd.api.types.infer_dtype(var_content.values, skipna=True)
30
+ if inferred_type == "categorical":
31
+ dtype = var_content.cat.categories.dtype
32
+
33
+ if np.issubdtype(dtype, np.integer):
34
+ type_info[var_name] = TYPE_INTEGER
35
+ elif np.issubdtype(dtype, np.floating):
36
+ type_info[var_name] = TYPE_FLOATING
37
+ elif np.issubdtype(dtype, np.object_):
38
+ # Check if all elements are strings
39
+ if all(isinstance(x, str) for x in var_content.cat.categories):
40
+ type_info[var_name] = TYPE_STRING
41
+ else:
42
+ type_info[var_name] = TYPE_UNKNOWN
43
+ else:
44
+ type_info[var_name] = TYPE_UNKNOWN
45
+ else:
46
+ # see https://pandas.pydata.org/docs/reference/api/pandas.api.types.infer_dtype.html
47
+ if inferred_type == 'string':
48
+ type_info[var_name] = TYPE_STRING
49
+ elif inferred_type == 'floating':
50
+ type_info[var_name] = TYPE_FLOATING
51
+ elif inferred_type == 'integer':
52
+ type_info[var_name] = TYPE_INTEGER
53
+ elif inferred_type == 'boolean':
54
+ type_info[var_name] = TYPE_BOOLEAN
55
+ elif inferred_type == 'datetime64' or inferred_type == 'datetime':
56
+ type_info[var_name] = TYPE_DATE_TIME
57
+ elif inferred_type == "date":
58
+ type_info[var_name] = TYPE_DATE_TIME
59
+ elif inferred_type == 'empty': # for columns with all None values
60
+ type_info[var_name] = TYPE_UNKNOWN
61
+ else:
62
+ type_info[var_name] = 'unknown(pandas:' + inferred_type + ')'
63
+ elif is_polars_dataframe(data):
64
+ import polars as pl
65
+ from polars.datatypes.group import INTEGER_DTYPES, FLOAT_DTYPES
66
+ for var_name, var_type in data.schema.items():
67
+
68
+ # https://docs.pola.rs/api/python/stable/reference/datatypes.html
69
+ if var_type in FLOAT_DTYPES:
70
+ type_info[var_name] = TYPE_FLOATING
71
+ elif var_type in INTEGER_DTYPES:
72
+ type_info[var_name] = TYPE_INTEGER
73
+ elif var_type == pl.datatypes.String:
74
+ type_info[var_name] = TYPE_STRING
75
+ elif var_type == pl.datatypes.Boolean:
76
+ type_info[var_name] = TYPE_BOOLEAN
77
+ elif var_type == pl.datatypes.Date or var_type == pl.datatypes.Datetime:
78
+ type_info[var_name] = TYPE_DATE_TIME
79
+ else:
80
+ type_info[var_name] = 'unknown(polars:' + str(var_type) + ')'
81
+ elif isinstance(data, dict):
82
+ for var_name, var_content in data.items():
83
+ if isinstance(var_content, Iterable):
84
+ if not any(True for _ in var_content): # empty
85
+ type_info[var_name] = TYPE_UNKNOWN
86
+ continue
87
+
88
+ type_set = set(type(val) for val in var_content)
89
+ if None in type_set:
90
+ type_set.remove(None)
91
+
92
+ if len(type_set) > 1:
93
+ type_info[var_name] = 'unknown(mixed types)'
94
+ continue
95
+
96
+ try:
97
+ import numpy
98
+ except ImportError:
99
+ numpy = None
100
+
101
+ type_obj = list(type_set)[0]
102
+ if type_obj == bool:
103
+ type_info[var_name] = TYPE_BOOLEAN
104
+ elif issubclass(type_obj, int):
105
+ type_info[var_name] = TYPE_INTEGER
106
+ elif issubclass(type_obj, float):
107
+ type_info[var_name] = TYPE_FLOATING
108
+ elif issubclass(type_obj, str):
109
+ type_info[var_name] = TYPE_STRING
110
+ elif issubclass(type_obj, datetime):
111
+ type_info[var_name] = TYPE_DATE_TIME
112
+ elif numpy and issubclass(type_obj, numpy.datetime64):
113
+ type_info[var_name] = TYPE_DATE_TIME
114
+ elif numpy and issubclass(type_obj, numpy.timedelta64):
115
+ type_info[var_name] = TYPE_DATE_TIME
116
+ elif numpy and issubclass(type_obj, numpy.integer):
117
+ type_info[var_name] = TYPE_INTEGER
118
+ elif numpy and issubclass(type_obj, numpy.floating):
119
+ type_info[var_name] = TYPE_FLOATING
120
+ else:
121
+ type_info[var_name] = 'unknown(python:' + str(type_obj) + ')'
122
+
123
+ return type_info
lets_plot/plot/stat.py CHANGED
@@ -498,11 +498,10 @@ def stat_sum(mapping=None, *, data=None, geom=None, position=None, show_legend=N
498
498
  --------
499
499
  .. jupyter-execute::
500
500
  :linenos:
501
- :emphasize-lines: 10
501
+ :emphasize-lines: 9
502
502
 
503
503
  import numpy as np
504
504
  from lets_plot import *
505
- from lets_plot.mapping import as_discrete
506
505
  LetsPlot.setup_html()
507
506
  n = 50
508
507
  np.random.seed(42)
@@ -515,11 +514,10 @@ def stat_sum(mapping=None, *, data=None, geom=None, position=None, show_legend=N
515
514
 
516
515
  .. jupyter-execute::
517
516
  :linenos:
518
- :emphasize-lines: 10
517
+ :emphasize-lines: 9
519
518
 
520
519
  import numpy as np
521
520
  from lets_plot import *
522
- from lets_plot.mapping import as_discrete
523
521
  LetsPlot.setup_html()
524
522
  n = 50
525
523
  np.random.seed(42)
lets_plot/plot/theme_.py CHANGED
@@ -69,6 +69,9 @@ def theme(*,
69
69
  plot_margin=None,
70
70
  plot_inset=None,
71
71
 
72
+ plot_title_position=None,
73
+ plot_caption_position=None,
74
+
72
75
  strip_background=None, # ToDo: x/y
73
76
  strip_text=None, # ToDo: x/y
74
77
  # ToDo: strip.placement
@@ -232,6 +235,14 @@ def theme(*,
232
235
  - a list of four numbers - the insets are applied to the top, right, bottom and left in that order.
233
236
 
234
237
  It is acceptable to use None for any side; in this case, the default value for the plot inset side will be used.
238
+ plot_title_position : {'panel', 'plot'}, default='panel'
239
+ Alignment of the plot title/subtitle.
240
+ A value of 'panel' means that title and subtitle are aligned to the plot panels.
241
+ A value of 'plot' means that title and subtitle are aligned to the entire plot (excluding margins).
242
+ plot_caption_position : {'panel', 'plot'}, default='panel'
243
+ Alignment of the plot caption.
244
+ A value of 'panel' means that caption is aligned to the plot panels.
245
+ A value of 'plot' means that caption is aligned to the entire plot (excluding margins).
235
246
  strip_background : str or dict
236
247
  Background of facet labels.
237
248
  Set 'blank' or result of `element_blank()` to draw nothing.
lets_plot/plot/tooltip.py CHANGED
@@ -155,7 +155,7 @@ class layer_tooltips(FeatureSpec):
155
155
  - field='^X' - for all positional x,
156
156
  - field='^Y' - for all positional y.
157
157
 
158
- |
158
+ ----
159
159
 
160
160
  The string template in `format` will allow to change lines
161
161
  for the default tooltip without `line` specifying.
@@ -163,7 +163,7 @@ class layer_tooltips(FeatureSpec):
163
163
  Aes and var formats are not interchangeable, i.e. var format
164
164
  will not be applied to aes, mapped to this variable.
165
165
 
166
- |
166
+ ----
167
167
 
168
168
  For more info see https://lets-plot.org/python/pages/formats.html.
169
169
 
@@ -420,29 +420,29 @@ class layer_tooltips(FeatureSpec):
420
420
  The resulting string will be at the beginning of the general tooltip, centered and highlighted in bold.
421
421
  A long title can be split into multiple lines using `\\\\n` as a text separator.
422
422
 
423
- Examples
424
- --------
425
- .. jupyter-execute::
426
- :linenos:
427
- :emphasize-lines: 15
423
+ Examples
424
+ --------
425
+ .. jupyter-execute::
426
+ :linenos:
427
+ :emphasize-lines: 15
428
428
 
429
- import numpy as np
430
- from lets_plot import *
431
- LetsPlot.setup_html()
432
- n = 100
433
- np.random.seed(42)
434
- data = {
435
- 'id': np.arange(n),
436
- 'x': np.random.normal(size=n),
437
- 'y': np.random.normal(size=n),
438
- 'c': np.random.choice(['a', 'b'], size=n),
439
- 'w': np.random.randint(1, 11, size=n)
440
- }
441
- ggplot(data, aes('x', 'y')) + \\
442
- geom_point(aes(color='c', size='w'), show_legend=False, \\
443
- tooltips=layer_tooltips().title('@id')
444
- .line('color|@c')
445
- .line('size|@w'))
429
+ import numpy as np
430
+ from lets_plot import *
431
+ LetsPlot.setup_html()
432
+ n = 100
433
+ np.random.seed(42)
434
+ data = {
435
+ 'id': np.arange(n),
436
+ 'x': np.random.normal(size=n),
437
+ 'y': np.random.normal(size=n),
438
+ 'c': np.random.choice(['a', 'b'], size=n),
439
+ 'w': np.random.randint(1, 11, size=n)
440
+ }
441
+ ggplot(data, aes('x', 'y')) + \\
442
+ geom_point(aes(color='c', size='w'), show_legend=False, \\
443
+ tooltips=layer_tooltips().title('@id')
444
+ .line('color|@c')
445
+ .line('size|@w'))
446
446
 
447
447
  """
448
448
  self._tooltip_title = value
lets_plot/plot/util.py CHANGED
@@ -2,14 +2,13 @@
2
2
  # Copyright (c) 2019. JetBrains s.r.o.
3
3
  # Use of this source code is governed by the MIT license that can be found in the LICENSE file.
4
4
  #
5
- from collections.abc import Iterable
6
- from datetime import datetime
7
- from typing import Any, Tuple, Sequence, Optional, Dict
5
+ from typing import Any, Tuple, Sequence, Optional, Dict, List
8
6
 
9
- from lets_plot._type_utils import is_dict_or_dataframe, is_polars_dataframe
7
+ from lets_plot._type_utils import is_pandas_data_frame
10
8
  from lets_plot.geo_data_internals.utils import find_geo_names
11
9
  from lets_plot.mapping import MappingMeta
12
- from lets_plot.plot.core import aes
10
+ from lets_plot.plot.core import aes, FeatureSpec
11
+ from lets_plot.plot.series_meta import infer_type, TYPE_UNKNOWN
13
12
 
14
13
 
15
14
  def as_boolean(val, *, default):
@@ -19,104 +18,94 @@ def as_boolean(val, *, default):
19
18
  return bool(val) and val != 'False'
20
19
 
21
20
 
22
- def as_annotated_data(raw_data: Any, raw_mapping: Any) -> Tuple:
23
- data_meta = {}
21
+ def as_annotated_data(data: Any, mapping_spec: FeatureSpec) -> Tuple:
22
+ data_type_by_var: Dict[str, str] = {} # VarName to Type
23
+ mapping_meta_by_var: Dict[str, Dict[str, MappingMeta]] = {} # VarName to Dict[Aes, MappingMeta]
24
+ mappings = {} # Aes to VarName
24
25
 
25
- # data
26
- data = raw_data
27
-
28
- if is_data_pub_stream(data):
29
- data = {}
30
- for col_name in raw_data.col_names:
31
- data[col_name] = []
32
-
33
- data_meta.update({'pubsub': {'channel_id': raw_data.channel_id, 'col_names': raw_data.col_names}})
34
-
35
- # mapping
36
- mapping = {}
37
- mapping_meta = []
38
- # series annotations
39
- series_meta = []
40
-
41
- class VariableMeta:
42
- def __init__(self):
43
- self.levels = None
44
- self.aesthetics = []
45
- self.order = None
46
-
47
- variables_meta: Dict[str, VariableMeta] = {}
48
-
49
- if is_data_frame(data):
50
- dtypes = data.dtypes.to_dict().items()
51
- for column_name, dtype in dtypes:
52
- if dtype.name == 'category' and dtype.ordered:
53
- var_meta = VariableMeta()
54
- var_meta.levels = dtype.categories.to_list()
55
- variables_meta[column_name] = var_meta
56
-
57
- if raw_mapping is not None:
58
- for aesthetic, variable in raw_mapping.as_dict().items():
59
- if aesthetic == 'name': # ignore FeatureSpec.name property
26
+ # fill mapping_meta_by_var, mappings and data_type_by_var.
27
+ if mapping_spec is not None:
28
+ for key, spec in mapping_spec.props().items():
29
+ # key is either an aesthetic name or 'name' (FeatureSpec.name property)
30
+ if key == 'name': # ignore FeatureSpec.name property
60
31
  continue
61
-
62
- if isinstance(variable, MappingMeta):
63
- mapping[aesthetic] = variable.variable
64
- if variable.variable in variables_meta:
65
- var_meta = variables_meta[variable.variable]
66
- else:
67
- var_meta = VariableMeta()
68
- var_meta.aesthetics.append(aesthetic)
69
- if variable.levels is not None:
70
- var_meta.levels = variable.levels
71
- order = variable.parameters.get('order')
72
- if order is not None:
73
- var_meta.order = order
74
- variables_meta[variable.variable] = var_meta
32
+
33
+ if isinstance(spec, MappingMeta):
34
+ mappings[key] = spec.variable
35
+ mapping_meta_by_var.setdefault(spec.variable, {})[key] = spec
36
+ data_type_by_var[spec.variable] = TYPE_UNKNOWN
75
37
  else:
76
- mapping[aesthetic] = variable
77
-
78
- for variableName, settings in variables_meta.items():
79
- if settings.levels is not None:
80
- # series annotations
81
- series_meta.append({
82
- 'column': variableName,
83
- 'factor_levels': settings.levels,
84
- 'order': settings.order
85
- })
86
- else:
87
- # mapping annotations
88
- for aesthetic in settings.aesthetics:
89
- value = raw_mapping.as_dict().get(aesthetic)
90
- if value is not None and isinstance(value, MappingMeta):
91
- mapping_meta.append({
92
- 'aes': aesthetic,
93
- 'annotation': value.annotation,
94
- 'parameters': value.parameters
95
- })
96
-
97
- data_as_dict = None
98
- if is_dict_or_dataframe(data):
99
- data_as_dict = data
100
- elif is_polars_dataframe(data):
101
- data_as_dict = data.to_dict()
102
-
103
- if data_as_dict is not None:
104
- for column_name, values in data_as_dict.items():
105
- if isinstance(values, Iterable):
106
- not_empty_series = any(True for _ in values)
107
- if not_empty_series and all(isinstance(val, datetime) for val in values):
108
- series_meta.append({
109
- 'column': column_name,
110
- 'type': 'datetime'
111
- })
112
-
113
- if len(series_meta) > 0:
114
- data_meta.update({'series_annotations': series_meta})
115
-
116
- if len(mapping_meta) > 0:
117
- data_meta.update({'mapping_annotations': mapping_meta})
118
-
119
- return data, aes(**mapping), {'data_meta': data_meta}
38
+ mappings[key] = spec # spec is a variable name
39
+
40
+ data_type_by_var.update(infer_type(data))
41
+
42
+ # fill series annotations
43
+ series_annotations = {} # var to series_annotation
44
+ for var_name, data_type in data_type_by_var.items():
45
+ series_annotation = {}
46
+
47
+ if data_type != TYPE_UNKNOWN:
48
+ series_annotation['type'] = data_type
49
+
50
+ if is_pandas_data_frame(data) and data[var_name].dtype.name == 'category' and data[var_name].dtype.ordered:
51
+ series_annotation['factor_levels'] = data[var_name].cat.categories.to_list()
52
+ elif var_name in mapping_meta_by_var:
53
+ levels = last_not_none(list(map(lambda mm: mm.levels, mapping_meta_by_var[var_name].values())))
54
+ if levels is not None:
55
+ series_annotation['factor_levels'] = levels
56
+
57
+ if 'factor_levels' in series_annotation and var_name in mapping_meta_by_var:
58
+ order = last_not_none(list(map(lambda mm: mm.parameters['order'], mapping_meta_by_var[var_name].values())))
59
+ if order is not None:
60
+ series_annotation['order'] = order
61
+
62
+ if len(series_annotation) > 0:
63
+ series_annotation['column'] = var_name
64
+ series_annotations[var_name] = series_annotation
65
+
66
+ # fill mapping annotations
67
+ mapping_annotations = []
68
+ for var_name, meta_data in mapping_meta_by_var.items():
69
+ for aesthetic, mapping_meta in meta_data.items():
70
+ if mapping_meta.annotation == 'as_discrete':
71
+ if 'factor_levels' in series_annotations.get(var_name, {}):
72
+ # there is a bug - if label is set then levels are not applied
73
+ continue
74
+
75
+ mapping_annotation = {}
76
+
77
+ # Note that the label is always set; otherwise, the scale title will appear as 'color.cyl'
78
+ label = mapping_meta.parameters.get('label')
79
+ if label is not None:
80
+ mapping_annotation.setdefault('parameters', {})['label'] = label
81
+
82
+ if mapping_meta.levels is not None:
83
+ mapping_annotation['levels'] = mapping_meta.levels
84
+
85
+ order_by = mapping_meta.parameters.get('order_by')
86
+ if order_by is not None:
87
+ mapping_annotation.setdefault('parameters', {})['order_by'] = order_by
88
+
89
+ order = mapping_meta.parameters.get('order')
90
+ if order is not None:
91
+ mapping_annotation.setdefault('parameters', {})['order'] = order
92
+
93
+ # add mapping meta if custom label is set or if series annotation for var doesn't contain order options
94
+ # otherwise don't add mapping meta - it's redundant, nothing unique compared to series annotation
95
+ if len(mapping_annotation):
96
+ mapping_annotation['aes'] = aesthetic
97
+ mapping_annotation['annotation'] = 'as_discrete'
98
+ mapping_annotations.append(mapping_annotation)
99
+
100
+ data_meta = {}
101
+
102
+ if len(series_annotations) > 0:
103
+ data_meta.update({'series_annotations': list(series_annotations.values())})
104
+
105
+ if len(mapping_annotations) > 0:
106
+ data_meta.update({'mapping_annotations': mapping_annotations})
107
+
108
+ return data, aes(**mappings), {'data_meta': data_meta}
120
109
 
121
110
 
122
111
  def is_data_pub_stream(data: Any) -> bool:
@@ -147,7 +136,8 @@ def normalize_map_join(map_join):
147
136
  data_names = [map_join[0]]
148
137
  map_names = [map_join[1]]
149
138
  elif len(map_join) > 2: # ['foo', 'bar', 'baz'] -> error
150
- raise ValueError("map_join of type list[str] expected to have 1 or 2 items, but was {}".format(len(map_join)))
139
+ raise ValueError(
140
+ "map_join of type list[str] expected to have 1 or 2 items, but was {}".format(len(map_join)))
151
141
  else:
152
142
  raise invalid_map_join_format()
153
143
  elif all(isinstance(v, Sequence) and not isinstance(v, str) for v in map_join): # all items are lists
@@ -217,17 +207,20 @@ def geo_data_frame_to_crs(gdf: 'GeoDataFrame', use_crs: Optional[str]):
217
207
  return gdf.to_crs('EPSG:4326' if use_crs is None else use_crs)
218
208
 
219
209
 
220
- def is_ndarray(data) -> bool:
221
- try:
222
- from numpy import ndarray
223
- return isinstance(data, ndarray)
224
- except ImportError:
225
- return False
210
+ def key_int2str(data):
211
+ if is_pandas_data_frame(data):
212
+ if data.columns.inferred_type == 'integer' or data.columns.inferred_type == 'mixed-integer':
213
+ data.columns = data.columns.astype(str)
214
+ return data
226
215
 
216
+ if isinstance(data, dict):
217
+ return {(str(k) if isinstance(k, int) else k): v for k, v in data.items()}
227
218
 
228
- def is_data_frame(data: Any) -> bool:
229
- try:
230
- from pandas import DataFrame
231
- return isinstance(data, DataFrame)
232
- except ImportError:
233
- return False
219
+ return data
220
+
221
+
222
+ def last_not_none(lst: List) -> Optional[Any]:
223
+ for i in reversed(lst):
224
+ if i is not None:
225
+ return i
226
+ return None
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: lets-plot
3
- Version: 4.3.3
3
+ Version: 4.4.0rc1
4
4
  Summary: An open source library for statistical plotting
5
5
  Home-page: https://lets-plot.org
6
6
  Author: JetBrains
@@ -1,19 +1,20 @@
1
- lets_plot_kotlin_bridge.cp310-win_amd64.pyd,sha256=V6IQlWhq1zxtkY_GWcdY4_u0RPqVo3qXAnI01IVPZS4,5346816
2
- lets_plot/__init__.py,sha256=aaaS4jkaC4cpt6YJgGquWnGyr-HarKSaVNJEX06mzVE,11426
1
+ lets_plot_kotlin_bridge.cp310-win_amd64.pyd,sha256=QMaNf06qYyE4cc5FUGJgQ3Cge3FNv0HLLYsosFJHZNI,6324736
2
+ lets_plot/__init__.py,sha256=JOsBQOnuJgUW3em6hRCx1bzQg9uOiTIhaAJmpJNJEwY,11480
3
3
  lets_plot/_global_settings.py,sha256=dozwVWl2_Sg_-sWC08IYqVBhg4PCDAxHBERvD_XoWJU,7631
4
4
  lets_plot/_kbridge.py,sha256=LCmRSeFeLFoESoVsm72QuZGFKDsRMMoN0lQF01xju1g,1250
5
- lets_plot/_type_utils.py,sha256=p2xeyF16AH36aJRmijb4k8qOd_7D8JaM5g4AsbNV1v4,2603
6
- lets_plot/_version.py,sha256=7acM7Es733uDgQOaw464yFHBU_j9Z0zeXUl_llIa5kQ,239
7
- lets_plot/mapping.py,sha256=rp5dPbL-mBesbJix7uhJxSmABSXr3F1W2Rqw5cAr3J8,3866
5
+ lets_plot/_type_utils.py,sha256=ZO7os2Va772U2pJSkTA3OwDylN1QtXZo5y_EZpiWMdI,2789
6
+ lets_plot/_version.py,sha256=hpNRWDoTIbOQ_gh0KysEjir69e7rMM_M3YkDqT1BFjM,242
7
+ lets_plot/mapping.py,sha256=vWWGrVgzgo1u3R8djyshSoOEuaqlqSQpEVeQNqeKWk0,3691
8
8
  lets_plot/settings_utils.py,sha256=vKrsXMuJHR88ZZhPtQFAC-xrWKCpCPiRetfx1GpBGKU,8678
9
9
  lets_plot/tilesets.py,sha256=8LC_GsrZd1X12rII28W1XbO7A8YfeG1AjBR8L_PPFVk,10810
10
- lets_plot/bistro/__init__.py,sha256=86vF5HEz0Sqjuv2ZVF7uRap3dDswh8zRY2xhGxqDwvI,384
10
+ lets_plot/bistro/__init__.py,sha256=0vjEBjuS3r4MR8ugQ1zIo1sks6K0ljSESJWH3pQcgYI,442
11
11
  lets_plot/bistro/_plot2d_common.py,sha256=E6a2QghFF8CWwUzT-iCtgqYBepCCPuwUyxcDM8BJkL8,3712
12
- lets_plot/bistro/corr.py,sha256=mX4n-7osAPbP0X4OatRiJPU_qujNWkWeGaWB_wCL4hQ,12994
13
- lets_plot/bistro/im.py,sha256=sDaZ5gJl5wOcHPz7dzBlmGMFLhgu6XTDK2xOlMFsUHI,5652
12
+ lets_plot/bistro/corr.py,sha256=GqBCneSccF8GBkJgkedpnUdIhXvmJ5Blhtej0qhKRrs,13015
13
+ lets_plot/bistro/im.py,sha256=HDpoNcqzYQrFfw40qAQQ8CvD0lQPzpNWkF93UrjLYjQ,5654
14
14
  lets_plot/bistro/joint.py,sha256=bnr4Q-kyfgSoDnplpBq9jXi2XVpBEfcA0cZRVSZM3gU,6455
15
15
  lets_plot/bistro/qq.py,sha256=LP5TSI7XZlUlPoJ92mAsFJl7Mnk5VQewqdcWXl1iAR4,6588
16
- lets_plot/bistro/residual.py,sha256=Bgk1izposgHE5gaNNpzjdDIwXDd-ygjFa6S7AyhZpKA,12196
16
+ lets_plot/bistro/residual.py,sha256=QTKvMqSl7NoRQRTe85C36XyKBozyh9g6dNaMMMXG320,12357
17
+ lets_plot/bistro/waterfall.py,sha256=JD4wtHV0aFqOMp5oPZz87GJ2eWFwwGnZcnPqje7ApAU,9957
17
18
  lets_plot/export/__init__.py,sha256=JloMKV4OAMgxBuYg8ObByZ3LJvqcUKed1G286WLA85E,194
18
19
  lets_plot/export/ggsave_.py,sha256=BjpQ7eX_lDLPJpyeDr_G5zzPtUWVebvSoSLb-72xBPs,4001
19
20
  lets_plot/frontend_context/__init__.py,sha256=LALJE-5rVdEcgCP-sWTwNAVoVZB-Pr2lG8CpVn04FrY,212
@@ -33,7 +34,7 @@ lets_plot/geo_data/core.py,sha256=8Kxp8hbMRJVItR-N3T_7Ml5TOIpCkYMUGb0vsfy9hUM,96
33
34
  lets_plot/geo_data/geocoder.py,sha256=6clN2-uJN95YcMpKNUC4aLmegAJhRvMLsSc1TusgH3Q,34690
34
35
  lets_plot/geo_data/geocodes.py,sha256=yuxj1FqhVCG0Vc3kUuxd21ShmL9WAtsu6tnmhackld4,18373
35
36
  lets_plot/geo_data/livemap_helper.py,sha256=4169J6yeo3nftw3ynjPuUfCtrgw55a1mX7NxvNaLZo0,2150
36
- lets_plot/geo_data/to_geo_data_frame.py,sha256=WoYHpKrpfP-TDKxv-XYDm275AsVwcpLN7Z-mRIIu8R4,5371
37
+ lets_plot/geo_data/to_geo_data_frame.py,sha256=abVrGs6naP2hhJ6F2I0SodX82101pgkekV4pGM7BRJ8,5462
37
38
  lets_plot/geo_data/type_assertion.py,sha256=9TThxe0Ojva6UH8MG_tGsIudKyIdRXmKJscNmBUULBc,809
38
39
  lets_plot/geo_data/gis/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
39
40
  lets_plot/geo_data/gis/fluent_dict.py,sha256=qLzgPgancRe336CZUvXIpM96DRsBXvn3iVh6VvO7hwY,7231
@@ -46,39 +47,42 @@ lets_plot/geo_data/gis/response.py,sha256=MsAk10JQe0XC-h4Cv0w7uzYxAtlx3YaSrqYXA6
46
47
  lets_plot/geo_data_internals/__init__.py,sha256=ZwcoMdyQ_k9589f2D3nXXjedJpyiDR8WyqaghTh_EVQ,238
47
48
  lets_plot/geo_data_internals/constants.py,sha256=2dViytUZPiojilhWV3UWzBAXgdHl5OoIJsNMsI0V7yU,441
48
49
  lets_plot/geo_data_internals/utils.py,sha256=8vfDa99yq1YpVNr-RDtpCJfbrON04rIG6cugpQXnJlU,1000
49
- lets_plot/package_data/lets-plot.min.js,sha256=FM6flPAdkadKyzlthezhTgE82RF1QS6kCJJndaE0F9k,2091600
50
- lets_plot/plot/__init__.py,sha256=XB20oTHOgYoW-TMe6pueeL_Cg6jjD63yvVoqX-_QVSw,1585
50
+ lets_plot/package_data/lets-plot.min.js,sha256=VnxMHXgaCkf5bPIh1L0H-eU309SES04CZYZa4LTW0Ao,2155683
51
+ lets_plot/plot/__init__.py,sha256=bXUtxpS8UXqYn1uYIwdTY2a2koxJMjcCOdG4iUxutMM,1711
51
52
  lets_plot/plot/_global_theme.py,sha256=eatwhJiiqnY6mrNW0Y1NMco2e7xxldhItgj1IOkhRuI,311
52
- lets_plot/plot/annotation.py,sha256=Egf9TweEsHWnWYF8nJYP8InrzMx2jnD7nGzeUcc8rRU,7964
53
- lets_plot/plot/coord.py,sha256=SuJfqejmlkAgJUNfNYN-t7jlQUNWaqon3vVgLSB9nBo,8269
54
- lets_plot/plot/core.py,sha256=BCcbuX8qnB2RpwhBkDiA7mSaLt6iy6_M_9Frw307soo,31999
53
+ lets_plot/plot/annotation.py,sha256=D6XKD85xQ6YqhedS8geHCWun_5xJZWOxyfFjeCo_6tU,7873
54
+ lets_plot/plot/coord.py,sha256=B4EEt6mqPERbYVwzl3VPkEym9hq_tO0LNtgdtluWQBQ,8218
55
+ lets_plot/plot/core.py,sha256=2LVaCx2wvJ6tSys0UW_fpgdb6V8uBF3Sg6sTPa_lC6E,32185
55
56
  lets_plot/plot/facet.py,sha256=sybZ5dpXOpLlG9KrX2LRSeeoVgX8xL22-hToR-YnHy8,7034
56
57
  lets_plot/plot/font_features.py,sha256=OInyzUmRbujBEeB2gxuD2O249-5htOQZi2Y_fujxpVY,2309
57
- lets_plot/plot/geom.py,sha256=_yUxF5QCdqtCcDg7Lii3QWgUUqZngk4IeiVIyhbB_JM,304188
58
+ lets_plot/plot/geom.py,sha256=m6BPCXIGNkxkQgzAeXVntCTMTzdz4UTdKoLJqfoGD9g,321342
58
59
  lets_plot/plot/geom_extras.py,sha256=yJ9T5hAQWnhV-KwW-a55qbDOOrLF1D28VZsHpC4aC34,1747
59
- lets_plot/plot/geom_function_.py,sha256=h11KorDJvWOUOofggY9fEFSvTKeNvqiUF3DtIIL5eDs,7199
60
- lets_plot/plot/geom_imshow_.py,sha256=pafKGgetTRkpEGycP7dW1ThXFTCrlAmSgk6kgymoC-0,15124
61
- lets_plot/plot/geom_livemap_.py,sha256=zEUrR4PE5-WrQXdPKD_o2VVUhiKMVAFAqu-atpbmrmg,11983
60
+ lets_plot/plot/geom_function_.py,sha256=EvCp_kGeY1zbZMnlp-_WnjJioLQA9YX-aOMFlv8A0zg,7458
61
+ lets_plot/plot/geom_imshow_.py,sha256=vj6Z9U-1VWsi8Q7G-X5MtwW9KTdMFbyr25wX3CTjODg,15132
62
+ lets_plot/plot/geom_livemap_.py,sha256=X_zYxbRFQAxmGYGTWF8cemEY-eDIXSHBTvuTeWs2Yu4,12115
62
63
  lets_plot/plot/gggrid_.py,sha256=EVx2zhlYmej8qXtdlhUzcCS6zTdbsjj3Nl5IwAD4hTI,4608
63
- lets_plot/plot/guide.py,sha256=FuRiKhcPG1-rjU62t_5H_NEhhCjhQkkKXDAdaYaPVZs,3949
64
- lets_plot/plot/label.py,sha256=vyPxpkXhC979_wHn2oWfhkZXw3bGfqdX910jzEPuW9U,3987
65
- lets_plot/plot/marginal_layer.py,sha256=9oJMGfYTOh98TmEctxNP1ouFTPt-_VdI571n9-JXc5o,6589
66
- lets_plot/plot/plot.py,sha256=L_cOYgYWce25B6_yVQE2FdHQ1SgJ8x7NZ9HfpATHhPI,8057
64
+ lets_plot/plot/ggtb_.py,sha256=lxt-e8iNXvNRBoENybRC_JY_bcGswfw8pSWhKedVkCw,266
65
+ lets_plot/plot/guide.py,sha256=iqdBgvtbTjzsTNJWmqfg7En9k-6EnMyBxbK5O6Y_8-w,6436
66
+ lets_plot/plot/label.py,sha256=xcqoGNARcYgSZHdA1h2EGUhJwtzBOax9nUOsz4CLhRQ,4736
67
+ lets_plot/plot/marginal_layer.py,sha256=auDAO5IiRpJVcqzqr31SnXJz7sQGIVbndx__qfr7JyY,6538
68
+ lets_plot/plot/plot.py,sha256=mS2vIt7tV1jUJI2atmerA6t1yCxGF2QqqugEqgUQPWo,8102
67
69
  lets_plot/plot/pos.py,sha256=NxnuE--5hwQCWOEqnoQu8TFppZYXJG5m2cgWkPjmXIg,10703
68
70
  lets_plot/plot/sampling.py,sha256=_f5kHZzTqrFRJhllMNeAhcPgHlKH7ZnZlLncC9C6yVI,8365
69
71
  lets_plot/plot/sandbox_.py,sha256=5wp2bkIBsihw9aIoKr8FUQZmtZbInHPCULbG5uPsMYE,571
70
72
  lets_plot/plot/scale.py,sha256=O-b5LJhrLW_3TtbUO3qiaC0vYTHLH-0w7dMrREFF9h4,138936
73
+ lets_plot/plot/scale_colormap_mpl.py,sha256=AoQ_oAcxbH6OMecUc_gvwJsqhJM52of435YIb-MP7lg,10428
71
74
  lets_plot/plot/scale_convenience.py,sha256=UOXX07wP5aARYwsOZ-6rK_RR0szhdhnThPvia6LOqrE,4271
72
75
  lets_plot/plot/scale_identity_.py,sha256=rMuiaI1wRleP_w8ExvaydlcWeznVJ60M-wzI2SPH7pY,24395
73
76
  lets_plot/plot/scale_position.py,sha256=ntpPRO8PA46hGuL9GMcqq18rXqaX1hJF91cHIHxw998,47383
74
- lets_plot/plot/stat.py,sha256=V8ye45Yl9D886h5G3sWcv-1U4btrFWVf68Ude1v37d8,21863
77
+ lets_plot/plot/series_meta.py,sha256=Nh-Vcq-zcg_oN4wdoHZxn6aKuScH3_5mVJ4D8LhbO3A,5621
78
+ lets_plot/plot/stat.py,sha256=HRumeeUrZNl8D_JWcukYAil87Uk2_94FcgGnYivkH6Q,21759
75
79
  lets_plot/plot/subplots.py,sha256=vKW3BHI5YRM5CGAs_CCQ9bhu5oWqW0Oh1m6b-bClSUA,11620
76
- lets_plot/plot/theme_.py,sha256=MFgySry4efMdOLAx0ZKosvSMp1q1Pemdja2Bgi4-gps,23631
80
+ lets_plot/plot/theme_.py,sha256=wrwRPMyQUfnAqnkLpV1LYX0vawXI47aECuH6WBzLJZA,24296
77
81
  lets_plot/plot/theme_set.py,sha256=KLQSAihJU8_FmAU0at8WUAtgnIqCvU2Rd5awNhTZimo,9496
78
- lets_plot/plot/tooltip.py,sha256=Vo9JCLQRSoiDFGVU6YBR9OxAfWZW_pxYdAa7v7S-Ydk,16354
79
- lets_plot/plot/util.py,sha256=RU7zYrFXSgdZzjMf6LHc6zkXrrTFb8g8CoDfznqn7qA,7950
80
- lets_plot-4.3.3.dist-info/LICENSE,sha256=D7RdUBHyt0ua4vSZs8H7-HIcliPTSk9zY3sNzx8fejY,1087
81
- lets_plot-4.3.3.dist-info/METADATA,sha256=OA4wi8QOJG6O-pOam71wvydlgNlMn3tekbZrgfMUsHU,11572
82
- lets_plot-4.3.3.dist-info/WHEEL,sha256=lO6CqtLHCAi38X3Es1a4R1lAjZFvN010IMRCFo2S7Mc,102
83
- lets_plot-4.3.3.dist-info/top_level.txt,sha256=ID-ORXUWN-oVZmD4YFy1rQVm2QT1D-MlGON3vdxqgpY,34
84
- lets_plot-4.3.3.dist-info/RECORD,,
82
+ lets_plot/plot/tooltip.py,sha256=PTjUh-CwXmKrb36pNWT2re0K1mZ9kvWwdt4GhhF7VTY,16448
83
+ lets_plot/plot/util.py,sha256=w5PWWPPG_b3g8z9yxfodsd38Csu-qg6z_Zgmzbavsn0,8812
84
+ lets_plot-4.4.0rc1.dist-info/LICENSE,sha256=D7RdUBHyt0ua4vSZs8H7-HIcliPTSk9zY3sNzx8fejY,1087
85
+ lets_plot-4.4.0rc1.dist-info/METADATA,sha256=6z1XJzxwz0ll6kfqSHEQO8S5V0OxWtXIjYs1GOfrk4g,11575
86
+ lets_plot-4.4.0rc1.dist-info/WHEEL,sha256=fsW6--WFfuzX2scefE6JfcSZ5dXg5h59u8lqlpL5uuo,101
87
+ lets_plot-4.4.0rc1.dist-info/top_level.txt,sha256=ID-ORXUWN-oVZmD4YFy1rQVm2QT1D-MlGON3vdxqgpY,34
88
+ lets_plot-4.4.0rc1.dist-info/RECORD,,
@@ -1,5 +1,5 @@
1
1
  Wheel-Version: 1.0
2
- Generator: bdist_wheel (0.43.0)
2
+ Generator: setuptools (72.1.0)
3
3
  Root-Is-Purelib: false
4
4
  Tag: cp310-cp310-win_amd64
5
5
 
Binary file