anyplotlib 0.1.0__py3-none-any.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.
- anyplotlib/__init__.py +53 -0
- anyplotlib/_base_plot.py +229 -0
- anyplotlib/_electron.py +74 -0
- anyplotlib/_repr_utils.py +345 -0
- anyplotlib/_utils.py +194 -0
- anyplotlib/axes/__init__.py +6 -0
- anyplotlib/axes/_axes.py +510 -0
- anyplotlib/axes/_inset_axes.py +126 -0
- anyplotlib/callbacks.py +328 -0
- anyplotlib/embed.py +194 -0
- anyplotlib/figure/__init__.py +7 -0
- anyplotlib/figure/_figure.py +633 -0
- anyplotlib/figure/_gridspec.py +99 -0
- anyplotlib/figure/_subplots.py +100 -0
- anyplotlib/figure_esm.js +6011 -0
- anyplotlib/markers.py +704 -0
- anyplotlib/plot1d/__init__.py +6 -0
- anyplotlib/plot1d/_plot1d.py +1376 -0
- anyplotlib/plot1d/_plotbar.py +436 -0
- anyplotlib/plot2d/__init__.py +5 -0
- anyplotlib/plot2d/_plot2d.py +726 -0
- anyplotlib/plot2d/_plotmesh.py +116 -0
- anyplotlib/plot3d/__init__.py +4 -0
- anyplotlib/plot3d/_plot3d.py +524 -0
- anyplotlib/plotxy/__init__.py +4 -0
- anyplotlib/plotxy/_plotxy.py +273 -0
- anyplotlib/sphinx_anywidget/__init__.py +177 -0
- anyplotlib/sphinx_anywidget/_directive.py +245 -0
- anyplotlib/sphinx_anywidget/_repr_utils.py +298 -0
- anyplotlib/sphinx_anywidget/_scraper.py +390 -0
- anyplotlib/sphinx_anywidget/_wheel_builder.py +84 -0
- anyplotlib/sphinx_anywidget/static/anywidget_bridge.js +1099 -0
- anyplotlib/sphinx_anywidget/static/anywidget_overlay.css +100 -0
- anyplotlib/widgets/__init__.py +18 -0
- anyplotlib/widgets/_base.py +218 -0
- anyplotlib/widgets/_widgets1d.py +109 -0
- anyplotlib/widgets/_widgets2d.py +141 -0
- anyplotlib/widgets/_widgets3d.py +50 -0
- anyplotlib-0.1.0.dist-info/METADATA +160 -0
- anyplotlib-0.1.0.dist-info/RECORD +42 -0
- anyplotlib-0.1.0.dist-info/WHEEL +4 -0
- anyplotlib-0.1.0.dist-info/licenses/LICENSE +21 -0
|
@@ -0,0 +1,436 @@
|
|
|
1
|
+
"""
|
|
2
|
+
plot1d/_plotbar.py
|
|
3
|
+
==================
|
|
4
|
+
Bar chart panel (PlotBar).
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
from __future__ import annotations
|
|
8
|
+
|
|
9
|
+
import numpy as np
|
|
10
|
+
from typing import Callable
|
|
11
|
+
|
|
12
|
+
from anyplotlib._base_plot import _BasePlot, _PanelMixin
|
|
13
|
+
from anyplotlib.callbacks import CallbackRegistry
|
|
14
|
+
from anyplotlib.widgets import (
|
|
15
|
+
Widget,
|
|
16
|
+
VLineWidget as _VLineWidget,
|
|
17
|
+
HLineWidget as _HLineWidget,
|
|
18
|
+
RangeWidget as _RangeWidget,
|
|
19
|
+
PointWidget as _PointWidget,
|
|
20
|
+
)
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
# ---------------------------------------------------------------------------
|
|
24
|
+
# _bar_x_axis helper
|
|
25
|
+
# ---------------------------------------------------------------------------
|
|
26
|
+
|
|
27
|
+
def _bar_x_axis(x_centers: np.ndarray) -> list:
|
|
28
|
+
"""Return a 2-element [x_left_edge, x_right_edge] list for a bar chart.
|
|
29
|
+
|
|
30
|
+
The edges are half a slot-width outside the first/last bar centre so that
|
|
31
|
+
a vline_widget at ``x_centers[i]`` renders at exactly the bar's centre
|
|
32
|
+
pixel when used with ``_xToFrac1d`` / ``_fracToPx1d`` in the JS renderer.
|
|
33
|
+
"""
|
|
34
|
+
n = len(x_centers)
|
|
35
|
+
if n == 0:
|
|
36
|
+
return [0.0, 1.0]
|
|
37
|
+
if n == 1:
|
|
38
|
+
return [float(x_centers[0]) - 0.5, float(x_centers[0]) + 0.5]
|
|
39
|
+
slot = (float(x_centers[-1]) - float(x_centers[0])) / (n - 1)
|
|
40
|
+
half = slot / 2.0
|
|
41
|
+
return [float(x_centers[0]) - half, float(x_centers[-1]) + half]
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
# ---------------------------------------------------------------------------
|
|
45
|
+
# PlotBar
|
|
46
|
+
# ---------------------------------------------------------------------------
|
|
47
|
+
|
|
48
|
+
_LOG_CLAMP = 1e-10 # smallest positive value used when log_scale=True
|
|
49
|
+
|
|
50
|
+
_DEFAULT_GROUP_PALETTE = [
|
|
51
|
+
"#4fc3f7", "#ff7043", "#66bb6a", "#ab47bc",
|
|
52
|
+
"#ffa726", "#26c6da", "#ec407a", "#8d6e63",
|
|
53
|
+
]
|
|
54
|
+
|
|
55
|
+
|
|
56
|
+
def _bar_range(flat: np.ndarray, bottom: float, log_scale: bool):
|
|
57
|
+
"""Return ``(dmin, dmax)`` with padding for the value axis."""
|
|
58
|
+
if log_scale:
|
|
59
|
+
pos = flat[flat > 0]
|
|
60
|
+
dmin = float(np.nanmin(pos)) if len(pos) else _LOG_CLAMP
|
|
61
|
+
dmax = max(float(np.nanmax(flat)) if len(flat) else 1.0,
|
|
62
|
+
bottom if bottom > 0 else _LOG_CLAMP)
|
|
63
|
+
if dmin <= 0:
|
|
64
|
+
dmin = _LOG_CLAMP
|
|
65
|
+
if dmax <= 0:
|
|
66
|
+
dmax = 1.0
|
|
67
|
+
dmax = 10 ** (np.log10(dmax) + 0.15)
|
|
68
|
+
dmin = 10 ** (np.log10(dmin) - 0.15)
|
|
69
|
+
else:
|
|
70
|
+
dmin = min(bottom, float(np.nanmin(flat)) if len(flat) else 0.0)
|
|
71
|
+
dmax = max(bottom, float(np.nanmax(flat)) if len(flat) else 1.0)
|
|
72
|
+
pad = (dmax - dmin) * 0.07 if dmax > dmin else 0.5
|
|
73
|
+
dmax += pad
|
|
74
|
+
if dmin < bottom:
|
|
75
|
+
dmin -= pad
|
|
76
|
+
return dmin, dmax
|
|
77
|
+
|
|
78
|
+
|
|
79
|
+
class PlotBar(_BasePlot, _PanelMixin):
|
|
80
|
+
"""Bar-chart plot panel.
|
|
81
|
+
|
|
82
|
+
Not an anywidget. Holds state in ``_state`` dict; every mutation calls
|
|
83
|
+
``_push()`` which writes to the parent Figure's panel trait.
|
|
84
|
+
|
|
85
|
+
Supports grouped bars (pass a 2-D *height* array with shape ``(N, G)``),
|
|
86
|
+
log-scale value axis, draggable overlay widgets, and hover/click callbacks.
|
|
87
|
+
|
|
88
|
+
Created by :meth:`Axes.bar`.
|
|
89
|
+
"""
|
|
90
|
+
|
|
91
|
+
def __init__(self, x, height=None, width: float = 0.8, bottom: float = 0.0, *,
|
|
92
|
+
align: str = "center",
|
|
93
|
+
color: str = "#4fc3f7",
|
|
94
|
+
colors=None,
|
|
95
|
+
orient: str = "v",
|
|
96
|
+
log_scale: bool = False,
|
|
97
|
+
group_labels=None,
|
|
98
|
+
group_colors=None,
|
|
99
|
+
show_values: bool = False,
|
|
100
|
+
units: str = "",
|
|
101
|
+
y_units: str = "",
|
|
102
|
+
# ── legacy backward-compat kwargs ──────────────────────
|
|
103
|
+
x_labels=None,
|
|
104
|
+
x_centers=None,
|
|
105
|
+
bar_width=None,
|
|
106
|
+
baseline=None,
|
|
107
|
+
values=None):
|
|
108
|
+
self._id: str = ""
|
|
109
|
+
self._fig: object = None
|
|
110
|
+
|
|
111
|
+
if align not in ("center", "edge"):
|
|
112
|
+
raise ValueError("align must be 'center' or 'edge'")
|
|
113
|
+
if orient not in ("v", "h"):
|
|
114
|
+
raise ValueError("orient must be 'v' or 'h'")
|
|
115
|
+
|
|
116
|
+
# ── legacy resolution ──────────────────────────────────────────
|
|
117
|
+
if height is None:
|
|
118
|
+
if values is not None:
|
|
119
|
+
height = values
|
|
120
|
+
else:
|
|
121
|
+
height = x
|
|
122
|
+
x = None
|
|
123
|
+
if baseline is not None:
|
|
124
|
+
bottom = baseline
|
|
125
|
+
if bar_width is not None:
|
|
126
|
+
width = bar_width
|
|
127
|
+
|
|
128
|
+
# ── height (values) — 1-D or 2-D for grouped bars ─────────────
|
|
129
|
+
height_arr = np.asarray(height, dtype=float)
|
|
130
|
+
if height_arr.ndim == 1:
|
|
131
|
+
groups = 1
|
|
132
|
+
values_2d = height_arr.reshape(-1, 1)
|
|
133
|
+
elif height_arr.ndim == 2:
|
|
134
|
+
groups = height_arr.shape[1]
|
|
135
|
+
values_2d = height_arr
|
|
136
|
+
else:
|
|
137
|
+
raise ValueError(
|
|
138
|
+
f"height must be 1-D or 2-D, got shape {height_arr.shape}"
|
|
139
|
+
)
|
|
140
|
+
n = values_2d.shape[0]
|
|
141
|
+
|
|
142
|
+
# ── x (positions or labels) ────────────────────────────────────
|
|
143
|
+
_x_labels: list = []
|
|
144
|
+
_x_centers: np.ndarray | None = None
|
|
145
|
+
|
|
146
|
+
if x is not None:
|
|
147
|
+
x_list = list(x)
|
|
148
|
+
if x_list and isinstance(x_list[0], str):
|
|
149
|
+
_x_labels = x_list
|
|
150
|
+
else:
|
|
151
|
+
_x_centers = np.asarray(x, dtype=float)
|
|
152
|
+
|
|
153
|
+
# Legacy keyword overrides
|
|
154
|
+
if x_labels is not None:
|
|
155
|
+
_x_labels = list(x_labels)
|
|
156
|
+
if x_centers is not None:
|
|
157
|
+
_x_centers = np.asarray(x_centers, dtype=float)
|
|
158
|
+
|
|
159
|
+
if _x_centers is None:
|
|
160
|
+
_x_centers = np.arange(n, dtype=float)
|
|
161
|
+
if len(_x_centers) != n:
|
|
162
|
+
raise ValueError("x length must match height length")
|
|
163
|
+
|
|
164
|
+
# ── data range ─────────────────────────────────────────────────
|
|
165
|
+
flat = values_2d.ravel()
|
|
166
|
+
dmin, dmax = _bar_range(flat, float(bottom), bool(log_scale))
|
|
167
|
+
|
|
168
|
+
# ── group colours ──────────────────────────────────────────────
|
|
169
|
+
if group_colors is None:
|
|
170
|
+
gc_list = (
|
|
171
|
+
[_DEFAULT_GROUP_PALETTE[i % len(_DEFAULT_GROUP_PALETTE)]
|
|
172
|
+
for i in range(groups)]
|
|
173
|
+
if groups > 1 else []
|
|
174
|
+
)
|
|
175
|
+
else:
|
|
176
|
+
gc_list = list(group_colors)
|
|
177
|
+
|
|
178
|
+
x_axis = _bar_x_axis(_x_centers)
|
|
179
|
+
|
|
180
|
+
self._state: dict = {
|
|
181
|
+
"kind": "bar",
|
|
182
|
+
"values": values_2d.tolist(), # always (N, G) 2-D list
|
|
183
|
+
"groups": groups,
|
|
184
|
+
"x_centers": _x_centers.tolist(),
|
|
185
|
+
"x_labels": _x_labels,
|
|
186
|
+
"bar_color": color,
|
|
187
|
+
"bar_colors": list(colors) if colors is not None else [],
|
|
188
|
+
"group_labels": list(group_labels) if group_labels is not None else [],
|
|
189
|
+
"group_colors": gc_list,
|
|
190
|
+
"bar_width": float(width),
|
|
191
|
+
"align": align,
|
|
192
|
+
"orient": orient,
|
|
193
|
+
"baseline": float(bottom),
|
|
194
|
+
"log_scale": bool(log_scale),
|
|
195
|
+
"show_values": bool(show_values),
|
|
196
|
+
"data_min": dmin,
|
|
197
|
+
"data_max": dmax,
|
|
198
|
+
"y_range": None,
|
|
199
|
+
"units": units,
|
|
200
|
+
"y_units": y_units,
|
|
201
|
+
"title": "",
|
|
202
|
+
"x_label": "",
|
|
203
|
+
"y_label": "",
|
|
204
|
+
"axis_visible": True,
|
|
205
|
+
"x_ticks_visible": True,
|
|
206
|
+
"y_ticks_visible": True,
|
|
207
|
+
# overlay-widget coordinate system (mirrors Plot1D)
|
|
208
|
+
"x_axis": x_axis,
|
|
209
|
+
"view_x0": 0.0,
|
|
210
|
+
"view_x1": 1.0,
|
|
211
|
+
"overlay_widgets": [],
|
|
212
|
+
"pointer_settled_ms": 0,
|
|
213
|
+
"pointer_settled_delta": 4,
|
|
214
|
+
"_view_from_python": False,
|
|
215
|
+
}
|
|
216
|
+
self.callbacks = CallbackRegistry()
|
|
217
|
+
self._widgets: dict[str, Widget] = {}
|
|
218
|
+
|
|
219
|
+
def to_state_dict(self) -> dict:
|
|
220
|
+
d = dict(self._state)
|
|
221
|
+
d["overlay_widgets"] = [w.to_dict() for w in self._widgets.values()]
|
|
222
|
+
return d
|
|
223
|
+
|
|
224
|
+
# ------------------------------------------------------------------
|
|
225
|
+
# Data
|
|
226
|
+
# ------------------------------------------------------------------
|
|
227
|
+
def set_data(self, height, x=None, x_labels=None, *, x_centers=None) -> None:
|
|
228
|
+
"""Replace bar heights; recalculates the value-axis range automatically.
|
|
229
|
+
|
|
230
|
+
Parameters
|
|
231
|
+
----------
|
|
232
|
+
height : array-like, shape ``(N,)`` or ``(N, G)``
|
|
233
|
+
New bar heights. For grouped charts the group count *G* must
|
|
234
|
+
match the original.
|
|
235
|
+
x : array-like of numeric, optional
|
|
236
|
+
New bar positions (replaces the stored ``x_centers``). Also
|
|
237
|
+
accepts the legacy keyword alias ``x_centers``.
|
|
238
|
+
x_labels : list of str, optional
|
|
239
|
+
New category labels.
|
|
240
|
+
"""
|
|
241
|
+
height_arr = np.asarray(height, dtype=float)
|
|
242
|
+
if height_arr.ndim == 1:
|
|
243
|
+
values_2d = height_arr.reshape(-1, 1)
|
|
244
|
+
elif height_arr.ndim == 2:
|
|
245
|
+
expected_g = self._state.get("groups", 1)
|
|
246
|
+
if height_arr.shape[1] != expected_g:
|
|
247
|
+
raise ValueError(
|
|
248
|
+
f"Group count mismatch: expected {expected_g}, "
|
|
249
|
+
f"got {height_arr.shape[1]}"
|
|
250
|
+
)
|
|
251
|
+
values_2d = height_arr
|
|
252
|
+
else:
|
|
253
|
+
raise ValueError(
|
|
254
|
+
f"height must be 1-D or 2-D, got shape {height_arr.shape}"
|
|
255
|
+
)
|
|
256
|
+
|
|
257
|
+
flat = values_2d.ravel()
|
|
258
|
+
baseline = self._state["baseline"]
|
|
259
|
+
log_scale = self._state.get("log_scale", False)
|
|
260
|
+
dmin, dmax = _bar_range(flat, float(baseline), bool(log_scale))
|
|
261
|
+
|
|
262
|
+
self._state["values"] = values_2d.tolist()
|
|
263
|
+
self._state["data_min"] = dmin
|
|
264
|
+
self._state["data_max"] = dmax
|
|
265
|
+
|
|
266
|
+
# Accept both `x` and legacy `x_centers` keyword
|
|
267
|
+
_x = x if x is not None else x_centers
|
|
268
|
+
if _x is not None:
|
|
269
|
+
xc = np.asarray(_x, dtype=float)
|
|
270
|
+
self._state["x_centers"] = xc.tolist()
|
|
271
|
+
self._state["x_axis"] = _bar_x_axis(xc)
|
|
272
|
+
if x_labels is not None:
|
|
273
|
+
self._state["x_labels"] = list(x_labels)
|
|
274
|
+
self._push()
|
|
275
|
+
|
|
276
|
+
# ------------------------------------------------------------------
|
|
277
|
+
# Display settings
|
|
278
|
+
# ------------------------------------------------------------------
|
|
279
|
+
def set_color(self, color: str) -> None:
|
|
280
|
+
"""Set a single colour for all bars."""
|
|
281
|
+
self._state["bar_color"] = color
|
|
282
|
+
self._push()
|
|
283
|
+
|
|
284
|
+
def set_colors(self, colors) -> None:
|
|
285
|
+
"""Set per-bar colours (list of CSS colour strings, length N)."""
|
|
286
|
+
self._state["bar_colors"] = list(colors)
|
|
287
|
+
self._push()
|
|
288
|
+
|
|
289
|
+
def set_show_values(self, show: bool) -> None:
|
|
290
|
+
"""Show or hide in-bar value annotations."""
|
|
291
|
+
self._state["show_values"] = bool(show)
|
|
292
|
+
self._push()
|
|
293
|
+
|
|
294
|
+
def set_log_scale(self, log_scale: bool) -> None:
|
|
295
|
+
"""Enable or disable a logarithmic value axis.
|
|
296
|
+
|
|
297
|
+
When *log_scale* is ``True`` any non-positive values are clamped to
|
|
298
|
+
``1e-10`` for display; the data-range bounds are recalculated in
|
|
299
|
+
log-space automatically.
|
|
300
|
+
"""
|
|
301
|
+
self._state["log_scale"] = bool(log_scale)
|
|
302
|
+
flat = np.asarray(self._state["values"]).ravel()
|
|
303
|
+
baseline = self._state["baseline"]
|
|
304
|
+
dmin, dmax = _bar_range(flat, float(baseline), bool(log_scale))
|
|
305
|
+
self._state["data_min"] = dmin
|
|
306
|
+
self._state["data_max"] = dmax
|
|
307
|
+
self._push()
|
|
308
|
+
|
|
309
|
+
# ------------------------------------------------------------------
|
|
310
|
+
# Display control
|
|
311
|
+
# ------------------------------------------------------------------
|
|
312
|
+
def set_xlabel(self, label: str, fontsize: float | None = None) -> None:
|
|
313
|
+
"""Set the x-axis label (mini-TeX allowed; default size 10 px)."""
|
|
314
|
+
self._set_label("x_label", label, "x_label_size", fontsize)
|
|
315
|
+
|
|
316
|
+
def set_ylabel(self, label: str, fontsize: float | None = None) -> None:
|
|
317
|
+
"""Set the y-axis / value-axis label (mini-TeX allowed; default size 10 px)."""
|
|
318
|
+
self._set_label("y_label", label, "y_label_size", fontsize)
|
|
319
|
+
|
|
320
|
+
def set_bar_width(self, width: float) -> None:
|
|
321
|
+
"""Set the bar width."""
|
|
322
|
+
self._state["bar_width"] = float(width)
|
|
323
|
+
self._push()
|
|
324
|
+
|
|
325
|
+
def set_align(self, align: str) -> None:
|
|
326
|
+
"""Set bar alignment: ``'center'`` or ``'edge'``."""
|
|
327
|
+
if align not in ("center", "edge"):
|
|
328
|
+
raise ValueError("align must be 'center' or 'edge'")
|
|
329
|
+
self._state["align"] = align
|
|
330
|
+
self._push()
|
|
331
|
+
|
|
332
|
+
def set_orient(self, orient: str) -> None:
|
|
333
|
+
"""Set bar orientation: ``'v'`` (vertical) or ``'h'`` (horizontal)."""
|
|
334
|
+
if orient not in ("v", "h"):
|
|
335
|
+
raise ValueError("orient must be 'v' or 'h'")
|
|
336
|
+
self._state["orient"] = orient
|
|
337
|
+
self._push()
|
|
338
|
+
|
|
339
|
+
def set_group_labels(self, labels) -> None:
|
|
340
|
+
"""Replace the category labels on the category axis."""
|
|
341
|
+
self._state["group_labels"] = list(labels)
|
|
342
|
+
self._push()
|
|
343
|
+
|
|
344
|
+
# ------------------------------------------------------------------
|
|
345
|
+
# View (xlim / ylim)
|
|
346
|
+
# ------------------------------------------------------------------
|
|
347
|
+
def set_xlim(self, xmin: float, xmax: float) -> None:
|
|
348
|
+
"""Pan/zoom the x-axis to [xmin, xmax] in data coordinates."""
|
|
349
|
+
x_axis = self._state["x_axis"]
|
|
350
|
+
span = x_axis[1] - x_axis[0]
|
|
351
|
+
if span == 0:
|
|
352
|
+
return
|
|
353
|
+
with self._python_view_push():
|
|
354
|
+
self._state["view_x0"] = (xmin - x_axis[0]) / span
|
|
355
|
+
self._state["view_x1"] = (xmax - x_axis[0]) / span
|
|
356
|
+
|
|
357
|
+
def set_ylim(self, y_min: float, y_max: float) -> None:
|
|
358
|
+
"""Fix the value-axis range to [y_min, y_max]."""
|
|
359
|
+
self._state["y_range"] = [float(y_min), float(y_max)]
|
|
360
|
+
self._push()
|
|
361
|
+
|
|
362
|
+
def get_ylim(self) -> tuple:
|
|
363
|
+
"""Return the current value-axis range as ``(y_min, y_max)``."""
|
|
364
|
+
yr = self._state.get("y_range")
|
|
365
|
+
if yr is not None:
|
|
366
|
+
return (float(yr[0]), float(yr[1]))
|
|
367
|
+
return (float(self._state["data_min"]), float(self._state["data_max"]))
|
|
368
|
+
|
|
369
|
+
def get_xlim(self) -> tuple:
|
|
370
|
+
"""Return the current x-axis view range in data coordinates."""
|
|
371
|
+
x_axis = self._state["x_axis"]
|
|
372
|
+
span = x_axis[1] - x_axis[0]
|
|
373
|
+
x0 = x_axis[0] + self._state["view_x0"] * span
|
|
374
|
+
x1 = x_axis[0] + self._state["view_x1"] * span
|
|
375
|
+
return (float(x0), float(x1))
|
|
376
|
+
|
|
377
|
+
def reset_view(self) -> None:
|
|
378
|
+
"""Reset pan/zoom to show all bars."""
|
|
379
|
+
with self._python_view_push():
|
|
380
|
+
self._state["view_x0"] = 0.0
|
|
381
|
+
self._state["view_x1"] = 1.0
|
|
382
|
+
self._state["y_range"] = None
|
|
383
|
+
|
|
384
|
+
# ------------------------------------------------------------------
|
|
385
|
+
# Overlay Widgets
|
|
386
|
+
# ------------------------------------------------------------------
|
|
387
|
+
def add_vline_widget(self, x: float, color: str = "#00e5ff") -> _VLineWidget:
|
|
388
|
+
"""Add a draggable vertical line at data position *x*."""
|
|
389
|
+
widget = _VLineWidget(lambda: None, x=float(x), color=color)
|
|
390
|
+
widget._push_fn = self._make_widget_push_fn(widget)
|
|
391
|
+
self._widgets[widget.id] = widget
|
|
392
|
+
self._push()
|
|
393
|
+
return widget
|
|
394
|
+
|
|
395
|
+
def add_hline_widget(self, y: float, color: str = "#00e5ff") -> _HLineWidget:
|
|
396
|
+
"""Add a draggable horizontal line at value-axis position *y*."""
|
|
397
|
+
widget = _HLineWidget(lambda: None, y=float(y), color=color)
|
|
398
|
+
widget._push_fn = self._make_widget_push_fn(widget)
|
|
399
|
+
self._widgets[widget.id] = widget
|
|
400
|
+
self._push()
|
|
401
|
+
return widget
|
|
402
|
+
|
|
403
|
+
def add_range_widget(self, x0: float, x1: float,
|
|
404
|
+
color: str = "#00e5ff",
|
|
405
|
+
style: str = "band",
|
|
406
|
+
y: float = 0.0,
|
|
407
|
+
_push: bool = True) -> _RangeWidget:
|
|
408
|
+
"""Add a draggable range overlay. See :meth:`Plot1D.add_range_widget` for full docs."""
|
|
409
|
+
widget = _RangeWidget(lambda: None, x0=float(x0), x1=float(x1),
|
|
410
|
+
color=color, style=style, y=float(y))
|
|
411
|
+
widget._push_fn = self._make_widget_push_fn(widget)
|
|
412
|
+
self._widgets[widget.id] = widget
|
|
413
|
+
if _push:
|
|
414
|
+
self._push()
|
|
415
|
+
return widget
|
|
416
|
+
|
|
417
|
+
def add_point_widget(self, x: float, y: float,
|
|
418
|
+
color: str = "#00e5ff",
|
|
419
|
+
show_crosshair: bool = True,
|
|
420
|
+
_push: bool = True) -> _PointWidget:
|
|
421
|
+
"""Add a freely-draggable control point to this panel."""
|
|
422
|
+
widget = _PointWidget(lambda: None, x=float(x), y=float(y), color=color,
|
|
423
|
+
show_crosshair=show_crosshair)
|
|
424
|
+
widget._push_fn = self._make_widget_push_fn(widget)
|
|
425
|
+
self._widgets[widget.id] = widget
|
|
426
|
+
if _push:
|
|
427
|
+
self._push()
|
|
428
|
+
return widget
|
|
429
|
+
|
|
430
|
+
def __repr__(self) -> str:
|
|
431
|
+
n = len(self._state.get("values", []))
|
|
432
|
+
orient = self._state.get("orient", "v")
|
|
433
|
+
groups = self._state.get("groups", 1)
|
|
434
|
+
if groups > 1:
|
|
435
|
+
return f"PlotBar(n={n}, groups={groups}, orient={orient!r})"
|
|
436
|
+
return f"PlotBar(n={n}, orient={orient!r})"
|