plotext-plus 1.0.9__py3-none-any.whl → 1.0.10__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.
- plotext_plus/__init__.py +20 -15
- plotext_plus/__main__.py +1 -0
- plotext_plus/_api.py +632 -371
- plotext_plus/_build.py +765 -149
- plotext_plus/_core.py +609 -164
- plotext_plus/_date.py +50 -32
- plotext_plus/_default.py +35 -28
- plotext_plus/_dict.py +807 -103
- plotext_plus/_doc.py +867 -296
- plotext_plus/_doc_utils.py +279 -245
- plotext_plus/_figure.py +1295 -303
- plotext_plus/_global.py +238 -140
- plotext_plus/_matrix.py +217 -63
- plotext_plus/_monitor.py +1036 -489
- plotext_plus/_output.py +29 -23
- plotext_plus/_shtab.py +2 -0
- plotext_plus/_themes.py +363 -247
- plotext_plus/_utility.py +581 -313
- plotext_plus/api.py +418 -332
- plotext_plus/charts.py +47 -24
- plotext_plus/core.py +570 -177
- plotext_plus/mcp_cli.py +15 -13
- plotext_plus/mcp_server.py +813 -332
- plotext_plus/plotext_cli.py +414 -275
- plotext_plus/plotting.py +86 -70
- plotext_plus/themes.py +10 -13
- plotext_plus/utilities.py +33 -33
- plotext_plus/utils.py +240 -140
- {plotext_plus-1.0.9.dist-info → plotext_plus-1.0.10.dist-info}/METADATA +7 -2
- plotext_plus-1.0.10.dist-info/RECORD +33 -0
- plotext_plus-1.0.9.dist-info/RECORD +0 -33
- {plotext_plus-1.0.9.dist-info → plotext_plus-1.0.10.dist-info}/WHEEL +0 -0
- {plotext_plus-1.0.9.dist-info → plotext_plus-1.0.10.dist-info}/entry_points.txt +0 -0
- {plotext_plus-1.0.9.dist-info → plotext_plus-1.0.10.dist-info}/licenses/LICENSE +0 -0
plotext_plus/api.py
CHANGED
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
# /usr/bin/env python3
|
|
2
|
-
# -*- coding: utf-8 -*-
|
|
3
2
|
|
|
4
3
|
"""
|
|
5
4
|
Modern Plotext API - A cleaner, more intuitive interface for creating terminal charts
|
|
@@ -8,21 +7,25 @@ backward compatibility with the existing plotext API.
|
|
|
8
7
|
"""
|
|
9
8
|
|
|
10
9
|
import plotext_plus._core as _core
|
|
11
|
-
from plotext_plus._output import
|
|
10
|
+
from plotext_plus._output import error
|
|
11
|
+
from plotext_plus._output import info
|
|
12
|
+
from plotext_plus._output import set_output_mode
|
|
13
|
+
from plotext_plus._output import success
|
|
14
|
+
from plotext_plus._output import warning
|
|
12
15
|
|
|
13
16
|
|
|
14
17
|
class Chart:
|
|
15
18
|
"""
|
|
16
19
|
Modern object-oriented interface for creating charts.
|
|
17
|
-
|
|
20
|
+
|
|
18
21
|
This class provides a chainable API for building charts with method chaining
|
|
19
22
|
and cleaner separation of concerns.
|
|
20
23
|
"""
|
|
21
|
-
|
|
24
|
+
|
|
22
25
|
def __init__(self, use_banners=False, banner_title=None):
|
|
23
26
|
"""
|
|
24
27
|
Initialize a new chart.
|
|
25
|
-
|
|
28
|
+
|
|
26
29
|
Args:
|
|
27
30
|
use_banners (bool): Whether to display charts in chuk-term banners
|
|
28
31
|
banner_title (str): Title for the banner (if enabled)
|
|
@@ -32,156 +35,175 @@ class Chart:
|
|
|
32
35
|
self._data = []
|
|
33
36
|
self._legend = None
|
|
34
37
|
self._config = {
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
38
|
+
"title": None,
|
|
39
|
+
"x_label": None,
|
|
40
|
+
"y_label": None,
|
|
41
|
+
"width": None,
|
|
42
|
+
"height": None,
|
|
43
|
+
"theme": "default",
|
|
41
44
|
}
|
|
42
|
-
|
|
45
|
+
|
|
43
46
|
# Configure output mode
|
|
44
47
|
if use_banners:
|
|
45
48
|
set_output_mode(True, banner_title)
|
|
46
49
|
# When using banners, automatically set appropriate size to fit within banner
|
|
47
50
|
from plotext import _utility as _ut
|
|
48
|
-
|
|
51
|
+
|
|
52
|
+
banner_width = (
|
|
53
|
+
_ut.terminal_width()
|
|
54
|
+
) # This now returns adjusted width for banners
|
|
49
55
|
if banner_width:
|
|
50
|
-
self._config[
|
|
51
|
-
|
|
56
|
+
self._config["width"] = banner_width
|
|
57
|
+
|
|
52
58
|
def scatter(self, x, y, marker=None, color=None, label=None):
|
|
53
59
|
"""Add scatter plot data"""
|
|
54
|
-
self._data.append(
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
60
|
+
self._data.append(
|
|
61
|
+
{
|
|
62
|
+
"type": "scatter",
|
|
63
|
+
"x": x,
|
|
64
|
+
"y": y,
|
|
65
|
+
"marker": marker,
|
|
66
|
+
"color": color,
|
|
67
|
+
"label": label,
|
|
68
|
+
}
|
|
69
|
+
)
|
|
70
|
+
return self
|
|
71
|
+
|
|
64
72
|
def line(self, x, y, marker=None, color=None, label=None):
|
|
65
73
|
"""Add line plot data"""
|
|
66
|
-
self._data.append(
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
74
|
+
self._data.append(
|
|
75
|
+
{
|
|
76
|
+
"type": "line",
|
|
77
|
+
"x": x,
|
|
78
|
+
"y": y,
|
|
79
|
+
"marker": marker,
|
|
80
|
+
"color": color,
|
|
81
|
+
"label": label,
|
|
82
|
+
}
|
|
83
|
+
)
|
|
84
|
+
return self
|
|
85
|
+
|
|
76
86
|
def bar(self, labels, values, color=None, horizontal=False):
|
|
77
87
|
"""Add bar chart data"""
|
|
78
|
-
self._data.append(
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
88
|
+
self._data.append(
|
|
89
|
+
{
|
|
90
|
+
"type": "bar",
|
|
91
|
+
"labels": labels,
|
|
92
|
+
"values": values,
|
|
93
|
+
"color": color,
|
|
94
|
+
"horizontal": horizontal,
|
|
95
|
+
}
|
|
96
|
+
)
|
|
97
|
+
return self
|
|
98
|
+
|
|
87
99
|
def title(self, title):
|
|
88
100
|
"""Set chart title"""
|
|
89
|
-
self._config[
|
|
101
|
+
self._config["title"] = title
|
|
90
102
|
return self
|
|
91
|
-
|
|
103
|
+
|
|
92
104
|
def xlabel(self, label):
|
|
93
105
|
"""Set x-axis label"""
|
|
94
|
-
self._config[
|
|
106
|
+
self._config["x_label"] = label
|
|
95
107
|
return self
|
|
96
|
-
|
|
108
|
+
|
|
97
109
|
def ylabel(self, label):
|
|
98
110
|
"""Set y-axis label"""
|
|
99
|
-
self._config[
|
|
111
|
+
self._config["y_label"] = label
|
|
100
112
|
return self
|
|
101
|
-
|
|
113
|
+
|
|
102
114
|
def size(self, width=None, height=None):
|
|
103
115
|
"""Set chart size"""
|
|
104
|
-
self._config[
|
|
105
|
-
self._config[
|
|
116
|
+
self._config["width"] = width
|
|
117
|
+
self._config["height"] = height
|
|
106
118
|
return self
|
|
107
|
-
|
|
119
|
+
|
|
108
120
|
def theme(self, theme_name):
|
|
109
121
|
"""Set chart theme"""
|
|
110
|
-
self._config[
|
|
122
|
+
self._config["theme"] = theme_name
|
|
111
123
|
return self
|
|
112
|
-
|
|
124
|
+
|
|
113
125
|
def banner_title(self, title):
|
|
114
126
|
"""Set banner title (if banner mode is enabled)"""
|
|
115
127
|
self.banner_title = title
|
|
116
128
|
if self.use_banners:
|
|
117
129
|
set_output_mode(True, title)
|
|
118
130
|
return self
|
|
119
|
-
|
|
131
|
+
|
|
120
132
|
def legend(self, legend_instance=None):
|
|
121
133
|
"""
|
|
122
134
|
Set or get legend for this chart
|
|
123
|
-
|
|
135
|
+
|
|
124
136
|
Args:
|
|
125
137
|
legend_instance (Legend): Legend instance to apply to chart
|
|
126
|
-
|
|
138
|
+
|
|
127
139
|
Returns:
|
|
128
140
|
Chart: Self for chaining, or current legend if no args provided
|
|
129
141
|
"""
|
|
130
142
|
if legend_instance is None:
|
|
131
143
|
return self._legend
|
|
132
|
-
|
|
144
|
+
|
|
133
145
|
self._legend = legend_instance
|
|
134
146
|
legend_instance.apply_to_chart(self)
|
|
135
147
|
return self
|
|
136
|
-
|
|
148
|
+
|
|
137
149
|
def show(self):
|
|
138
150
|
"""Render and display the chart"""
|
|
139
151
|
# Clear any existing plot data
|
|
140
152
|
_core.clear_figure()
|
|
141
|
-
|
|
153
|
+
|
|
142
154
|
# Configure plot settings
|
|
143
|
-
if self._config[
|
|
144
|
-
_core.title(self._config[
|
|
145
|
-
if self._config[
|
|
146
|
-
_core.xlabel(self._config[
|
|
147
|
-
if self._config[
|
|
148
|
-
_core.ylabel(self._config[
|
|
149
|
-
if self._config[
|
|
150
|
-
_core.plot_size(self._config[
|
|
151
|
-
|
|
155
|
+
if self._config["title"]:
|
|
156
|
+
_core.title(self._config["title"])
|
|
157
|
+
if self._config["x_label"]:
|
|
158
|
+
_core.xlabel(self._config["x_label"])
|
|
159
|
+
if self._config["y_label"]:
|
|
160
|
+
_core.ylabel(self._config["y_label"])
|
|
161
|
+
if self._config["width"] or self._config["height"]:
|
|
162
|
+
_core.plot_size(self._config["width"], self._config["height"])
|
|
163
|
+
|
|
152
164
|
# Add data to plot
|
|
153
165
|
for data_item in self._data:
|
|
154
|
-
if data_item[
|
|
166
|
+
if data_item["type"] == "scatter":
|
|
155
167
|
_core.scatter(
|
|
156
|
-
data_item[
|
|
157
|
-
data_item[
|
|
158
|
-
marker=data_item[
|
|
159
|
-
color=data_item[
|
|
160
|
-
label=data_item[
|
|
168
|
+
data_item["x"],
|
|
169
|
+
data_item["y"],
|
|
170
|
+
marker=data_item["marker"],
|
|
171
|
+
color=data_item["color"],
|
|
172
|
+
label=data_item["label"],
|
|
161
173
|
)
|
|
162
|
-
elif data_item[
|
|
174
|
+
elif data_item["type"] == "line":
|
|
163
175
|
_core.plot(
|
|
164
|
-
data_item[
|
|
165
|
-
data_item[
|
|
166
|
-
marker=data_item[
|
|
167
|
-
color=data_item[
|
|
168
|
-
label=data_item[
|
|
176
|
+
data_item["x"],
|
|
177
|
+
data_item["y"],
|
|
178
|
+
marker=data_item["marker"],
|
|
179
|
+
color=data_item["color"],
|
|
180
|
+
label=data_item["label"],
|
|
169
181
|
)
|
|
170
|
-
elif data_item[
|
|
171
|
-
if data_item[
|
|
172
|
-
_core.horizontal_bar(
|
|
182
|
+
elif data_item["type"] == "bar":
|
|
183
|
+
if data_item["horizontal"]:
|
|
184
|
+
_core.horizontal_bar(
|
|
185
|
+
data_item["labels"],
|
|
186
|
+
data_item["values"],
|
|
187
|
+
color=data_item["color"],
|
|
188
|
+
)
|
|
173
189
|
else:
|
|
174
|
-
_core.bar(
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
190
|
+
_core.bar(
|
|
191
|
+
data_item["labels"],
|
|
192
|
+
data_item["values"],
|
|
193
|
+
color=data_item["color"],
|
|
194
|
+
)
|
|
195
|
+
elif data_item["type"] == "histogram":
|
|
196
|
+
_core.hist(
|
|
197
|
+
data_item["data"], bins=data_item["bins"], color=data_item["color"]
|
|
198
|
+
)
|
|
199
|
+
|
|
178
200
|
# Display the chart
|
|
179
201
|
_core.show()
|
|
180
202
|
return self
|
|
181
|
-
|
|
182
|
-
def save(self, path, format=
|
|
203
|
+
|
|
204
|
+
def save(self, path, format="txt"):
|
|
183
205
|
"""Save chart to file"""
|
|
184
|
-
if format ==
|
|
206
|
+
if format == "html":
|
|
185
207
|
_core.save_fig(path, keep_colors=True)
|
|
186
208
|
else:
|
|
187
209
|
_core.save_fig(path)
|
|
@@ -192,17 +214,26 @@ class ScatterChart(Chart):
|
|
|
192
214
|
"""
|
|
193
215
|
Specialized class for creating scatter plots with a focused API
|
|
194
216
|
"""
|
|
195
|
-
|
|
196
|
-
def __init__(
|
|
217
|
+
|
|
218
|
+
def __init__(
|
|
219
|
+
self,
|
|
220
|
+
x,
|
|
221
|
+
y,
|
|
222
|
+
marker=None,
|
|
223
|
+
color=None,
|
|
224
|
+
label=None,
|
|
225
|
+
use_banners=False,
|
|
226
|
+
banner_title=None,
|
|
227
|
+
):
|
|
197
228
|
"""Initialize a scatter chart with data"""
|
|
198
229
|
super().__init__(use_banners, banner_title)
|
|
199
230
|
self.scatter(x, y, marker, color, label)
|
|
200
|
-
|
|
201
|
-
def add_trend_line(self, x, y, color=
|
|
231
|
+
|
|
232
|
+
def add_trend_line(self, x, y, color="red", label="Trend"):
|
|
202
233
|
"""Add a trend line to the scatter plot"""
|
|
203
234
|
self.line(x, y, color=color, label=label)
|
|
204
235
|
return self
|
|
205
|
-
|
|
236
|
+
|
|
206
237
|
def add_regression(self):
|
|
207
238
|
"""Add linear regression line (future enhancement)"""
|
|
208
239
|
# Placeholder for regression functionality
|
|
@@ -213,17 +244,26 @@ class LineChart(Chart):
|
|
|
213
244
|
"""
|
|
214
245
|
Specialized class for creating line charts with enhanced features
|
|
215
246
|
"""
|
|
216
|
-
|
|
217
|
-
def __init__(
|
|
247
|
+
|
|
248
|
+
def __init__(
|
|
249
|
+
self,
|
|
250
|
+
x,
|
|
251
|
+
y,
|
|
252
|
+
marker=None,
|
|
253
|
+
color=None,
|
|
254
|
+
label=None,
|
|
255
|
+
use_banners=False,
|
|
256
|
+
banner_title=None,
|
|
257
|
+
):
|
|
218
258
|
"""Initialize a line chart with data"""
|
|
219
259
|
super().__init__(use_banners, banner_title)
|
|
220
260
|
self.line(x, y, marker, color, label)
|
|
221
|
-
|
|
261
|
+
|
|
222
262
|
def add_fill(self, fillx=False, filly=False):
|
|
223
263
|
"""Add fill under the line (future enhancement)"""
|
|
224
264
|
# Placeholder for fill functionality
|
|
225
265
|
return self
|
|
226
|
-
|
|
266
|
+
|
|
227
267
|
def smooth(self, window_size=3):
|
|
228
268
|
"""Apply smoothing to the line (future enhancement)"""
|
|
229
269
|
# Placeholder for smoothing functionality
|
|
@@ -234,29 +274,39 @@ class BarChart(Chart):
|
|
|
234
274
|
"""
|
|
235
275
|
Specialized class for creating bar charts with extensive customization
|
|
236
276
|
"""
|
|
237
|
-
|
|
238
|
-
def __init__(
|
|
277
|
+
|
|
278
|
+
def __init__(
|
|
279
|
+
self,
|
|
280
|
+
labels,
|
|
281
|
+
values,
|
|
282
|
+
color=None,
|
|
283
|
+
horizontal=False,
|
|
284
|
+
use_banners=False,
|
|
285
|
+
banner_title=None,
|
|
286
|
+
):
|
|
239
287
|
"""Initialize a bar chart with data"""
|
|
240
288
|
super().__init__(use_banners, banner_title)
|
|
241
289
|
self.bar(labels, values, color, horizontal)
|
|
242
290
|
self.labels = labels
|
|
243
291
|
self.values = values
|
|
244
|
-
|
|
292
|
+
|
|
245
293
|
def stack(self, values, color=None, label=None):
|
|
246
294
|
"""Add stacked bars (future enhancement)"""
|
|
247
295
|
# Placeholder for stacked bar functionality
|
|
248
296
|
return self
|
|
249
|
-
|
|
297
|
+
|
|
250
298
|
def group(self, values, color=None, label=None):
|
|
251
299
|
"""Add grouped bars (future enhancement)"""
|
|
252
300
|
# Placeholder for grouped bar functionality
|
|
253
301
|
return self
|
|
254
|
-
|
|
302
|
+
|
|
255
303
|
def sort_by_value(self, ascending=True):
|
|
256
304
|
"""Sort bars by value"""
|
|
257
305
|
# Simple implementation for sorting
|
|
258
|
-
sorted_pairs = sorted(
|
|
259
|
-
|
|
306
|
+
sorted_pairs = sorted(
|
|
307
|
+
zip(self.values, self.labels, strict=False), reverse=not ascending
|
|
308
|
+
)
|
|
309
|
+
self.values, self.labels = zip(*sorted_pairs, strict=False)
|
|
260
310
|
return self
|
|
261
311
|
|
|
262
312
|
|
|
@@ -264,30 +314,27 @@ class HistogramChart(Chart):
|
|
|
264
314
|
"""
|
|
265
315
|
Specialized class for creating histograms with statistical features
|
|
266
316
|
"""
|
|
267
|
-
|
|
317
|
+
|
|
268
318
|
def __init__(self, data, bins=20, color=None, use_banners=False, banner_title=None):
|
|
269
319
|
"""Initialize a histogram with data"""
|
|
270
320
|
super().__init__(use_banners, banner_title)
|
|
271
321
|
self.data = data
|
|
272
322
|
self.bins = bins
|
|
273
323
|
self._create_histogram(data, bins, color)
|
|
274
|
-
|
|
324
|
+
|
|
275
325
|
def _create_histogram(self, data, bins, color):
|
|
276
326
|
"""Create histogram from raw data"""
|
|
277
327
|
# Add histogram data to the chart
|
|
278
|
-
self._data.append(
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
})
|
|
284
|
-
return self
|
|
285
|
-
|
|
328
|
+
self._data.append(
|
|
329
|
+
{"type": "histogram", "data": data, "bins": bins, "color": color}
|
|
330
|
+
)
|
|
331
|
+
return self
|
|
332
|
+
|
|
286
333
|
def add_normal_curve(self):
|
|
287
334
|
"""Overlay a normal distribution curve (future enhancement)"""
|
|
288
335
|
# Placeholder for normal curve overlay
|
|
289
336
|
return self
|
|
290
|
-
|
|
337
|
+
|
|
291
338
|
def add_statistics(self):
|
|
292
339
|
"""Add mean, median, std dev lines (future enhancement)"""
|
|
293
340
|
# Placeholder for statistical lines
|
|
@@ -298,11 +345,11 @@ class CandlestickChart(Chart):
|
|
|
298
345
|
"""
|
|
299
346
|
Specialized class for financial candlestick charts
|
|
300
347
|
"""
|
|
301
|
-
|
|
348
|
+
|
|
302
349
|
def __init__(self, dates, data, colors=None, use_banners=False, banner_title=None):
|
|
303
350
|
"""
|
|
304
351
|
Initialize a candlestick chart
|
|
305
|
-
|
|
352
|
+
|
|
306
353
|
Args:
|
|
307
354
|
dates: List of dates
|
|
308
355
|
data: List of [open, high, low, close] values
|
|
@@ -311,56 +358,49 @@ class CandlestickChart(Chart):
|
|
|
311
358
|
super().__init__(use_banners, banner_title)
|
|
312
359
|
self.dates = dates
|
|
313
360
|
self.data = data
|
|
314
|
-
self._data.append(
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
})
|
|
320
|
-
|
|
321
|
-
def add_volume(self, volumes, color='blue'):
|
|
361
|
+
self._data.append(
|
|
362
|
+
{"type": "candlestick", "dates": dates, "data": data, "colors": colors}
|
|
363
|
+
)
|
|
364
|
+
|
|
365
|
+
def add_volume(self, volumes, color="blue"):
|
|
322
366
|
"""Add volume bars below candlesticks (future enhancement)"""
|
|
323
367
|
# Placeholder for volume functionality
|
|
324
368
|
return self
|
|
325
|
-
|
|
326
|
-
def add_moving_average(self, period=20, color=
|
|
369
|
+
|
|
370
|
+
def add_moving_average(self, period=20, color="orange"):
|
|
327
371
|
"""Add moving average line (future enhancement)"""
|
|
328
372
|
# Placeholder for moving average
|
|
329
373
|
return self
|
|
330
|
-
|
|
374
|
+
|
|
331
375
|
def show(self):
|
|
332
376
|
"""Render and display the candlestick chart"""
|
|
333
377
|
_core.clear_figure()
|
|
334
|
-
|
|
335
|
-
if self._config[
|
|
336
|
-
_core.title(self._config[
|
|
337
|
-
if self._config[
|
|
338
|
-
_core.xlabel(self._config[
|
|
339
|
-
if self._config[
|
|
340
|
-
_core.ylabel(self._config[
|
|
341
|
-
if self._config[
|
|
342
|
-
_core.plot_size(self._config[
|
|
343
|
-
|
|
378
|
+
|
|
379
|
+
if self._config["title"]:
|
|
380
|
+
_core.title(self._config["title"])
|
|
381
|
+
if self._config["x_label"]:
|
|
382
|
+
_core.xlabel(self._config["x_label"])
|
|
383
|
+
if self._config["y_label"]:
|
|
384
|
+
_core.ylabel(self._config["y_label"])
|
|
385
|
+
if self._config["width"] or self._config["height"]:
|
|
386
|
+
_core.plot_size(self._config["width"], self._config["height"])
|
|
387
|
+
|
|
344
388
|
for data_item in self._data:
|
|
345
|
-
if data_item[
|
|
389
|
+
if data_item["type"] == "candlestick":
|
|
346
390
|
# Convert list format to dictionary format expected by plotext
|
|
347
|
-
dates = data_item[
|
|
348
|
-
ohlc_data = data_item[
|
|
349
|
-
|
|
391
|
+
dates = data_item["dates"]
|
|
392
|
+
ohlc_data = data_item["data"]
|
|
393
|
+
|
|
350
394
|
# Format data as expected by plotext candlestick function
|
|
351
395
|
formatted_data = {
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
396
|
+
"Open": [item[0] for item in ohlc_data],
|
|
397
|
+
"High": [item[1] for item in ohlc_data],
|
|
398
|
+
"Low": [item[2] for item in ohlc_data],
|
|
399
|
+
"Close": [item[3] for item in ohlc_data],
|
|
356
400
|
}
|
|
357
|
-
|
|
358
|
-
_core.candlestick(
|
|
359
|
-
|
|
360
|
-
formatted_data,
|
|
361
|
-
colors=data_item['colors']
|
|
362
|
-
)
|
|
363
|
-
|
|
401
|
+
|
|
402
|
+
_core.candlestick(dates, formatted_data, colors=data_item["colors"])
|
|
403
|
+
|
|
364
404
|
_core.show()
|
|
365
405
|
return self
|
|
366
406
|
|
|
@@ -369,11 +409,11 @@ class HeatmapChart(Chart):
|
|
|
369
409
|
"""
|
|
370
410
|
Specialized class for creating heatmaps and matrix visualizations
|
|
371
411
|
"""
|
|
372
|
-
|
|
412
|
+
|
|
373
413
|
def __init__(self, data, colorscale=None, use_banners=False, banner_title=None):
|
|
374
414
|
"""
|
|
375
415
|
Initialize a heatmap chart
|
|
376
|
-
|
|
416
|
+
|
|
377
417
|
Args:
|
|
378
418
|
data: 2D matrix or pandas DataFrame
|
|
379
419
|
colorscale: Color scale for the heatmap
|
|
@@ -381,209 +421,238 @@ class HeatmapChart(Chart):
|
|
|
381
421
|
super().__init__(use_banners, banner_title)
|
|
382
422
|
self.data = data
|
|
383
423
|
self.colorscale = colorscale
|
|
384
|
-
self._data.append({
|
|
385
|
-
|
|
386
|
-
'data': data,
|
|
387
|
-
'colorscale': colorscale
|
|
388
|
-
})
|
|
389
|
-
|
|
424
|
+
self._data.append({"type": "heatmap", "data": data, "colorscale": colorscale})
|
|
425
|
+
|
|
390
426
|
def annotate(self, show_values=True):
|
|
391
427
|
"""Add value annotations to cells (future enhancement)"""
|
|
392
428
|
# Placeholder for annotations
|
|
393
429
|
return self
|
|
394
|
-
|
|
430
|
+
|
|
395
431
|
def show(self):
|
|
396
432
|
"""Render and display the heatmap"""
|
|
397
433
|
_core.clear_figure()
|
|
398
|
-
|
|
434
|
+
|
|
399
435
|
# Set appropriate plot size for heatmaps FIRST - ensure full width usage
|
|
400
|
-
if self._config[
|
|
401
|
-
_core.plotsize(self._config[
|
|
436
|
+
if self._config["width"] or self._config["height"]:
|
|
437
|
+
_core.plotsize(self._config["width"], self._config["height"])
|
|
402
438
|
else:
|
|
403
439
|
# Default to full terminal width for better heatmap display
|
|
404
440
|
import plotext_plus._utility as _ut
|
|
441
|
+
|
|
405
442
|
terminal_width = _ut.terminal_width()
|
|
406
443
|
if terminal_width:
|
|
407
444
|
# Set reasonable dimensions for heatmap display
|
|
408
445
|
heatmap_height = max(20, len(self.data) * 6 + 10)
|
|
409
446
|
_core.plotsize(terminal_width - 4, heatmap_height)
|
|
410
|
-
|
|
447
|
+
|
|
411
448
|
# Configure plot settings (same as base Chart class)
|
|
412
|
-
if self._config[
|
|
413
|
-
_core.title(self._config[
|
|
414
|
-
if self._config[
|
|
415
|
-
_core.xlabel(self._config[
|
|
416
|
-
if self._config[
|
|
417
|
-
_core.ylabel(self._config[
|
|
418
|
-
|
|
449
|
+
if self._config["title"]:
|
|
450
|
+
_core.title(self._config["title"])
|
|
451
|
+
if self._config["x_label"]:
|
|
452
|
+
_core.xlabel(self._config["x_label"])
|
|
453
|
+
if self._config["y_label"]:
|
|
454
|
+
_core.ylabel(self._config["y_label"])
|
|
455
|
+
|
|
419
456
|
for data_item in self._data:
|
|
420
|
-
if data_item[
|
|
421
|
-
data = data_item[
|
|
422
|
-
|
|
457
|
+
if data_item["type"] == "heatmap":
|
|
458
|
+
data = data_item["data"]
|
|
459
|
+
|
|
423
460
|
# Check if data is a pandas DataFrame
|
|
424
|
-
if hasattr(data,
|
|
461
|
+
if hasattr(data, "columns"):
|
|
425
462
|
# It's already a DataFrame
|
|
426
|
-
_core.heatmap(data, color=data_item[
|
|
463
|
+
_core.heatmap(data, color=data_item["colorscale"])
|
|
427
464
|
else:
|
|
428
465
|
# It's a list/matrix, create filled heatmap blocks
|
|
429
|
-
self._draw_filled_heatmap(data, data_item[
|
|
430
|
-
|
|
466
|
+
self._draw_filled_heatmap(data, data_item["colorscale"])
|
|
467
|
+
|
|
431
468
|
_core.show()
|
|
432
469
|
return self
|
|
433
|
-
|
|
470
|
+
|
|
434
471
|
def _draw_list_heatmap(self, matrix, colorscale):
|
|
435
472
|
"""Draw a heatmap using continuous colored blocks"""
|
|
436
473
|
if not matrix or not matrix[0]:
|
|
437
474
|
return
|
|
438
|
-
|
|
475
|
+
|
|
439
476
|
rows = len(matrix)
|
|
440
477
|
cols = len(matrix[0])
|
|
441
|
-
|
|
478
|
+
|
|
442
479
|
# Flatten and normalize the data for color mapping
|
|
443
480
|
flat_data = [val for row in matrix for val in row]
|
|
444
481
|
min_val = min(flat_data)
|
|
445
482
|
max_val = max(flat_data)
|
|
446
483
|
value_range = max_val - min_val if max_val != min_val else 1
|
|
447
|
-
|
|
484
|
+
|
|
448
485
|
# Define color palette
|
|
449
486
|
color_palettes = {
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
487
|
+
"plasma": ["black", "purple", "magenta", "red", "orange", "yellow"],
|
|
488
|
+
"viridis": ["black", "blue", "green", "bright green", "yellow"],
|
|
489
|
+
"cool": ["cyan", "blue", "magenta", "white"],
|
|
490
|
+
"hot": ["black", "red", "orange", "yellow", "white"],
|
|
491
|
+
"default": ["blue", "cyan", "green", "yellow", "red", "magenta"],
|
|
455
492
|
}
|
|
456
|
-
colors = color_palettes.get(colorscale, color_palettes[
|
|
457
|
-
|
|
493
|
+
colors = color_palettes.get(colorscale, color_palettes["default"])
|
|
494
|
+
|
|
458
495
|
# Create heatmap using continuous filled rectangles for each cell
|
|
459
496
|
for row_idx in range(rows):
|
|
460
497
|
row_data = matrix[row_idx]
|
|
461
498
|
y_level = rows - row_idx - 1 # Flip so row 0 is at top
|
|
462
|
-
|
|
499
|
+
|
|
463
500
|
for col_idx, value in enumerate(row_data):
|
|
464
501
|
# Normalize value to get color
|
|
465
502
|
normalized = (value - min_val) / value_range
|
|
466
503
|
color_idx = int(normalized * (len(colors) - 1))
|
|
467
504
|
color = colors[min(color_idx, len(colors) - 1)]
|
|
468
|
-
|
|
505
|
+
|
|
469
506
|
# Create a continuous filled rectangle for this cell
|
|
470
507
|
# Use multiple closely spaced points to fill the area
|
|
471
508
|
cell_points_x = []
|
|
472
509
|
cell_points_y = []
|
|
473
|
-
|
|
510
|
+
|
|
474
511
|
# Fill the cell with dense points to create solid appearance
|
|
475
|
-
for x_offset in [
|
|
476
|
-
|
|
512
|
+
for x_offset in [
|
|
513
|
+
-0.45,
|
|
514
|
+
-0.35,
|
|
515
|
+
-0.25,
|
|
516
|
+
-0.15,
|
|
517
|
+
-0.05,
|
|
518
|
+
0.05,
|
|
519
|
+
0.15,
|
|
520
|
+
0.25,
|
|
521
|
+
0.35,
|
|
522
|
+
0.45,
|
|
523
|
+
]:
|
|
524
|
+
for y_offset in [
|
|
525
|
+
-0.45,
|
|
526
|
+
-0.35,
|
|
527
|
+
-0.25,
|
|
528
|
+
-0.15,
|
|
529
|
+
-0.05,
|
|
530
|
+
0.05,
|
|
531
|
+
0.15,
|
|
532
|
+
0.25,
|
|
533
|
+
0.35,
|
|
534
|
+
0.45,
|
|
535
|
+
]:
|
|
477
536
|
cell_points_x.append(col_idx + x_offset)
|
|
478
537
|
cell_points_y.append(y_level + y_offset)
|
|
479
|
-
|
|
538
|
+
|
|
480
539
|
# Draw all points for this cell at once with the same color
|
|
481
540
|
if cell_points_x and cell_points_y:
|
|
482
|
-
_core.scatter(cell_points_x, cell_points_y, color=color, marker=
|
|
483
|
-
|
|
541
|
+
_core.scatter(cell_points_x, cell_points_y, color=color, marker="█")
|
|
542
|
+
|
|
484
543
|
# Set axis limits and labels to show the grid properly
|
|
485
544
|
_core.xlim(-0.5, cols - 0.5)
|
|
486
545
|
_core.ylim(-0.5, rows - 0.5)
|
|
487
|
-
_core.xlabel(
|
|
488
|
-
_core.ylabel(
|
|
489
|
-
|
|
546
|
+
_core.xlabel("Column")
|
|
547
|
+
_core.ylabel("Row")
|
|
548
|
+
|
|
490
549
|
def _draw_filled_heatmap(self, matrix, colorscale):
|
|
491
550
|
"""Draw a heatmap using filled rectangular blocks for each cell"""
|
|
492
551
|
if not matrix or not matrix[0]:
|
|
493
552
|
return
|
|
494
|
-
|
|
553
|
+
|
|
495
554
|
rows = len(matrix)
|
|
496
555
|
cols = len(matrix[0])
|
|
497
|
-
|
|
556
|
+
|
|
498
557
|
# Flatten and normalize the data for color mapping
|
|
499
558
|
flat_data = [val for row in matrix for val in row]
|
|
500
559
|
min_val = min(flat_data)
|
|
501
560
|
max_val = max(flat_data)
|
|
502
561
|
value_range = max_val - min_val if max_val != min_val else 1
|
|
503
|
-
|
|
562
|
+
|
|
504
563
|
# Define color palette
|
|
505
564
|
color_palettes = {
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
565
|
+
"plasma": ["black", "purple", "magenta", "red", "orange", "yellow"],
|
|
566
|
+
"viridis": ["black", "blue", "green", "bright green", "yellow"],
|
|
567
|
+
"cool": ["cyan", "blue", "magenta", "white"],
|
|
568
|
+
"hot": ["black", "red", "orange", "yellow", "white"],
|
|
569
|
+
"default": ["blue", "cyan", "green", "yellow", "red", "magenta"],
|
|
511
570
|
}
|
|
512
|
-
colors = color_palettes.get(colorscale, color_palettes[
|
|
513
|
-
|
|
571
|
+
colors = color_palettes.get(colorscale, color_palettes["default"])
|
|
572
|
+
|
|
514
573
|
# Create filled rectangles for each cell using bar charts
|
|
515
574
|
for row_idx in range(rows):
|
|
516
575
|
row_data = matrix[row_idx]
|
|
517
576
|
y_center = rows - row_idx - 1 # Flip so row 0 is at top
|
|
518
|
-
|
|
577
|
+
|
|
519
578
|
for col_idx, value in enumerate(row_data):
|
|
520
579
|
# Normalize value to get color
|
|
521
580
|
normalized = (value - min_val) / value_range
|
|
522
581
|
color_idx = int(normalized * (len(colors) - 1))
|
|
523
582
|
color = colors[min(color_idx, len(colors) - 1)]
|
|
524
|
-
|
|
583
|
+
|
|
525
584
|
# Create a filled rectangle using horizontal bar at this cell position
|
|
526
585
|
# Bar from col_idx-0.4 to col_idx+0.4, at y_center with height 0.8
|
|
527
586
|
x_positions = []
|
|
528
587
|
y_positions = []
|
|
529
|
-
|
|
588
|
+
|
|
530
589
|
# Fill the rectangle with a dense grid of points
|
|
531
590
|
x_steps = 20 # More density for smoother appearance
|
|
532
591
|
y_steps = 8
|
|
533
|
-
|
|
592
|
+
|
|
534
593
|
for i in range(x_steps + 1):
|
|
535
594
|
for j in range(y_steps + 1):
|
|
536
595
|
x_offset = (i / x_steps - 0.5) * 0.9 # -0.45 to +0.45
|
|
537
596
|
y_offset = (j / y_steps - 0.5) * 0.9 # -0.45 to +0.45
|
|
538
597
|
x_positions.append(col_idx + x_offset)
|
|
539
598
|
y_positions.append(y_center + y_offset)
|
|
540
|
-
|
|
599
|
+
|
|
541
600
|
# Draw all points for this cell with the same color
|
|
542
601
|
if x_positions and y_positions:
|
|
543
|
-
_core.scatter(x_positions, y_positions, color=color, marker=
|
|
544
|
-
|
|
602
|
+
_core.scatter(x_positions, y_positions, color=color, marker="█")
|
|
603
|
+
|
|
545
604
|
# Set axis limits and labels to show the grid properly
|
|
546
605
|
_core.xlim(-0.5, cols - 0.5)
|
|
547
606
|
_core.ylim(-0.5, rows - 0.5)
|
|
548
|
-
_core.xlabel(
|
|
549
|
-
_core.ylabel(
|
|
607
|
+
_core.xlabel("Column")
|
|
608
|
+
_core.ylabel("Row")
|
|
550
609
|
|
|
551
610
|
|
|
552
611
|
class MatrixChart(Chart):
|
|
553
612
|
"""
|
|
554
613
|
Specialized class for matrix plotting with advanced features
|
|
555
614
|
"""
|
|
556
|
-
|
|
557
|
-
def __init__(
|
|
615
|
+
|
|
616
|
+
def __init__(
|
|
617
|
+
self,
|
|
618
|
+
matrix,
|
|
619
|
+
marker=None,
|
|
620
|
+
style=None,
|
|
621
|
+
fast=False,
|
|
622
|
+
use_banners=False,
|
|
623
|
+
banner_title=None,
|
|
624
|
+
):
|
|
558
625
|
"""Initialize a matrix plot"""
|
|
559
626
|
super().__init__(use_banners, banner_title)
|
|
560
627
|
self.matrix = matrix
|
|
561
|
-
self._data.append(
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
628
|
+
self._data.append(
|
|
629
|
+
{
|
|
630
|
+
"type": "matrix",
|
|
631
|
+
"matrix": matrix,
|
|
632
|
+
"marker": marker,
|
|
633
|
+
"style": style,
|
|
634
|
+
"fast": fast,
|
|
635
|
+
}
|
|
636
|
+
)
|
|
637
|
+
|
|
569
638
|
def show(self):
|
|
570
639
|
"""Render and display the matrix plot"""
|
|
571
640
|
_core.clear_figure()
|
|
572
|
-
|
|
573
|
-
if self._config[
|
|
574
|
-
_core.title(self._config[
|
|
575
|
-
if self._config[
|
|
576
|
-
_core.plot_size(self._config[
|
|
577
|
-
|
|
641
|
+
|
|
642
|
+
if self._config["title"]:
|
|
643
|
+
_core.title(self._config["title"])
|
|
644
|
+
if self._config["width"] or self._config["height"]:
|
|
645
|
+
_core.plot_size(self._config["width"], self._config["height"])
|
|
646
|
+
|
|
578
647
|
for data_item in self._data:
|
|
579
|
-
if data_item[
|
|
648
|
+
if data_item["type"] == "matrix":
|
|
580
649
|
_core.matrix_plot(
|
|
581
|
-
data_item[
|
|
582
|
-
marker=data_item[
|
|
583
|
-
style=data_item[
|
|
584
|
-
fast=data_item[
|
|
650
|
+
data_item["matrix"],
|
|
651
|
+
marker=data_item["marker"],
|
|
652
|
+
style=data_item["style"],
|
|
653
|
+
fast=data_item["fast"],
|
|
585
654
|
)
|
|
586
|
-
|
|
655
|
+
|
|
587
656
|
_core.show()
|
|
588
657
|
return self
|
|
589
658
|
|
|
@@ -592,43 +661,47 @@ class StemChart(Chart):
|
|
|
592
661
|
"""
|
|
593
662
|
Specialized class for stem plots (lollipop charts)
|
|
594
663
|
"""
|
|
595
|
-
|
|
596
|
-
def __init__(
|
|
664
|
+
|
|
665
|
+
def __init__(
|
|
666
|
+
self,
|
|
667
|
+
x,
|
|
668
|
+
y,
|
|
669
|
+
color=None,
|
|
670
|
+
orientation="vertical",
|
|
671
|
+
use_banners=False,
|
|
672
|
+
banner_title=None,
|
|
673
|
+
):
|
|
597
674
|
"""Initialize a stem chart"""
|
|
598
675
|
super().__init__(use_banners, banner_title)
|
|
599
676
|
self.x = x
|
|
600
677
|
self.y = y
|
|
601
678
|
self.orientation = orientation
|
|
602
679
|
# Use vertical lines to create stem effect
|
|
603
|
-
self._data.append(
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
'color': color,
|
|
608
|
-
'orientation': orientation
|
|
609
|
-
})
|
|
610
|
-
|
|
680
|
+
self._data.append(
|
|
681
|
+
{"type": "stem", "x": x, "y": y, "color": color, "orientation": orientation}
|
|
682
|
+
)
|
|
683
|
+
|
|
611
684
|
def show(self):
|
|
612
685
|
"""Render and display the stem chart"""
|
|
613
686
|
_core.clear_figure()
|
|
614
|
-
|
|
615
|
-
if self._config[
|
|
616
|
-
_core.title(self._config[
|
|
617
|
-
if self._config[
|
|
618
|
-
_core.xlabel(self._config[
|
|
619
|
-
if self._config[
|
|
620
|
-
_core.ylabel(self._config[
|
|
621
|
-
if self._config[
|
|
622
|
-
_core.plot_size(self._config[
|
|
623
|
-
|
|
687
|
+
|
|
688
|
+
if self._config["title"]:
|
|
689
|
+
_core.title(self._config["title"])
|
|
690
|
+
if self._config["x_label"]:
|
|
691
|
+
_core.xlabel(self._config["x_label"])
|
|
692
|
+
if self._config["y_label"]:
|
|
693
|
+
_core.ylabel(self._config["y_label"])
|
|
694
|
+
if self._config["width"] or self._config["height"]:
|
|
695
|
+
_core.plot_size(self._config["width"], self._config["height"])
|
|
696
|
+
|
|
624
697
|
for data_item in self._data:
|
|
625
|
-
if data_item[
|
|
698
|
+
if data_item["type"] == "stem":
|
|
626
699
|
# Create stem plot using scatter points only for now
|
|
627
700
|
# Full stem functionality would require extending core API
|
|
628
|
-
_core.scatter(
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
701
|
+
_core.scatter(
|
|
702
|
+
data_item["x"], data_item["y"], color=data_item["color"], marker="●"
|
|
703
|
+
) # Use solid dot for stem heads
|
|
704
|
+
|
|
632
705
|
_core.show()
|
|
633
706
|
return self
|
|
634
707
|
|
|
@@ -637,75 +710,77 @@ class Legend:
|
|
|
637
710
|
"""
|
|
638
711
|
Legend class for adding legends to any chart type
|
|
639
712
|
"""
|
|
640
|
-
|
|
713
|
+
|
|
641
714
|
def __init__(self):
|
|
642
715
|
self.items = []
|
|
643
|
-
self.position =
|
|
644
|
-
self.style =
|
|
716
|
+
self.position = "upper right"
|
|
717
|
+
self.style = "box"
|
|
645
718
|
self.show_border = True
|
|
646
|
-
|
|
719
|
+
|
|
647
720
|
def add(self, label, color=None, marker=None, line_style=None):
|
|
648
721
|
"""
|
|
649
722
|
Add an item to the legend
|
|
650
|
-
|
|
723
|
+
|
|
651
724
|
Args:
|
|
652
725
|
label (str): Text label for the legend item
|
|
653
726
|
color (str): Color for the legend item
|
|
654
727
|
marker (str): Marker style for the legend item
|
|
655
728
|
line_style (str): Line style for the legend item
|
|
656
729
|
"""
|
|
657
|
-
self.items.append(
|
|
658
|
-
|
|
659
|
-
|
|
660
|
-
|
|
661
|
-
|
|
662
|
-
|
|
663
|
-
|
|
664
|
-
|
|
730
|
+
self.items.append(
|
|
731
|
+
{
|
|
732
|
+
"label": label,
|
|
733
|
+
"color": color or "default",
|
|
734
|
+
"marker": marker or "■",
|
|
735
|
+
"line_style": line_style or "solid",
|
|
736
|
+
}
|
|
737
|
+
)
|
|
738
|
+
return self
|
|
739
|
+
|
|
665
740
|
def set_position(self, pos):
|
|
666
741
|
"""Set legend position ('upper right', 'upper left', 'lower right', 'lower left')"""
|
|
667
742
|
self.position = pos
|
|
668
743
|
return self
|
|
669
|
-
|
|
744
|
+
|
|
670
745
|
def set_style(self, style_name):
|
|
671
746
|
"""Set legend style ('box', 'plain')"""
|
|
672
747
|
self.style = style_name
|
|
673
748
|
return self
|
|
674
|
-
|
|
749
|
+
|
|
675
750
|
def set_border(self, show=True):
|
|
676
751
|
"""Show or hide legend border"""
|
|
677
752
|
self.show_border = show
|
|
678
753
|
return self
|
|
679
|
-
|
|
754
|
+
|
|
680
755
|
def apply_to_chart(self, chart_instance):
|
|
681
756
|
"""Apply this legend to a chart instance"""
|
|
682
757
|
# Set this legend as the chart's legend (replace any existing legend)
|
|
683
758
|
chart_instance._legend = self
|
|
684
759
|
return self
|
|
685
|
-
|
|
760
|
+
|
|
686
761
|
def render_legend_text(self):
|
|
687
762
|
"""Generate legend text representation"""
|
|
688
763
|
if not self.items:
|
|
689
764
|
return []
|
|
690
|
-
|
|
765
|
+
|
|
691
766
|
legend_lines = []
|
|
692
|
-
if self.show_border and self.style ==
|
|
767
|
+
if self.show_border and self.style == "box":
|
|
693
768
|
legend_lines.append("┌─ Legend ─┐")
|
|
694
|
-
|
|
769
|
+
|
|
695
770
|
for item in self.items:
|
|
696
|
-
marker = item[
|
|
697
|
-
label = item[
|
|
771
|
+
marker = item["marker"]
|
|
772
|
+
label = item["label"]
|
|
698
773
|
# Use color-coded markers if available
|
|
699
|
-
if self.style ==
|
|
774
|
+
if self.style == "box":
|
|
700
775
|
legend_lines.append(f"│ {marker} {label}")
|
|
701
776
|
else:
|
|
702
777
|
legend_lines.append(f"{marker} {label}")
|
|
703
|
-
|
|
704
|
-
if self.show_border and self.style ==
|
|
778
|
+
|
|
779
|
+
if self.show_border and self.style == "box":
|
|
705
780
|
legend_lines.append("└──────────┘")
|
|
706
|
-
|
|
781
|
+
|
|
707
782
|
return legend_lines
|
|
708
|
-
|
|
783
|
+
|
|
709
784
|
def show(self):
|
|
710
785
|
"""Display the legend independently"""
|
|
711
786
|
legend_text = self.render_legend_text()
|
|
@@ -719,14 +794,16 @@ class PlotextAPI:
|
|
|
719
794
|
Modern functional API that provides cleaner function-based interface
|
|
720
795
|
while maintaining the flexibility of the original plotext.
|
|
721
796
|
"""
|
|
722
|
-
|
|
797
|
+
|
|
723
798
|
@staticmethod
|
|
724
799
|
def create_chart(use_banners=False, banner_title=None):
|
|
725
800
|
"""Create a new Chart instance"""
|
|
726
801
|
return Chart(use_banners, banner_title)
|
|
727
|
-
|
|
802
|
+
|
|
728
803
|
@staticmethod
|
|
729
|
-
def quick_scatter(
|
|
804
|
+
def quick_scatter(
|
|
805
|
+
x, y, title=None, xlabel=None, ylabel=None, use_banners=False, banner_title=None
|
|
806
|
+
):
|
|
730
807
|
"""Quickly create and display a scatter plot"""
|
|
731
808
|
chart = Chart(use_banners, banner_title)
|
|
732
809
|
chart.scatter(x, y)
|
|
@@ -738,9 +815,11 @@ class PlotextAPI:
|
|
|
738
815
|
chart.ylabel(ylabel)
|
|
739
816
|
chart.show()
|
|
740
817
|
return chart
|
|
741
|
-
|
|
818
|
+
|
|
742
819
|
@staticmethod
|
|
743
|
-
def quick_line(
|
|
820
|
+
def quick_line(
|
|
821
|
+
x, y, title=None, xlabel=None, ylabel=None, use_banners=False, banner_title=None
|
|
822
|
+
):
|
|
744
823
|
"""Quickly create and display a line plot"""
|
|
745
824
|
chart = Chart(use_banners, banner_title)
|
|
746
825
|
chart.line(x, y)
|
|
@@ -752,9 +831,16 @@ class PlotextAPI:
|
|
|
752
831
|
chart.ylabel(ylabel)
|
|
753
832
|
chart.show()
|
|
754
833
|
return chart
|
|
755
|
-
|
|
834
|
+
|
|
756
835
|
@staticmethod
|
|
757
|
-
def quick_bar(
|
|
836
|
+
def quick_bar(
|
|
837
|
+
labels,
|
|
838
|
+
values,
|
|
839
|
+
title=None,
|
|
840
|
+
horizontal=False,
|
|
841
|
+
use_banners=False,
|
|
842
|
+
banner_title=None,
|
|
843
|
+
):
|
|
758
844
|
"""Quickly create and display a bar chart"""
|
|
759
845
|
chart = Chart(use_banners, banner_title)
|
|
760
846
|
chart.bar(labels, values, horizontal=horizontal)
|
|
@@ -762,27 +848,27 @@ class PlotextAPI:
|
|
|
762
848
|
chart.title(title)
|
|
763
849
|
chart.show()
|
|
764
850
|
return chart
|
|
765
|
-
|
|
851
|
+
|
|
766
852
|
@staticmethod
|
|
767
853
|
def enable_banners(enabled=True, default_title="Plotext Chart"):
|
|
768
854
|
"""Globally enable or disable banner mode"""
|
|
769
855
|
set_output_mode(enabled, default_title)
|
|
770
|
-
|
|
856
|
+
|
|
771
857
|
@staticmethod
|
|
772
858
|
def log_info(message):
|
|
773
859
|
"""Output info message using chuk-term"""
|
|
774
860
|
info(message)
|
|
775
|
-
|
|
861
|
+
|
|
776
862
|
@staticmethod
|
|
777
863
|
def log_success(message):
|
|
778
864
|
"""Output success message using chuk-term"""
|
|
779
865
|
success(message)
|
|
780
|
-
|
|
866
|
+
|
|
781
867
|
@staticmethod
|
|
782
868
|
def log_warning(message):
|
|
783
869
|
"""Output warning message using chuk-term"""
|
|
784
870
|
warning(message)
|
|
785
|
-
|
|
871
|
+
|
|
786
872
|
@staticmethod
|
|
787
873
|
def log_error(message):
|
|
788
874
|
"""Output error message using chuk-term"""
|
|
@@ -805,24 +891,24 @@ log_error = api.log_error
|
|
|
805
891
|
|
|
806
892
|
# Export specialized chart classes
|
|
807
893
|
__all__ = [
|
|
808
|
-
|
|
809
|
-
|
|
810
|
-
|
|
811
|
-
|
|
812
|
-
|
|
813
|
-
|
|
814
|
-
|
|
815
|
-
|
|
816
|
-
|
|
817
|
-
|
|
818
|
-
|
|
819
|
-
|
|
820
|
-
|
|
821
|
-
|
|
822
|
-
|
|
823
|
-
|
|
824
|
-
|
|
825
|
-
|
|
826
|
-
|
|
827
|
-
|
|
828
|
-
]
|
|
894
|
+
"Chart",
|
|
895
|
+
"ScatterChart",
|
|
896
|
+
"LineChart",
|
|
897
|
+
"BarChart",
|
|
898
|
+
"HistogramChart",
|
|
899
|
+
"CandlestickChart",
|
|
900
|
+
"HeatmapChart",
|
|
901
|
+
"MatrixChart",
|
|
902
|
+
"StemChart",
|
|
903
|
+
"Legend",
|
|
904
|
+
"PlotextAPI",
|
|
905
|
+
"create_chart",
|
|
906
|
+
"quick_scatter",
|
|
907
|
+
"quick_line",
|
|
908
|
+
"quick_bar",
|
|
909
|
+
"enable_banners",
|
|
910
|
+
"log_info",
|
|
911
|
+
"log_success",
|
|
912
|
+
"log_warning",
|
|
913
|
+
"log_error",
|
|
914
|
+
]
|