plotext-plus 1.0.8__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/utils.py CHANGED
@@ -1,47 +1,71 @@
1
1
  # This file contains some plotext functions which are only available to the top main level and not to sub figures (which are written in _figure.py and _monitor.py). These are functions which requires some coding and would be too long to be added directly in _core.py
2
2
 
3
- from plotext_plus._utility import marker_codes, hd_symbols, sin
4
- from plotext_plus._figure import _figure_class
5
- from plotext_plus._utility import themes as _themes
6
- import plotext_plus._utility as ut
7
- from time import time, sleep
8
- from math import sqrt, ceil
9
3
  import datetime as dt
4
+ from math import ceil
5
+ from math import sqrt
6
+ from time import sleep
7
+ from time import time
8
+
9
+ import plotext_plus._utility as ut
10
+ from plotext_plus._figure import _FigureClass
11
+ from plotext_plus._utility import hd_symbols
12
+ from plotext_plus._utility import marker_codes
13
+ from plotext_plus._utility import themes as _themes
10
14
 
11
- figure = _figure_class() # the main figure at top level
15
+ figure = _FigureClass() # the main figure at top level
12
16
 
13
17
  ##############################################
14
18
  ####### Simple Bar Functions ########
15
19
  ##############################################
16
20
 
17
- def simple_bar(*args, width = None, marker = None, color = None, title = None):
21
+
22
+ def simple_bar(*args, width=None, marker=None, color=None, title=None):
18
23
  x, y = ut.set_data(*args)
19
24
  marker = ut.correct_marker(marker)
20
25
 
21
26
  color_ok = ut.is_color(color) or (isinstance(color, list) and len(color) == len(x))
22
27
  color = [color] if color_ok else None
23
28
 
24
- simple_stacked_bar(x, [y], width = width, marker = marker, colors = color, title = title)
29
+ simple_stacked_bar(x, [y], width=width, marker=marker, colors=color, title=title)
25
30
 
26
- def simple_stacked_bar(*args, width = None, marker = None, colors = None, title = None, labels = None):
27
- x, y, Y, width = ut.bar_data(*args, width = width)
31
+
32
+ def simple_stacked_bar(
33
+ *args, width=None, marker=None, colors=None, title=None, labels=None
34
+ ):
35
+ x, y, y_scaled, width = ut.bar_data(*args, width=width)
28
36
  marker = ut.correct_marker(marker)
29
-
30
- bars = len(Y); stacked_bars = len(Y[0])
31
37
 
32
- colors_ok1 = isinstance(colors, list) and isinstance(colors[0], list) and ut.matrix_size(colors) == [bars, stacked_bars]
38
+ bars = len(y_scaled)
39
+ stacked_bars = len(y_scaled[0])
40
+
41
+ colors_ok1 = (
42
+ isinstance(colors, list)
43
+ and isinstance(colors[0], list)
44
+ and ut.matrix_size(colors) == [bars, stacked_bars]
45
+ )
33
46
  colors_ok2 = isinstance(colors, list) and len(colors) == stacked_bars
34
- colors = ut.transpose(colors) if colors_ok1 else [colors] * bars if colors_ok2 else [ut.color_sequence[:stacked_bars]] * bars
47
+ colors = (
48
+ ut.transpose(colors)
49
+ if colors_ok1
50
+ else (
51
+ [colors] * bars if colors_ok2 else [ut.color_sequence[:stacked_bars]] * bars
52
+ )
53
+ )
35
54
 
36
55
  title = ut.get_title(title, width)
37
- bars = [ut.single_bar(x[i], Y[i], y[i], marker, colors[i]) for i in range(bars)]
56
+ bars = [ut.single_bar(x[i], y_scaled[i], y[i], marker, colors[i]) for i in range(bars)]
38
57
  labels = ut.get_simple_labels(marker, labels, colors[0], width)
39
- figure.monitor.matrix.canvas = title + '\n'.join(bars) + labels
58
+ figure.monitor.matrix.canvas = title + "\n".join(bars) + labels
40
59
  figure.monitor.fast_plot = True
