lets-plot 4.8.1rc1__cp311-cp311-manylinux2014_x86_64.manylinux_2_17_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.
- lets_plot/__init__.py +382 -0
- lets_plot/_global_settings.py +192 -0
- lets_plot/_kbridge.py +197 -0
- lets_plot/_type_utils.py +133 -0
- lets_plot/_version.py +6 -0
- lets_plot/bistro/__init__.py +16 -0
- lets_plot/bistro/_plot2d_common.py +106 -0
- lets_plot/bistro/corr.py +448 -0
- lets_plot/bistro/im.py +196 -0
- lets_plot/bistro/joint.py +192 -0
- lets_plot/bistro/qq.py +207 -0
- lets_plot/bistro/residual.py +341 -0
- lets_plot/bistro/waterfall.py +332 -0
- lets_plot/export/__init__.py +6 -0
- lets_plot/export/ggsave_.py +172 -0
- lets_plot/frontend_context/__init__.py +8 -0
- lets_plot/frontend_context/_configuration.py +140 -0
- lets_plot/frontend_context/_dynamic_configure_html.py +115 -0
- lets_plot/frontend_context/_frontend_ctx.py +16 -0
- lets_plot/frontend_context/_html_contexts.py +223 -0
- lets_plot/frontend_context/_intellij_python_json_ctx.py +38 -0
- lets_plot/frontend_context/_isolated_webview_panel_ctx.py +81 -0
- lets_plot/frontend_context/_json_contexts.py +39 -0
- lets_plot/frontend_context/_jupyter_notebook_ctx.py +82 -0
- lets_plot/frontend_context/_mime_types.py +7 -0
- lets_plot/frontend_context/_static_html_page_ctx.py +76 -0
- lets_plot/frontend_context/_static_svg_ctx.py +26 -0
- lets_plot/frontend_context/_webbr_html_page_ctx.py +29 -0
- lets_plot/frontend_context/sandbox.py +5 -0
- lets_plot/geo_data/__init__.py +19 -0
- lets_plot/geo_data/core.py +335 -0
- lets_plot/geo_data/geocoder.py +988 -0
- lets_plot/geo_data/geocodes.py +512 -0
- lets_plot/geo_data/gis/__init__.py +0 -0
- lets_plot/geo_data/gis/fluent_dict.py +201 -0
- lets_plot/geo_data/gis/geocoding_service.py +42 -0
- lets_plot/geo_data/gis/geometry.py +91 -0
- lets_plot/geo_data/gis/json_request.py +232 -0
- lets_plot/geo_data/gis/json_response.py +308 -0
- lets_plot/geo_data/gis/request.py +492 -0
- lets_plot/geo_data/gis/response.py +247 -0
- lets_plot/geo_data/livemap_helper.py +65 -0
- lets_plot/geo_data/to_geo_data_frame.py +141 -0
- lets_plot/geo_data/type_assertion.py +34 -0
- lets_plot/geo_data_internals/__init__.py +4 -0
- lets_plot/geo_data_internals/constants.py +13 -0
- lets_plot/geo_data_internals/utils.py +33 -0
- lets_plot/mapping.py +115 -0
- lets_plot/package_data/lets-plot.min.js +3 -0
- lets_plot/plot/__init__.py +64 -0
- lets_plot/plot/_global_theme.py +14 -0
- lets_plot/plot/annotation.py +290 -0
- lets_plot/plot/coord.py +242 -0
- lets_plot/plot/core.py +1071 -0
- lets_plot/plot/expand_limits_.py +78 -0
- lets_plot/plot/facet.py +210 -0
- lets_plot/plot/font_features.py +71 -0
- lets_plot/plot/geom.py +9146 -0
- lets_plot/plot/geom_extras.py +53 -0
- lets_plot/plot/geom_function_.py +219 -0
- lets_plot/plot/geom_imshow_.py +393 -0
- lets_plot/plot/geom_livemap_.py +343 -0
- lets_plot/plot/ggbunch_.py +96 -0
- lets_plot/plot/gggrid_.py +139 -0
- lets_plot/plot/ggtb_.py +81 -0
- lets_plot/plot/guide.py +231 -0
- lets_plot/plot/label.py +187 -0
- lets_plot/plot/marginal_layer.py +181 -0
- lets_plot/plot/plot.py +245 -0
- lets_plot/plot/pos.py +344 -0
- lets_plot/plot/sampling.py +338 -0
- lets_plot/plot/sandbox_.py +26 -0
- lets_plot/plot/scale.py +3580 -0
- lets_plot/plot/scale_colormap_mpl.py +300 -0
- lets_plot/plot/scale_convenience.py +155 -0
- lets_plot/plot/scale_identity_.py +653 -0
- lets_plot/plot/scale_position.py +1342 -0
- lets_plot/plot/series_meta.py +209 -0
- lets_plot/plot/stat.py +585 -0
- lets_plot/plot/subplots.py +331 -0
- lets_plot/plot/subplots_util.py +24 -0
- lets_plot/plot/theme_.py +790 -0
- lets_plot/plot/theme_set.py +418 -0
- lets_plot/plot/tooltip.py +486 -0
- lets_plot/plot/util.py +267 -0
- lets_plot/settings_utils.py +244 -0
- lets_plot/tilesets.py +429 -0
- lets_plot-4.8.1rc1.dist-info/METADATA +221 -0
- lets_plot-4.8.1rc1.dist-info/RECORD +97 -0
- lets_plot-4.8.1rc1.dist-info/WHEEL +6 -0
- lets_plot-4.8.1rc1.dist-info/licenses/LICENSE +21 -0
- lets_plot-4.8.1rc1.dist-info/licenses/licenses/LICENSE.FreeType +166 -0
- lets_plot-4.8.1rc1.dist-info/licenses/licenses/LICENSE.ImageMagick +106 -0
- lets_plot-4.8.1rc1.dist-info/licenses/licenses/LICENSE.expat +21 -0
- lets_plot-4.8.1rc1.dist-info/licenses/licenses/LICENSE.fontconfig +200 -0
- lets_plot-4.8.1rc1.dist-info/top_level.txt +2 -0
- lets_plot_kotlin_bridge.cpython-311-x86_64-linux-gnu.so +0 -0
lets_plot/_kbridge.py
ADDED
|
@@ -0,0 +1,197 @@
|
|
|
1
|
+
# Copyright (c) 2020. 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
|
+
# noinspection PyUnresolvedReferences
|
|
5
|
+
from typing import Dict
|
|
6
|
+
|
|
7
|
+
import lets_plot_kotlin_bridge
|
|
8
|
+
|
|
9
|
+
from ._global_settings import get_js_cdn_url
|
|
10
|
+
from ._type_utils import standardize_dict
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
def _generate_dynamic_display_html(plot_spec: Dict) -> str:
|
|
14
|
+
plot_spec = _standardize_plot_spec(plot_spec)
|
|
15
|
+
# Old implementation (deprecated):
|
|
16
|
+
# return lets_plot_kotlin_bridge.generate_html(plot_spec)
|
|
17
|
+
|
|
18
|
+
# New implementation using get_display_html_for_raw_spec with default parameters
|
|
19
|
+
return lets_plot_kotlin_bridge.get_display_html_for_raw_spec(
|
|
20
|
+
plot_spec,
|
|
21
|
+
{}, # empty sizing_options -> defaults to notebookCell sizing (MIN width, SCALED height)
|
|
22
|
+
True, # dynamic_script_loading
|
|
23
|
+
False, # force_immediate_render
|
|
24
|
+
False # responsive
|
|
25
|
+
)
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
def _generate_svg(plot_spec: Dict, w: float = None, h: float = None, unit: str = None, use_css_pixelated_image_rendering: bool=True) -> str:
|
|
29
|
+
plot_spec = _standardize_plot_spec(plot_spec)
|
|
30
|
+
w = -1.0 if w is None else float(w)
|
|
31
|
+
h = -1.0 if h is None else float(h)
|
|
32
|
+
unit = '' if unit is None else str(unit) # None is not a valid value for str type - PyArg_ParseTuple will fail
|
|
33
|
+
return lets_plot_kotlin_bridge.export_svg(plot_spec, w, h, unit, use_css_pixelated_image_rendering)
|
|
34
|
+
|
|
35
|
+
def _generate_png(bytestring: Dict, output_width: float, output_height: float, unit: str, dpi: int, scale: float) -> str:
|
|
36
|
+
"""
|
|
37
|
+
Export a plot to PNG format. Returns base64 encoded string of the PNG image.
|
|
38
|
+
"""
|
|
39
|
+
plot_spec = _standardize_plot_spec(bytestring)
|
|
40
|
+
output_width = -1.0 if output_width is None else float(output_width)
|
|
41
|
+
output_height = -1.0 if output_height is None else float(output_height)
|
|
42
|
+
unit = '' if unit is None else str(unit) # None is not a valid value for str type - PyArg_ParseTuple will fail
|
|
43
|
+
dpi = -1 if dpi is None else int(dpi)
|
|
44
|
+
scale = -1.0 if scale is None else float(scale)
|
|
45
|
+
return lets_plot_kotlin_bridge.export_png(plot_spec, output_width, output_height, unit, dpi, scale)
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
def _generate_mvg(bytestring: Dict, output_width: float, output_height: float, unit: str, dpi: int, scale: float) -> str:
|
|
49
|
+
"""
|
|
50
|
+
Export a plot to MVG format. For internal use.
|
|
51
|
+
"""
|
|
52
|
+
plot_spec = _standardize_plot_spec(bytestring)
|
|
53
|
+
output_width = -1.0 if output_width is None else float(output_width)
|
|
54
|
+
output_height = -1.0 if output_height is None else float(output_height)
|
|
55
|
+
unit = '' if unit is None else str(unit) # None is not a valid value for str type - PyArg_ParseTuple will fail
|
|
56
|
+
dpi = -1 if dpi is None else int(dpi)
|
|
57
|
+
scale = -1.0 if scale is None else float(scale)
|
|
58
|
+
return lets_plot_kotlin_bridge.export_mvg(plot_spec, output_width, output_height, unit, dpi, scale)
|
|
59
|
+
|
|
60
|
+
|
|
61
|
+
def _generate_static_html_page(plot_spec: Dict, iframe: bool) -> str:
|
|
62
|
+
plot_spec = _standardize_plot_spec(plot_spec)
|
|
63
|
+
scriptUrl = get_js_cdn_url()
|
|
64
|
+
return lets_plot_kotlin_bridge.export_html(plot_spec, scriptUrl, iframe)
|
|
65
|
+
|
|
66
|
+
|
|
67
|
+
def _generate_static_html_page_for_raw_spec(
|
|
68
|
+
plot_spec: Dict,
|
|
69
|
+
sizing_options: Dict,
|
|
70
|
+
dynamic_script_loading: bool = False,
|
|
71
|
+
force_immediate_render: bool = False,
|
|
72
|
+
responsive: bool = False,
|
|
73
|
+
height100pct: bool = False
|
|
74
|
+
) -> str:
|
|
75
|
+
plot_spec = _standardize_plot_spec(plot_spec)
|
|
76
|
+
sizing_options = standardize_dict(sizing_options)
|
|
77
|
+
scriptUrl = get_js_cdn_url()
|
|
78
|
+
return lets_plot_kotlin_bridge.get_static_html_page_for_raw_spec(
|
|
79
|
+
plot_spec,
|
|
80
|
+
scriptUrl,
|
|
81
|
+
sizing_options,
|
|
82
|
+
dynamic_script_loading,
|
|
83
|
+
force_immediate_render,
|
|
84
|
+
responsive,
|
|
85
|
+
height100pct
|
|
86
|
+
)
|
|
87
|
+
|
|
88
|
+
|
|
89
|
+
def _standardize_plot_spec(plot_spec: Dict) -> Dict:
|
|
90
|
+
"""
|
|
91
|
+
:param plot_spec: dict
|
|
92
|
+
"""
|
|
93
|
+
if not isinstance(plot_spec, dict):
|
|
94
|
+
raise ValueError("dict expected but was {}".format(type(plot_spec)))
|
|
95
|
+
|
|
96
|
+
return standardize_dict(plot_spec)
|
|
97
|
+
|
|
98
|
+
|
|
99
|
+
def _generate_static_configure_html() -> str:
|
|
100
|
+
"""
|
|
101
|
+
Generate static HTML configuration.
|
|
102
|
+
|
|
103
|
+
Returns
|
|
104
|
+
-------
|
|
105
|
+
str
|
|
106
|
+
HTML string containing the static configuration with the script URL from global settings.
|
|
107
|
+
"""
|
|
108
|
+
scriptUrl = get_js_cdn_url()
|
|
109
|
+
return lets_plot_kotlin_bridge.get_static_configure_html(scriptUrl)
|
|
110
|
+
|
|
111
|
+
|
|
112
|
+
def _generate_display_html_for_raw_spec(
|
|
113
|
+
plot_spec: Dict,
|
|
114
|
+
sizing_options: Dict,
|
|
115
|
+
*,
|
|
116
|
+
dynamic_script_loading: bool = False,
|
|
117
|
+
force_immediate_render: bool = False,
|
|
118
|
+
responsive: bool = False,
|
|
119
|
+
height100pct: bool = False
|
|
120
|
+
) -> str:
|
|
121
|
+
"""
|
|
122
|
+
Generate HTML for displaying a plot from 'raw' specification (not processed by plot backend)
|
|
123
|
+
with customizable options.
|
|
124
|
+
|
|
125
|
+
Parameters
|
|
126
|
+
----------
|
|
127
|
+
plot_spec : Dict
|
|
128
|
+
Dict containing the plot specification.
|
|
129
|
+
sizing_options : Dict
|
|
130
|
+
Dict containing sizing policy options (width_mode, height_mode, width, height).
|
|
131
|
+
dynamic_script_loading : bool, default=False
|
|
132
|
+
Controls how the generated JS code interacts with the lets-plot.js library.
|
|
133
|
+
If True, assumes the library loads dynamically (asynchronously).
|
|
134
|
+
If False, assumes the library loads synchronously via a <script> tag in the page header.
|
|
135
|
+
force_immediate_render : bool, default=False
|
|
136
|
+
Controls the timing of plot rendering.
|
|
137
|
+
If True, renders the plot immediately.
|
|
138
|
+
If False, waits for the ResizeObserver event to ensure proper DOM layout.
|
|
139
|
+
responsive : bool, default=False
|
|
140
|
+
If True, makes the plot responsive to container size changes.
|
|
141
|
+
height100pct : bool, default=False
|
|
142
|
+
If True, sets the plot container div height to 100%.
|
|
143
|
+
|
|
144
|
+
Returns
|
|
145
|
+
-------
|
|
146
|
+
str
|
|
147
|
+
HTML string containing the plot with specified options.
|
|
148
|
+
|
|
149
|
+
Notes
|
|
150
|
+
-----
|
|
151
|
+
The sizing_options dict supports the following structure:
|
|
152
|
+
{
|
|
153
|
+
'width_mode': str, # 'fixed', 'min', 'fit', 'scaled' (case-insensitive)
|
|
154
|
+
'height_mode': str, # 'fixed', 'min', 'fit', 'scaled' (case-insensitive)
|
|
155
|
+
'width': number, # optional
|
|
156
|
+
'height': number # optional
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
Sizing modes determine how the plot dimensions are calculated:
|
|
160
|
+
|
|
161
|
+
1. FIXED mode:
|
|
162
|
+
- Uses the explicitly provided width/height values
|
|
163
|
+
- Falls back to the default figure size if no values are provided
|
|
164
|
+
- Not responsive to container size
|
|
165
|
+
|
|
166
|
+
2. MIN mode:
|
|
167
|
+
Applies the smallest dimension among:
|
|
168
|
+
- The default figure size
|
|
169
|
+
- The specified width/height (if provided)
|
|
170
|
+
- The container size (if available)
|
|
171
|
+
|
|
172
|
+
3. FIT mode:
|
|
173
|
+
Uses either:
|
|
174
|
+
- The specified width/height if provided
|
|
175
|
+
- Otherwise uses container size if available
|
|
176
|
+
- Falls back to default figure size if neither is available
|
|
177
|
+
|
|
178
|
+
4. SCALED mode:
|
|
179
|
+
- Always preserves the figure's aspect ratio
|
|
180
|
+
- Typical usage: one dimension (usually width) uses FIXED/MIN/FIT mode,
|
|
181
|
+
and SCALED height adjusts to maintain aspect ratio
|
|
182
|
+
- Special case: when both width and height are SCALED:
|
|
183
|
+
* Requires container size to be available
|
|
184
|
+
* Fits a figure within container while preserving the aspect ratio
|
|
185
|
+
* Neither dimension is predetermined
|
|
186
|
+
|
|
187
|
+
"""
|
|
188
|
+
plot_spec = _standardize_plot_spec(plot_spec)
|
|
189
|
+
sizing_options = standardize_dict(sizing_options)
|
|
190
|
+
return lets_plot_kotlin_bridge.get_display_html_for_raw_spec(
|
|
191
|
+
plot_spec,
|
|
192
|
+
sizing_options,
|
|
193
|
+
dynamic_script_loading,
|
|
194
|
+
force_immediate_render,
|
|
195
|
+
responsive,
|
|
196
|
+
height100pct
|
|
197
|
+
)
|
lets_plot/_type_utils.py
ADDED
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
#
|
|
2
|
+
# Copyright (c) 2019. JetBrains s.r.o.
|
|
3
|
+
# Use of this source code is governed by the MIT license that can be found in the LICENSE file.
|
|
4
|
+
#
|
|
5
|
+
import json
|
|
6
|
+
import math
|
|
7
|
+
from datetime import datetime, date, time, timezone
|
|
8
|
+
|
|
9
|
+
from typing import Dict
|
|
10
|
+
|
|
11
|
+
try:
|
|
12
|
+
import numpy
|
|
13
|
+
except ImportError:
|
|
14
|
+
numpy = None
|
|
15
|
+
|
|
16
|
+
try:
|
|
17
|
+
import pandas
|
|
18
|
+
except ImportError:
|
|
19
|
+
pandas = None
|
|
20
|
+
|
|
21
|
+
try:
|
|
22
|
+
import polars
|
|
23
|
+
except ImportError:
|
|
24
|
+
polars = None
|
|
25
|
+
|
|
26
|
+
try:
|
|
27
|
+
import shapely
|
|
28
|
+
import shapely.geometry
|
|
29
|
+
except ImportError:
|
|
30
|
+
shapely = None
|
|
31
|
+
|
|
32
|
+
try:
|
|
33
|
+
import jax.numpy as jnp
|
|
34
|
+
except ImportError:
|
|
35
|
+
jnp = None
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
# Parameter 'value' can also be pandas.DataFrame
|
|
39
|
+
def standardize_dict(value: Dict) -> Dict:
|
|
40
|
+
result = {}
|
|
41
|
+
for k, v in value.items():
|
|
42
|
+
result[_standardize_value(k)] = _standardize_value(v)
|
|
43
|
+
|
|
44
|
+
return result
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
def is_pandas_data_frame(v) -> bool:
|
|
48
|
+
return pandas and isinstance(v, pandas.DataFrame)
|
|
49
|
+
|
|
50
|
+
|
|
51
|
+
def is_polars_dataframe(v):
|
|
52
|
+
return polars and isinstance(v, polars.DataFrame)
|
|
53
|
+
|
|
54
|
+
|
|
55
|
+
def is_dict_or_dataframe(v):
|
|
56
|
+
return isinstance(v, dict) or (pandas and isinstance(v, pandas.DataFrame))
|
|
57
|
+
|
|
58
|
+
|
|
59
|
+
def is_int(v):
|
|
60
|
+
return isinstance(v, int) or (numpy and isinstance(v, numpy.integer)) or (jnp and isinstance(v, jnp.integer))
|
|
61
|
+
|
|
62
|
+
|
|
63
|
+
def is_float(v):
|
|
64
|
+
return isinstance(v, float) or (numpy and isinstance(v, numpy.floating)) or (jnp and isinstance(v, jnp.floating))
|
|
65
|
+
|
|
66
|
+
|
|
67
|
+
def is_ndarray(data) -> bool:
|
|
68
|
+
return (numpy and isinstance(data, numpy.ndarray)) or (jnp and isinstance(data, jnp.ndarray))
|
|
69
|
+
|
|
70
|
+
|
|
71
|
+
def is_number(v):
|
|
72
|
+
return is_int(v) or is_float(v)
|
|
73
|
+
|
|
74
|
+
|
|
75
|
+
def _standardize_value(v):
|
|
76
|
+
if v is None:
|
|
77
|
+
return v
|
|
78
|
+
if isinstance(v, bool):
|
|
79
|
+
return bool(v)
|
|
80
|
+
if isinstance(v, str):
|
|
81
|
+
return str(v)
|
|
82
|
+
if is_float(v):
|
|
83
|
+
if math.isfinite(v):
|
|
84
|
+
return float(v)
|
|
85
|
+
# None for special values like 'nan' etc. because
|
|
86
|
+
# some JSON parsers (like com.google.gson.Gson) do not handle them well.
|
|
87
|
+
return None
|
|
88
|
+
if is_int(v):
|
|
89
|
+
return float(v)
|
|
90
|
+
if is_dict_or_dataframe(v):
|
|
91
|
+
return standardize_dict(v)
|
|
92
|
+
if is_polars_dataframe(v):
|
|
93
|
+
return standardize_dict(v.to_dict(as_series=False))
|
|
94
|
+
if isinstance(v, list):
|
|
95
|
+
return [_standardize_value(elem) for elem in v]
|
|
96
|
+
if isinstance(v, tuple):
|
|
97
|
+
return tuple(_standardize_value(elem) for elem in v)
|
|
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)):
|
|
106
|
+
return _standardize_value(v.tolist())
|
|
107
|
+
|
|
108
|
+
# Universal NaT/NaN check
|
|
109
|
+
if pandas and pandas.isna(v):
|
|
110
|
+
return None
|
|
111
|
+
|
|
112
|
+
if isinstance(v, datetime):
|
|
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:
|
|
126
|
+
return None
|
|
127
|
+
|
|
128
|
+
if shapely and isinstance(v, shapely.geometry.base.BaseGeometry):
|
|
129
|
+
return json.dumps(shapely.geometry.mapping(v))
|
|
130
|
+
try:
|
|
131
|
+
return repr(v)
|
|
132
|
+
except Exception:
|
|
133
|
+
raise Exception('Unsupported type: {0}({1})'.format(v, type(v)))
|
lets_plot/_version.py
ADDED
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
# Copyright (c) 2020. 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 .corr import *
|
|
5
|
+
from .im import *
|
|
6
|
+
from .qq import *
|
|
7
|
+
from .residual import *
|
|
8
|
+
from .joint import *
|
|
9
|
+
from .waterfall import *
|
|
10
|
+
|
|
11
|
+
__all__ = (im.__all__ +
|
|
12
|
+
corr.__all__ +
|
|
13
|
+
qq.__all__ +
|
|
14
|
+
residual.__all__ +
|
|
15
|
+
joint.__all__ +
|
|
16
|
+
waterfall.__all__)
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
#
|
|
2
|
+
# Copyright (c) 2023. JetBrains s.r.o.
|
|
3
|
+
# Use of this source code is governed by the MIT license that can be found in the LICENSE file.
|
|
4
|
+
#
|
|
5
|
+
from ..plot.core import DummySpec, aes
|
|
6
|
+
from ..plot.geom import *
|
|
7
|
+
from ..plot.marginal_layer import ggmarginal
|
|
8
|
+
|
|
9
|
+
_BINS_DEF = 30
|
|
10
|
+
_COLOR_DEF = "pen"
|
|
11
|
+
|
|
12
|
+
_MARGINAL_ALPHA = .1
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
def _get_bin_params_2d(xs, ys, binwidth, bins):
|
|
16
|
+
if isinstance(bins, int):
|
|
17
|
+
bins = [bins, bins]
|
|
18
|
+
if isinstance(binwidth, int) or isinstance(binwidth, float):
|
|
19
|
+
binwidth = [binwidth, binwidth]
|
|
20
|
+
if binwidth is not None or bins is not None or len(xs) == 0:
|
|
21
|
+
return binwidth, bins
|
|
22
|
+
binwidth_x = (max(xs) - min(xs)) / _BINS_DEF
|
|
23
|
+
binwidth_y = (max(ys) - min(ys)) / _BINS_DEF
|
|
24
|
+
binwidth_max = max(binwidth_x, binwidth_y)
|
|
25
|
+
|
|
26
|
+
return [binwidth_max, binwidth_max], bins
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
def _get_geom2d_layer(geom_kind, binwidth2d, bins2d, color, color_by, size, alpha, show_legend):
|
|
30
|
+
if geom_kind == 'point':
|
|
31
|
+
return geom_point(color=color, size=size, alpha=alpha, show_legend=show_legend)
|
|
32
|
+
if geom_kind == 'tile':
|
|
33
|
+
return geom_bin2d(
|
|
34
|
+
aes(fill=('..count..' if color_by is None else color_by)),
|
|
35
|
+
bins=bins2d, binwidth=binwidth2d,
|
|
36
|
+
color=color, size=size, alpha=alpha,
|
|
37
|
+
show_legend=show_legend
|
|
38
|
+
)
|
|
39
|
+
if geom_kind == 'hex':
|
|
40
|
+
return geom_hex(
|
|
41
|
+
aes(fill=('..count..' if color_by is None else color_by)),
|
|
42
|
+
bins=bins2d, binwidth=binwidth2d,
|
|
43
|
+
color=color, size=size, alpha=alpha,
|
|
44
|
+
show_legend=show_legend
|
|
45
|
+
)
|
|
46
|
+
if geom_kind == 'density2d':
|
|
47
|
+
return geom_density2d(
|
|
48
|
+
aes(color=('..group..' if color_by is None else color_by)),
|
|
49
|
+
color=color, size=size, alpha=alpha,
|
|
50
|
+
show_legend=show_legend
|
|
51
|
+
)
|
|
52
|
+
if geom_kind == 'density2df':
|
|
53
|
+
return geom_density2df(
|
|
54
|
+
aes(fill=('..group..' if color_by is None else color_by)),
|
|
55
|
+
color=color, size=size, alpha=alpha,
|
|
56
|
+
show_legend=show_legend
|
|
57
|
+
)
|
|
58
|
+
if geom_kind == 'pointdensity':
|
|
59
|
+
return geom_pointdensity(
|
|
60
|
+
aes(color=('..density..' if color_by is None else color_by)),
|
|
61
|
+
color=color, size=size, alpha=alpha,
|
|
62
|
+
show_legend=show_legend
|
|
63
|
+
)
|
|
64
|
+
if geom_kind == 'none':
|
|
65
|
+
return None
|
|
66
|
+
raise Exception("Unknown geom '{0}'".format(geom_kind))
|
|
67
|
+
|
|
68
|
+
|
|
69
|
+
def _get_marginal_layers(marginal, binwidth2d, bins2d, color, color_by, show_legend):
|
|
70
|
+
marginal_color = None if color_by is not None else (color or _COLOR_DEF)
|
|
71
|
+
|
|
72
|
+
def bin_param_to_1d(param2d, side):
|
|
73
|
+
if param2d is None:
|
|
74
|
+
return None
|
|
75
|
+
else:
|
|
76
|
+
if side in ['t', 'b']:
|
|
77
|
+
return param2d[0]
|
|
78
|
+
else:
|
|
79
|
+
return param2d[1]
|
|
80
|
+
|
|
81
|
+
def _get_marginal_layer(geom_kind, side, size):
|
|
82
|
+
if geom_kind in ['dens', 'density']:
|
|
83
|
+
layer = geom_area(stat='density', position='identity', color=marginal_color, fill=marginal_color,
|
|
84
|
+
alpha=_MARGINAL_ALPHA, show_legend=show_legend)
|
|
85
|
+
elif geom_kind in ['hist', 'histogram']:
|
|
86
|
+
binwidth = bin_param_to_1d(binwidth2d, side)
|
|
87
|
+
bins = bin_param_to_1d(bins2d, side)
|
|
88
|
+
layer = geom_histogram(bins=bins, binwidth=binwidth,
|
|
89
|
+
color=marginal_color, fill=marginal_color, alpha=_MARGINAL_ALPHA,
|
|
90
|
+
show_legend=show_legend)
|
|
91
|
+
elif geom_kind in ['box', 'boxplot']:
|
|
92
|
+
layer = geom_boxplot(color=marginal_color, fill=marginal_color, alpha=_MARGINAL_ALPHA, show_legend=show_legend)
|
|
93
|
+
else:
|
|
94
|
+
raise Exception("Unknown geom '{0}'".format(geom_kind))
|
|
95
|
+
|
|
96
|
+
return ggmarginal(side, size=size, layer=layer)
|
|
97
|
+
|
|
98
|
+
result = DummySpec()
|
|
99
|
+
for layer_description in filter(bool, marginal.split(",")):
|
|
100
|
+
params = layer_description.strip().split(":")
|
|
101
|
+
geom_kind, sides = params[0].strip(), params[1].strip()
|
|
102
|
+
size = float(params[2].strip()) if len(params) > 2 else None
|
|
103
|
+
for side in sides:
|
|
104
|
+
result += _get_marginal_layer(geom_kind, side, size)
|
|
105
|
+
|
|
106
|
+
return result
|