41
60
 
42
- def simple_multiple_bar(*args, width = None, marker = None, colors = None, title = None, labels = None):
43
- x, y, Y, width = ut.bar_data(*args, width = width, mode='multiple')
44
- bars = len(Y); multiple_bars = len(Y[0]); lx = len(x[0])
61
+
62
+ def simple_multiple_bar(
63
+ *args, width=None, marker=None, colors=None, title=None, labels=None
64
+ ):
65
+ x, y, y_scaled, width = ut.bar_data(*args, width=width, mode="multiple")
66
+ bars = len(y_scaled)
67
+ multiple_bars = len(y_scaled[0])
68
+ lx = len(x[0])
45
69
  marker = ut.correct_marker(marker)
46
70
 
47
71
  colors_ok = isinstance(colors, list) and len(colors) == multiple_bars
@@ -49,78 +73,96 @@ def simple_multiple_bar(*args, width = None, marker = None, colors = None, title
49
73
 
50
74
  out = ut.get_title(title, width)
51
75
  for i in range(bars):
52
- xn = [x[i] if j == (multiple_bars - 1) // 2 else ut.space * lx for j in range(multiple_bars)]
53
- new = [ut.single_bar(xn[j], [Y[i][j]], y[j][i], marker, [colors[j]]) for j in range(multiple_bars)]
54
- out += '\n'.join(new)
55
- out += '\n\n' if i != bars - 1 else ''
76
+ xn = [
77
+ x[i] if j == (multiple_bars - 1) // 2 else ut.space * lx
78
+ for j in range(multiple_bars)
79
+ ]
80
+ new = [
81
+ ut.single_bar(xn[j], [y_scaled[i][j]], y[j][i], marker, [colors[j]])
82
+ for j in range(multiple_bars)
83
+ ]
84
+ out += "\n".join(new)
85
+ out += "\n\n" if i != bars - 1 else ""
56
86
  labels = ut.get_simple_labels(marker, labels, colors, width)
57
87
  figure.monitor.matrix.canvas = out + labels
58
88
  figure.monitor.fast_plot = True
59
89
 
90
+
60
91
  ##############################################
61
92
  ############# Play GIF ################
62
93
  ##############################################
63
94
 
95
+
64
96
  def play_gif(path):
65
- from PIL import Image, ImageSequence
97
+ from PIL import Image
98
+ from PIL import ImageSequence
99
+
66
100
  path = ut.correct_path(path)
67
101
  if not ut.is_file(path):
68
102
  return
69
103
  im = Image.open(path)
70
- index = 1
71
104
  for image in ImageSequence.Iterator(im):
72
105
  load_time = time()
73
106
  figure.clt()
74
- image = image.convert('RGB')
75
- figure.monitor._draw_image(image, fast = True)
107
+ image = image.convert("RGB")
108
+ figure.monitor._draw_image(image, fast=True)
76
109
  figure.show()
77
110
  load_time = time() - load_time
78
- frame_time = image.info['duration'] / 10 ** 3
111
+ frame_time = image.info["duration"] / 10**3
79
112
  if load_time < frame_time:
80
113
  sleep(frame_time - load_time)
81
-
114
+
115
+
82
116
  ##############################################
83
117
  ########## Video Functions ############
84
118
  ##############################################
85
119
 
86
- def play_video(path, from_youtube = False):
120
+
121
+ def play_video(path, from_youtube=False):
87
122
  path = ut.correct_path(path)
88
123
  if not ut.is_file(path):
89
124
  return
90
125
  _play_video(path, from_youtube)
91
126
 
127
+
92
128
  def play_youtube(url):
93
129
  import pafy
130
+
94
131
  video = pafy.new(url)
95
132
  best = video.getbest()
96
- _play_video(best.url, from_youtube = True)
133
+ _play_video(best.url, from_youtube=True)
134
+
97
135
 
98
136
  def get_youtube(url, path, log):
99
137
  import pafy
138
+
100
139
  video = pafy.new(url)
101
- best = video.getbest(preftype = "mp4")
140
+ best = video.getbest(preftype="mp4")
102
141
  path = "youtube-video.mp4" if path is None else path
103
142
  path = ut.correct_path(path)
104
- best.download(filepath = path, quiet = not log)
105
- print(ut.format_strings('YouTube video downloaded as', path)) if log else None
143
+ best.download(filepath=path, quiet=not log)
144
+ print(ut.format_strings("YouTube video downloaded as", path)) if log else None
106
145
 
107
- def _play_video(path, from_youtube = False):
146
+
147
+ def _play_video(path, from_youtube=False):
108
148
  import cv2
109
149
  from ffpyplayer.player import MediaPlayer
110
150
  from PIL import Image
151
+
111
152
  cap = cv2.VideoCapture(path)
112
- player = MediaPlayer(path)#, paused = True, loglevel = 'quiet');
113
- fr = 0;
153
+ player = MediaPlayer(path) # , paused = True, loglevel = 'quiet');
154
+ fr = 0
114
155
  while fr == 0:
115
156
  fr = cap.get(cv2.CAP_PROP_FPS)
116
- frame_time = 1 / fr
117
- #to_list = lambda frame: [[tuple(int(el) for el in tup) for tup in row] for row in frame]
118
- pt = lambda time: '{time:05.1f} '.format(time=round(10 ** 3 * time, 1))
157
+ frame_time = 1 / fr
158
+ # to_list = lambda frame: [[tuple(int(el) for el in tup) for tup in row] for row in frame]
159
+ def pt(time):
160
+ return f"{round(10 ** 3 * time, 1):05.1f} "
119
161
  real_time = video_time = 0
120
162
  while True:
121
163
  load_time = time()
122
- check_video, frame = cap.read();
123
- audio, check_audio = player.get_frame(show = False)
164
+ check_video, frame = cap.read()
165
+ audio, check_audio = player.get_frame(show=False)
124
166
  load_time = time() - load_time
125
167
  if not check_video:
126
168
  break
@@ -129,61 +171,73 @@ def _play_video(path, from_youtube = False):
129
171
  real_time += load_time
130
172
  video_time += frame_time
131
173
  show_time = 0
132
- shown = False
133
174
  if video_time >= real_time:
134
- shown = True
135
175
  show_time = time()
136
176
  frame = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB) if from_youtube else frame
137
- #frame = to_list(frame)
177
+ # frame = to_list(frame)
138
178
  image = Image.fromarray(frame)
139
-
179
+
140
180
  # Synchronized frame rendering - ensure each step completes before next
141
181
  figure.clt()
142
182
  # Small delay to ensure clear operation completes
143
183
  sleep(0.001) # 1ms delay
144
- figure.monitor._draw_image(image, fast = True)
184
+ figure.monitor._draw_image(image, fast=True)
145
185
  # Small delay to ensure image drawing completes before display
146
186
  sleep(0.001) # 1ms delay
147
187
  figure.show()
148
188
  # Brief delay after display to prevent frame overlap
149
189
  sleep(0.002) # 2ms delay for terminal rendering
150
-
190
+
151
191
  show_time = time() - show_time
152
192
  sleep_time = 0
153
193
  if real_time < video_time:
154
194
  sleep_time = time()
155
195
  sleep(video_time - real_time)
156
196
  sleep_time = time() - sleep_time
157
- total_time = load_time + show_time + sleep_time
197
+ load_time + show_time + sleep_time
158
198
  real_time += show_time + sleep_time
159
- #print('load: ' + pt(load_time), 'show: ' + pt(show_time), 'sleep: ' + pt(sleep_time), 'total: ' + pt(total_time), 'frame: ' + pt(frame_time), 'real: ' + pt(real_time), 'video: ' + pt(video_time), 'r/v:', round(real_time / video_time, 3)) if shown else None
199
+ # print('load: ' + pt(load_time), 'show: ' + pt(show_time), 'sleep: ' + pt(sleep_time), 'total: ' + pt(total_time), 'frame: ' + pt(frame_time), 'real: ' + pt(real_time), 'video: ' + pt(video_time), 'r/v:', round(real_time / video_time, 3)) if shown else None
160
200
  player.close_player()
161
201
  cap.release()
162
202
  cv2.destroyAllWindows()
163
203
  figure.clf()
164
204
 
205
+
165
206
  ##############################################
166
207
  ############ Utilities ###############
167
208
  ##############################################
168
209
 
169
- test_data_url = "https://raw.githubusercontent.com/piccolomo/plotext/master/data/data.txt"
170
- test_bar_data_url = "https://raw.githubusercontent.com/piccolomo/plotext/master/data/bar_data.txt"
171
- test_image_url = "https://raw.githubusercontent.com/piccolomo/plotext/master/data/cat.jpg"
172
- test_gif_url = "https://raw.githubusercontent.com/piccolomo/plotext/master/data/homer.gif"
173
- test_video_url = "https://raw.githubusercontent.com/piccolomo/plotext/master/data/moonwalk.mp4"
174
- test_youtube_url = 'https://www.youtube.com/watch?v=ZNAvVVc4b3E&t=75s'
210
+ test_data_url = (
211
+ "https://raw.githubusercontent.com/piccolomo/plotext/master/data/data.txt"
212
+ )
213
+ test_bar_data_url = (
214
+ "https://raw.githubusercontent.com/piccolomo/plotext/master/data/bar_data.txt"
215
+ )
216
+ test_image_url = (
217
+ "https://raw.githubusercontent.com/piccolomo/plotext/master/data/cat.jpg"
218
+ )
219
+ test_gif_url = (
220
+ "https://raw.githubusercontent.com/piccolomo/plotext/master/data/homer.gif"
221
+ )
222
+ test_video_url = (
223
+ "https://raw.githubusercontent.com/piccolomo/plotext/master/data/moonwalk.mp4"
224
+ )
225
+ test_youtube_url = "https://www.youtube.com/watch?v=ZNAvVVc4b3E&t=75s"
175
226
 
176
227
  ##############################################
177
228
  ######### Matplotlib Backend ##########
178
229
  ##############################################
179
230
 
180
- def from_matplotlib(fig, marker = None):
231
+
232
+ def from_matplotlib(fig, marker=None):
181
233
  fig.canvas.draw()
182
234
  slots = (rows, cols) = fig.axes[0].get_subplotspec().get_gridspec().get_geometry()
183
- figure.clf(); #clt()
235
+ figure.clf() # clt()
184
236
  figure.subplots(*slots)
185
- round10 = lambda data: [round(el, 10) for el in data]
186
- to_rgb = lambda rgb_norm: tuple([round(255 * el) for el in rgb_norm[:3]])
237
+ def round10(data):
238
+ return [round(el, 10) for el in data]
239
+ def to_rgb(rgb_norm):
240
+ return tuple([round(255 * el) for el in rgb_norm[:3]])
187
241
  figure.axes_color(to_rgb(fig.patch.get_facecolor()))
188
242
  for sub in fig.axes[:]:
189
243
  p = sub.get_subplotspec().get_geometry()[2]
@@ -200,20 +254,20 @@ def from_matplotlib(fig, marker = None):
200
254
  monitor.canvas_color(to_rgb(sub.get_facecolor()))
201
255
  for point in sub.collections:
202
256
  label = point.get_label()
203
- label = label if label[0] != '_' else ''
204
- #point.set_offset_position('data')
257
+ label = label if label[0] != "_" else ""
258
+ # point.set_offset_position('data')
205
259
  x, y = ut.transpose(point.get_offsets())
206
260
  color = [ut.to_rgb(point.to_rgba(el)) for el in point.get_facecolors()[0]]
207
261
  # can't find the right point colors
208
- monitor.scatter(x, y, label = label, marker = marker)
262
+ monitor.scatter(x, y, label=label, marker=marker)
209
263
  for line in sub.get_lines():
210
264
  label = line.get_label()
211
- label = label if label[0] != '_' else ''
265
+ label = label if label[0] != "_" else ""
212
266
  x, y = line.get_data()
213
- monitor.plot(x, y, marker = marker, color = line.get_c(), label = label)
267
+ monitor.plot(x, y, marker=marker, color=line.get_c(), label=label)
214
268
  for b in sub.patches:
215
269
  label = b.get_label()
216
- label = label if label[0] != '_' else ''
270
+ label = label if label[0] != "_" else ""
217
271
  color = b.get_facecolor()
218
272
  color = ut.to_rgb(color)
219
273
  box = b.get_bbox()
@@ -223,148 +277,194 @@ def from_matplotlib(fig, marker = None):
223
277
  fill = b.get_fill()
224
278
  fillx = fill if y0 == 0 else False
225
279
  filly = fill if x0 == 0 else False
226
- monitor.plot(x, y, fillx = fillx, filly = filly, marker = marker, color = color, label = label)
280
+ monitor.plot(
281
+ x, y, fillx=fillx, filly=filly, marker=marker, color=color, label=label
282
+ )
227
283
  monitor.xlim(*sub.get_xlim())
228
284
  monitor.ylim(*sub.get_ylim())
229
285
 
286
+
230
287
  ##############################################
231
288
  ####### Presentation Functions ########
232
289
  ##############################################
233
-
290
+
291
+
234
292
  def markers():
235
293
  markers = list(hd_symbols.keys())[::-1] + list(marker_codes.keys())
236
- l = len(markers)
237
- rows = int(sqrt(l))
238
- cols = ceil(l / rows)
294
+ marker_count = len(markers)
295
+ rows = int(sqrt(marker_count))
296
+ cols = ceil(marker_count / rows)
239
297
  y = ut.sin(1)
240
- figure.clf(); figure.theme('pro'); figure.xfrequency(0); figure.yfrequency(0); figure.frame(1)
298
+ figure.clf()
299
+ figure.theme("pro")
300
+ figure.xfrequency(0)
301
+ figure.yfrequency(0)
302
+ figure.frame(1)
241
303
  figure.subplots(rows, cols)
242
304
  figure.frame(0)
243
305
  for row in range(1, rows + 1):
244
306
  for col in range(1, cols + 1):
245
307
  i = (row - 1) * cols + col - 1
246
- if i < l:
308
+ if i < marker_count:
247
309
  subplot = figure.subplot(row, col)
248
310
  figure.frame(1)
249
- default = ' [default]' if markers[i] == 'hd' else ''
311
+ default = " [default]" if markers[i] == "hd" else ""
250
312
  subplot.title(markers[i] + default)
251
- subplot.scatter(y, marker = markers[i])
252
- subplot.ticks_style('bold')
253
- #figure.ticks_color(figure._utility.title_color)
313
+ subplot.scatter(y, marker=markers[i])
314
+ subplot.ticks_style("bold")
315
+ # figure.ticks_color(figure._utility.title_color)
254
316
  figure.show()
255
317
  figure.clf()
256
318
 
319
+
257
320
  def colors():
258
- print(ut.colorize("String Color Codes", style = 'bold'))
321
+ print(ut.colorize("String Color Codes", style="bold"))
259
322
  bg = "default"
260
- c = ut.no_duplicates([el.replace('+', '') for el in ut.colors if el not in ['default', 'black', 'white']])
261
- cp = [ut.colorize(ut.pad_string(el + '+', 10), el + '+', background = bg) for el in c]
262
- c = [ut.colorize(ut.pad_string(el, 10), el, background = bg) for el in c]
263
- c = [' ' + c[i] + cp[i] for i in range(len(c))]
264
- c = '\n'.join(c)
265
- print(' ' + ut.colorize(ut.pad_string('default', 20), background = bg))
266
- print(' ' + ut.colorize(ut.pad_string('black', 10), 'black', background = 'gray') + ut.colorize(ut.pad_string('white', 10), 'white', background = bg))
323
+ c = ut.no_duplicates(
324
+ [
325
+ el.replace("+", "")
326
+ for el in ut.colors
327
+ if el not in ["default", "black", "white"]
328
+ ]
329
+ )
330
+ cp = [ut.colorize(ut.pad_string(el + "+", 10), el + "+", background=bg) for el in c]
331
+ c = [ut.colorize(ut.pad_string(el, 10), el, background=bg) for el in c]
332
+ c = [" " + c[i] + cp[i] for i in range(len(c))]
333
+ c = "\n".join(c)
334
+ print(" " + ut.colorize(ut.pad_string("default", 20), background=bg))
335
+ print(
336
+ " "
337
+ + ut.colorize(ut.pad_string("black", 10), "black", background="gray")
338
+ + ut.colorize(ut.pad_string("white", 10), "white", background=bg)
339
+ )
267
340
  print(c)
268
341
  print()
269
- #print(colorize("\n\nInteger Color Codes:", style = ''))
270
- c = ut.colorize("Integer Color Codes", style = 'bold', show = False) + '\n'
342
+ # print(colorize("\n\nInteger Color Codes:", style = ''))
343
+ c = ut.colorize("Integer Color Codes", style="bold", show=False) + "\n"
271
344
  for row in range(16):
272
- cr = ' '
345
+ cr = " "
273
346
  for col in range(16):
274
347
  i = row * 16 + col
275
348
  cr += ut.colorize(ut.pad_string(i, 5), i)
276
- c += cr + '\n'
349
+ c += cr + "\n"
277
350
  print(c)
278
- c = '\n'
351
+ c = "\n"
279
352
  rgb = (100, 200, 85)
280
- rgb_string = '(' + ', '.join([str(el) for el in rgb]) + ')'
281
- print(ut.colorize("RGB Tuples like:", style = "bold"), ut.colorize(rgb_string, rgb, "bold"))
353
+ rgb_string = "(" + ", ".join([str(el) for el in rgb]) + ")"
354
+ print(
355
+ ut.colorize("RGB Tuples like:", style="bold"),
356
+ ut.colorize(rgb_string, rgb, "bold"),
357
+ )
358
+
282
359
 
283
360
  def styles():
284
- from plotext_plus._utility import styles, colorize, title_color
285
- c = [colorize(el, style = el) for el in styles]
286
- c = '\n'.join(c)
361
+ from plotext_plus._utility import colorize
362
+ from plotext_plus._utility import styles
363
+ from plotext_plus._utility import title_color
364
+
365
+ c = [colorize(el, style=el) for el in styles]
366
+ c = "\n".join(c)
287
367
  print(c)
288
- mul = 'bold italic dim'
289
- print('\n' + colorize('multiple styles are accepted, ', title_color) + 'eg: ' + colorize(mul, style = mul))
368
+ mul = "bold italic dim"
369
+ print(
370
+ "\n"
371
+ + colorize("multiple styles are accepted, ", title_color)
372
+ + "eg: "
373
+ + colorize(mul, style=mul)
374
+ )
375
+
290
376
 
291
377
  def themes():
292
378
  themes = list(_themes.keys())[::]
293
- l = len(themes)
294
- rows = int(sqrt(l))
295
- cols = ceil(l / rows)
296
- y1 = ut.sin(periods = 1)
297
- y2 = ut.sin(periods = 1, phase = -1)
379
+ theme_count = len(themes)
380
+ rows = int(sqrt(theme_count))
381
+ cols = ceil(theme_count / rows)
382
+ y1 = ut.sin(periods=1)
383
+ y2 = ut.sin(periods=1, phase=-1)
298
384
  figure.clf()
299
385
  figure.subplots(rows, cols)
300
386
  for row in range(1, rows + 1):
301
387
  for col in range(1, cols + 1):
302
388
  i = (row - 1) * cols + col - 1
303
- if i < l:
389
+ if i < theme_count:
304
390
  subplot = figure.subplot(row, col)
305
391
  subplot.theme(themes[i])
306
392
  subplot.title(themes[i])
307
- subplot.scatter(y1); subplot.plot(y2)
393
+ subplot.scatter(y1)
394
+ subplot.plot(y2)
308
395
  figure.show()
309
396
  figure.clf()
310
397
 
398
+
311
399
  ##############################################
312
400
  ########### Test Function #############
313
401
  ##############################################
314
402
 
403
+
315
404
  def test():
316
405
  import random
317
- figure.clf(); figure.clt()
318
- figure.date_form("d/m/Y");
406
+
407
+ figure.clf()
408
+ figure.clt()
409
+ figure.date_form("d/m/Y")
319
410
  figure.take_min()
320
411
  figure.plot_size(None, ut.terminal_height())
321
- #figure.plot_size(108, 70)
322
-
412
+ # figure.plot_size(108, 70)
413
+
323
414
  figure.plotsize(ut.tw(), ut.th() - 5)
324
415
  figure.subplots(2, 2)
325
-
416
+
326
417
  subplot = figure.subplot(1, 1)
327
418
  subplot.title("Multiple Axes Plot")
328
- subplot.canvas_color(66); subplot.axes_color(4); subplot.ticks_color(216); subplot.ticks_style('bold italic')
329
- y = ut.sin(periods = 1); l = len(y)
330
- subplot.scatter(y, label = "lower left")
331
- x = [figure.today_datetime() + dt.timedelta(days = i) for i in range(l)]; x = figure.datetimes_to_strings(x)
332
- subplot.plot(x, x, label = 'upper right - all dates', xside = 2, yside = 2)
333
- subplot.vline(l / 2, 'red')
419
+ subplot.canvas_color(66)
420
+ subplot.axes_color(4)
421
+ subplot.ticks_color(216)
422
+ subplot.ticks_style("bold italic")
423
+ y = ut.sin(periods=1)
424
+ data_length = len(y)
425
+ subplot.scatter(y, label="lower left")
426
+ x = [figure.today_datetime() + dt.timedelta(days=i) for i in range(data_length)]
427
+ x = figure.datetimes_to_strings(x)
428
+ subplot.plot(x, x, label="upper right - all dates", xside=2, yside=2)
429
+ subplot.vline(data_length / 2, "red")
334
430
  subplot.hline(0, 200)
335
- subplot.text("origin", l // 2, 0, color = 'red', alignment = 'center')
336
- subplot.xlabel('x lower'); subplot.xlabel('x upper', 2)
337
- subplot.ylabel('y left', 'left'); subplot.ylabel('y right', 'right')
338
- subplot.xfrequency(8); subplot.xfrequency(5, 2);
339
- subplot.yfrequency(3); subplot.yfrequency(5, 2);
340
- subplot.grid(1,1)
341
-
431
+ subplot.text("origin", data_length // 2, 0, color="red", alignment="center")
432
+ subplot.xlabel("x lower")
433
+ subplot.xlabel("x upper", 2)
434
+ subplot.ylabel("y left", "left")
435
+ subplot.ylabel("y right", "right")
436
+ subplot.xfrequency(8)
437
+ subplot.xfrequency(5, 2)
438
+ subplot.yfrequency(3)
439
+ subplot.yfrequency(5, 2)
440
+ subplot.grid(1, 1)
441
+
342
442
  subplot = figure.subplot(1, 2)
343
- subplot.theme('innocent')
443
+ subplot.theme("innocent")
344
444
  xb = ["Sausage", "Pepperoni", "Mushrooms", "Cheese", "Chicken", "Beef"]
345
445
  y1 = [36, 14, 11, 8, 7, 4]
346
446
  y2 = [20, 12, 35, 15, 4, 5]
347
- subplot.stacked_bar(xb, [y1, y2], labels = ["men", "women"])
447
+ subplot.stacked_bar(xb, [y1, y2], labels=["men", "women"])
348
448
 
349
449
  subplot = figure.subplot(2, 1)
350
- subplot.theme('dreamland')
351
- ld = 7 * 10 ** 4
450
+ subplot.theme("dreamland")
451
+ ld = 7 * 10**4
352
452
  data = [random.gauss(0, 1) for el in range(10 * ld)]
353
- subplot.hist(data, bins = 60, label="mean 0")
354
- subplot.frame(1); #subplot.xaxes(1, 0); subplot.yaxes(1, 0)
355
-
453
+ subplot.hist(data, bins=60, label="mean 0")
454
+ subplot.frame(1) # subplot.xaxes(1, 0); subplot.yaxes(1, 0)
455
+
356
456
  subplot = figure.subplot(2, 2)
357
- subplot.canvas_color('gray+'); subplot.axes_color('gray+')
358
- ut.download(test_image_url, 'cat.jpg')
359
- subplot.image_plot('cat.jpg', grayscale = False)
360
- ut.delete_file('cat.jpg')
361
- subplot.title('A very Cute Cat')
457
+ subplot.canvas_color("gray+")
458
+ subplot.axes_color("gray+")
459
+ ut.download(test_image_url, "cat.jpg")
460
+ subplot.image_plot("cat.jpg", grayscale=False)
461
+ ut.delete_file("cat.jpg")
462
+ subplot.title("A very Cute Cat")
362
463
  subplot.frame(0)
363
464
 
364
- #figure.plotsize(0, 0)
465
+ # figure.plotsize(0, 0)
365
466
  figure.show()
366
467
  figure._get_time()
367
- figure.save_fig('test.txt')
368
- figure.save_fig('test.html')
369
- #figure.clf()
370
-
468
+ figure.save_fig("test.txt")
469
+ figure.save_fig("test.html")
470
+ # figure.clf()
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: plotext_plus
3
- Version: 1.0.8
3
+ Version: 1.0.10
4
4
  Summary: Modern terminal plotting library with enhanced visual features, themes, and AI integration
5
5
  Project-URL: Homepage, https://github.com/ccmitchellusa/plotext_plus
6
6
  Project-URL: Repository, https://github.com/ccmitchellusa/plotext_plus.git
@@ -23,6 +23,7 @@ Classifier: Topic :: Scientific/Engineering :: Visualization
23
23
  Classifier: Topic :: Software Development :: Libraries :: Python Modules
24
24
  Classifier: Topic :: Terminals
25
25
  Requires-Python: >=3.11
26
+ Requires-Dist: chuk-mcp-server>=0.3.5
26
27
  Requires-Dist: chuk-term>=0.1.0
27
28
  Requires-Dist: shtab>=1.7.2
28
29
  Provides-Extra: completion
@@ -30,7 +31,7 @@ Requires-Dist: shtab; extra == 'completion'
30
31
  Provides-Extra: image
31
32
  Requires-Dist: pillow>=8.4; extra == 'image'
32
33
  Provides-Extra: mcp
33
- Requires-Dist: chuk-mcp-server>=0.2.3; extra == 'mcp'
34
+ Requires-Dist: chuk-mcp-server>=0.3.5; extra == 'mcp'
34
35
  Provides-Extra: video
35
36
  Requires-Dist: ffpyplayer>=4.3.5; extra == 'video'
36
37
  Requires-Dist: opencv-python>=4.5.5; extra == 'video'
@@ -301,3 +302,7 @@ plt.theme('professional')
301
302
  plt.plot([1,2,3], [1,4,2])
302
303
  plt.show()
303
304
  ```
305
+
306
+ ## 🛠️ Development & Build System
307
+
308
+ Plotext+ includes a comprehensive build system with modern tooling. See **[Build Documentation](docs/build.md)** for complete setup, testing, publishing, and deployment instructions.