plotext-plus 1.0.1__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.
@@ -0,0 +1,370 @@
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
+
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
+ import datetime as dt
10
+
11
+ figure = _figure_class() # the main figure at top level
12
+
13
+ ##############################################
14
+ ####### Simple Bar Functions ########
15
+ ##############################################
16
+
17
+ def simple_bar(*args, width = None, marker = None, color = None, title = None):
18
+ x, y = ut.set_data(*args)
19
+ marker = ut.correct_marker(marker)
20
+
21
+ color_ok = ut.is_color(color) or (isinstance(color, list) and len(color) == len(x))
22
+ color = [color] if color_ok else None
23
+
24
+ simple_stacked_bar(x, [y], width = width, marker = marker, colors = color, title = title)
25
+
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)
28
+ marker = ut.correct_marker(marker)
29
+
30
+ bars = len(Y); stacked_bars = len(Y[0])
31
+
32
+ colors_ok1 = isinstance(colors, list) and isinstance(colors[0], list) and ut.matrix_size(colors) == [bars, stacked_bars]
33
+ 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
35
+
36
+ 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)]
38
+ labels = ut.get_simple_labels(marker, labels, colors[0], width)
39
+ figure.monitor.matrix.canvas = title + '\n'.join(bars) + labels
40
+ figure.monitor.fast_plot = True
41
+
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])
45
+ marker = ut.correct_marker(marker)
46
+
47
+ colors_ok = isinstance(colors, list) and len(colors) == multiple_bars
48
+ colors = colors if colors_ok else ut.color_sequence[:multiple_bars]
49
+
50
+ out = ut.get_title(title, width)
51
+ 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 ''
56
+ labels = ut.get_simple_labels(marker, labels, colors, width)
57
+ figure.monitor.matrix.canvas = out + labels
58
+ figure.monitor.fast_plot = True
59
+
60
+ ##############################################
61
+ ############# Play GIF ################
62
+ ##############################################
63
+
64
+ def play_gif(path):
65
+ from PIL import Image, ImageSequence
66
+ path = ut.correct_path(path)
67
+ if not ut.is_file(path):
68
+ return
69
+ im = Image.open(path)
70
+ index = 1
71
+ for image in ImageSequence.Iterator(im):
72
+ load_time = time()
73
+ figure.clt()
74
+ image = image.convert('RGB')
75
+ figure.monitor._draw_image(image, fast = True)
76
+ figure.show()
77
+ load_time = time() - load_time
78
+ frame_time = image.info['duration'] / 10 ** 3
79
+ if load_time < frame_time:
80
+ sleep(frame_time - load_time)
81
+
82
+ ##############################################
83
+ ########## Video Functions ############
84
+ ##############################################
85
+
86
+ def play_video(path, from_youtube = False):
87
+ path = ut.correct_path(path)
88
+ if not ut.is_file(path):
89
+ return
90
+ _play_video(path, from_youtube)
91
+
92
+ def play_youtube(url):
93
+ import pafy
94
+ video = pafy.new(url)
95
+ best = video.getbest()
96
+ _play_video(best.url, from_youtube = True)
97
+
98
+ def get_youtube(url, path, log):
99
+ import pafy
100
+ video = pafy.new(url)
101
+ best = video.getbest(preftype = "mp4")
102
+ path = "youtube-video.mp4" if path is None else path
103
+ 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
106
+
107
+ def _play_video(path, from_youtube = False):
108
+ import cv2
109
+ from ffpyplayer.player import MediaPlayer
110
+ from PIL import Image
111
+ cap = cv2.VideoCapture(path)
112
+ player = MediaPlayer(path)#, paused = True, loglevel = 'quiet');
113
+ fr = 0;
114
+ while fr == 0:
115
+ 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))
119
+ real_time = video_time = 0
120
+ while True:
121
+ load_time = time()
122
+ check_video, frame = cap.read();
123
+ audio, check_audio = player.get_frame(show = False)
124
+ load_time = time() - load_time
125
+ if not check_video:
126
+ break
127
+ if load_time >= frame_time:
128
+ continue
129
+ real_time += load_time
130
+ video_time += frame_time
131
+ show_time = 0
132
+ shown = False
133
+ if video_time >= real_time:
134
+ shown = True
135
+ show_time = time()
136
+ frame = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB) if from_youtube else frame
137
+ #frame = to_list(frame)
138
+ image = Image.fromarray(frame)
139
+
140
+ # Synchronized frame rendering - ensure each step completes before next
141
+ figure.clt()
142
+ # Small delay to ensure clear operation completes
143
+ sleep(0.001) # 1ms delay
144
+ figure.monitor._draw_image(image, fast = True)
145
+ # Small delay to ensure image drawing completes before display
146
+ sleep(0.001) # 1ms delay
147
+ figure.show()
148
+ # Brief delay after display to prevent frame overlap
149
+ sleep(0.002) # 2ms delay for terminal rendering
150
+
151
+ show_time = time() - show_time
152
+ sleep_time = 0
153
+ if real_time < video_time:
154
+ sleep_time = time()
155
+ sleep(video_time - real_time)
156
+ sleep_time = time() - sleep_time
157
+ total_time = load_time + show_time + sleep_time
158
+ 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
160
+ player.close_player()
161
+ cap.release()
162
+ cv2.destroyAllWindows()
163
+ figure.clf()
164
+
165
+ ##############################################
166
+ ############ Utilities ###############
167
+ ##############################################
168
+
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'
175
+
176
+ ##############################################
177
+ ######### Matplotlib Backend ##########
178
+ ##############################################
179
+
180
+ def from_matplotlib(fig, marker = None):
181
+ fig.canvas.draw()
182
+ slots = (rows, cols) = fig.axes[0].get_subplotspec().get_gridspec().get_geometry()
183
+ figure.clf(); #clt()
184
+ 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]])
187
+ figure.axes_color(to_rgb(fig.patch.get_facecolor()))
188
+ for sub in fig.axes[:]:
189
+ p = sub.get_subplotspec().get_geometry()[2]
190
+ row = int((p - 0) / cols + 1)
191
+ col = p + 1 - (row - 1) * cols
192
+ monitor = figure.subplot(row, col)
193
+ monitor.xlabel(sub.get_xlabel())
194
+ monitor.ylabel(sub.get_ylabel())
195
+ monitor.title(sub.get_title())
196
+ monitor.xscale(sub.get_xscale())
197
+ monitor.yscale(sub.get_yscale())
198
+ monitor.xticks(round10(sub.get_xticks()))
199
+ monitor.yticks(round10(sub.get_yticks()))
200
+ monitor.canvas_color(to_rgb(sub.get_facecolor()))
201
+ for point in sub.collections:
202
+ label = point.get_label()
203
+ label = label if label[0] != '_' else ''
204
+ #point.set_offset_position('data')
205
+ x, y = ut.transpose(point.get_offsets())
206
+ color = [ut.to_rgb(point.to_rgba(el)) for el in point.get_facecolors()[0]]
207
+ # can't find the right point colors
208
+ monitor.scatter(x, y, label = label, marker = marker)
209
+ for line in sub.get_lines():
210
+ label = line.get_label()
211
+ label = label if label[0] != '_' else ''
212
+ x, y = line.get_data()
213
+ monitor.plot(x, y, marker = marker, color = line.get_c(), label = label)
214
+ for b in sub.patches:
215
+ label = b.get_label()
216
+ label = label if label[0] != '_' else ''
217
+ color = b.get_facecolor()
218
+ color = ut.to_rgb(color)
219
+ box = b.get_bbox()
220
+ x0, y0, x1, y1 = box.x0, box.y0, box.x1, box.y1
221
+ x = [x0, x0, x1, x1, x0]
222
+ y = [y0, y1, y1, y0, y0]
223
+ fill = b.get_fill()
224
+ fillx = fill if y0 == 0 else False
225
+ filly = fill if x0 == 0 else False
226
+ monitor.plot(x, y, fillx = fillx, filly = filly, marker = marker, color = color, label = label)
227
+ monitor.xlim(*sub.get_xlim())
228
+ monitor.ylim(*sub.get_ylim())
229
+
230
+ ##############################################
231
+ ####### Presentation Functions ########
232
+ ##############################################
233
+
234
+ def markers():
235
+ markers = list(hd_symbols.keys())[::-1] + list(marker_codes.keys())
236
+ l = len(markers)
237
+ rows = int(sqrt(l))
238
+ cols = ceil(l / rows)
239
+ y = ut.sin(1)
240
+ figure.clf(); figure.theme('pro'); figure.xfrequency(0); figure.yfrequency(0); figure.frame(1)
241
+ figure.subplots(rows, cols)
242
+ figure.frame(0)
243
+ for row in range(1, rows + 1):
244
+ for col in range(1, cols + 1):
245
+ i = (row - 1) * cols + col - 1
246
+ if i < l:
247
+ subplot = figure.subplot(row, col)
248
+ figure.frame(1)
249
+ default = ' [default]' if markers[i] == 'hd' else ''
250
+ 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)
254
+ figure.show()
255
+ figure.clf()
256
+
257
+ def colors():
258
+ print(ut.colorize("String Color Codes", style = 'bold'))
259
+ 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))
267
+ print(c)
268
+ print()
269
+ #print(colorize("\n\nInteger Color Codes:", style = ''))
270
+ c = ut.colorize("Integer Color Codes", style = 'bold', show = False) + '\n'
271
+ for row in range(16):
272
+ cr = ' '
273
+ for col in range(16):
274
+ i = row * 16 + col
275
+ cr += ut.colorize(ut.pad_string(i, 5), i)
276
+ c += cr + '\n'
277
+ print(c)
278
+ c = '\n'
279
+ 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"))
282
+
283
+ 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)
287
+ print(c)
288
+ mul = 'bold italic dim'
289
+ print('\n' + colorize('multiple styles are accepted, ', title_color) + 'eg: ' + colorize(mul, style = mul))
290
+
291
+ def themes():
292
+ 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)
298
+ figure.clf()
299
+ figure.subplots(rows, cols)
300
+ for row in range(1, rows + 1):
301
+ for col in range(1, cols + 1):
302
+ i = (row - 1) * cols + col - 1
303
+ if i < l:
304
+ subplot = figure.subplot(row, col)
305
+ subplot.theme(themes[i])
306
+ subplot.title(themes[i])
307
+ subplot.scatter(y1); subplot.plot(y2)
308
+ figure.show()
309
+ figure.clf()
310
+
311
+ ##############################################
312
+ ########### Test Function #############
313
+ ##############################################
314
+
315
+ def test():
316
+ import random
317
+ figure.clf(); figure.clt()
318
+ figure.date_form("d/m/Y");
319
+ figure.take_min()
320
+ figure.plot_size(None, ut.terminal_height())
321
+ #figure.plot_size(108, 70)
322
+
323
+ figure.plotsize(ut.tw(), ut.th() - 5)
324
+ figure.subplots(2, 2)
325
+
326
+ subplot = figure.subplot(1, 1)
327
+ 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')
334
+ 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
+
342
+ subplot = figure.subplot(1, 2)
343
+ subplot.theme('innocent')
344
+ xb = ["Sausage", "Pepperoni", "Mushrooms", "Cheese", "Chicken", "Beef"]
345
+ y1 = [36, 14, 11, 8, 7, 4]
346
+ y2 = [20, 12, 35, 15, 4, 5]
347
+ subplot.stacked_bar(xb, [y1, y2], labels = ["men", "women"])
348
+
349
+ subplot = figure.subplot(2, 1)
350
+ subplot.theme('dreamland')
351
+ ld = 7 * 10 ** 4
352
+ 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
+
356
+ 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')
362
+ subplot.frame(0)
363
+
364
+ #figure.plotsize(0, 0)
365
+ figure.show()
366
+ figure._get_time()
367
+ figure.save_fig('test.txt')
368
+ figure.save_fig('test.html')
369
+ #figure.clf()
370
+
@@ -0,0 +1,171 @@
1
+ import plotext_plus._utility as ut
2
+
3
+ class matrix_class():
4
+ def __init__(self):
5
+ self.set_size(0, 0)
6
+ self.set_axes_color()
7
+ self.set_canvas_area(0, 0, 0, 0)
8
+ self.set_canvas_color()
9
+ self.set_matrices()
10
+ self.set_canvas()
11
+
12
+ def set_size(self, cols, rows):
13
+ self.rows = rows; self.Rows = range(self.rows)
14
+ self.cols = cols; self.Cols = range(self.cols)
15
+ self.size = [self.rows, self.cols]
16
+
17
+ def update_size(self):
18
+ self.cols, self.rows = ut.matrix_size(self.marker)
19
+ self.Rows = range(self.rows); self.Cols = range(self.cols)
20
+ self.size = [self.rows, self.cols]
21
+
22
+ def set_axes_color(self, color = ut.no_color):
23
+ self.axes_color = color
24
+
25
+ def set_canvas_area(self, col1, col2, row1, row2):
26
+ self.Cols_canvas = range(col1, col2)
27
+ self.Rows_canvas = range(row1, row2)
28
+
29
+ def set_canvas_color(self, color = ut.no_color):
30
+ self.canvas_color = color
31
+
32
+ def in_canvas(self, col, row):
33
+ return col in self.Cols_canvas and row in self.Rows_canvas
34
+
35
+ def set_matrices(self):
36
+ self.marker = [[ut.space] * self.cols for row in self.Rows]
37
+ self.fullground = [[ut.no_color] * self.cols for row in self.Rows]
38
+ get_background = lambda col, row: self.canvas_color if self.in_canvas(col, row) else self.axes_color
39
+ self.background = [[get_background(col, row) for col in self.Cols] for row in self.Rows]
40
+ self.style = [[ut.no_color] * self.cols for row in self.Rows]
41
+
42
+ def legal(self, col, row):
43
+ return col in self.Cols and row in self.Rows
44
+
45
+ def get_marker(self, col, row):
46
+ return self.marker[row][col] #if self.legal(col, row) else "OUT"
47
+
48
+ def get_marker_row(self, row):
49
+ return self.marker[row] #if self.legal(0, row) else "OUT"
50
+
51
+ def get_marker_col(self, col):
52
+ return [self.marker[r][col] for r in self.Rows]#if self.legal(0, row) else "OUT"
53
+
54
+ def set_marker(self, col, row, marker):
55
+ self.marker[row][col] = marker
56
+
57
+ def set_fullground(self, col, row, fullground = None):
58
+ self.fullground[row][col] = fullground
59
+
60
+ def set_background(self, col, row, background = None):
61
+ self.background[row][col] = background
62
+
63
+ def set_style(self, col, row, style = None):
64
+ self.style[row][col] = style
65
+
66
+ def insert_element(self, col, row, marker, fullground = None, style = None, background = None, check_canvas = False):
67
+ test_canvas = True if check_canvas is False else col in self.Cols_canvas and row in self.Rows_canvas
68
+ if self.legal(col, row) and test_canvas:
69
+ self.set_marker(col, row, marker)
70
+ self.set_fullground(col, row, fullground) if fullground is not None else None
71
+ self.set_background(col, row, background) if background is not None else None
72
+ self.set_style(col, row, style) if style is not None else None
73
+
74
+ def add_horizontal_string(self, col, row, string, fullground = None, style = None, background = None, alignment = "left", check_space = False, check_canvas = False):
75
+ l = len(string); L = range(l)
76
+ col = col if alignment == "left" else col - l // 2 if alignment == "center" else col - l + 1 if alignment == "right" else ut.correct_coord(self.get_marker_row(row), string, col) # if dynamic
77
+ b, e = max(col - 1, 0), min(col + l + 1, self.cols)
78
+ test_space = all([self.get_marker(c, row) == ut.space for c in range(b, e)]) and col >= 0 and col + l <= self.cols if check_space else True
79
+ [self.insert_element(col + i, row, string[i], fullground, style, background, check_canvas) for i in L] if test_space else None
80
+ return test_space
81
+
82
+ def add_vertical_string(self, col, row, string, fullground = None, style = None, background = None, alignment = "bottom", check_canvas = False):
83
+ l = len(string); L = range(l)
84
+ row = row if alignment == "bottom" else row - l // 2 if alignment == "center" else row - l + 1 #if alignment == "top"
85
+ [self.insert_element(col, row + i, string[i], fullground, style, background, check_canvas) for i in L]
86
+
87
+ def add_multiple_horizontal_strings(self, col, row, string, fullground = None, style = None, background = None, alignment = "left", check_space = False, check_canvas = False):
88
+ strings = ''.join(string).split('\n'); S = len(strings)
89
+ [self.add_horizontal_string(col, row - s, strings[s], fullground, style, background, alignment, check_space, check_canvas) for s in range(S)]
90
+
91
+ def add_multiple_vertical_strings(self, col, row, string, fullground = None, style = None, background = None, alignment = "left", check_canvas = False):
92
+ strings = ''.join(string).split('\n'); S = len(strings)
93
+ [self.add_vertical_string(col + s, row, strings[s], fullground, style, background, alignment, check_canvas) for s in range(S)]
94
+
95
+ def get_colors(self, col, row):
96
+ return [self.fullground[row][col], self.style[row][col], self.background[row][col]] #if self.legal(col, row) else ["OUT"] * 3
97
+
98
+ def set_canvas(self):
99
+ canvas = ''
100
+ for row in self.Rows[::-1]:
101
+ for col in self.Cols:
102
+ marker = self.marker[row][col]
103
+ colors = self.get_colors(col, row)
104
+ if col == 0 or colors != self.get_colors(col - 1, row):
105
+ ansi = ut.colors_to_ansi(*colors)
106
+ canvas += ansi
107
+ canvas += marker
108
+ if col == self.cols - 1 or colors != self.get_colors(col + 1, row):
109
+ #ansi_next = colors_to_ansi(*colors_next)
110
+ canvas += ut.ansi_end #+ ansi_next
111
+ canvas += '\n'
112
+
113
+ self.canvas = canvas
114
+ #print(repr(canvas))
115
+ #self.canvas = '\n'.join([''.join(self.marker[row]) for row in self.Rows])
116
+ return self.canvas
117
+
118
+ def get_canvas(self):
119
+ return self.canvas
120
+
121
+ def hstack(self, extra):
122
+ self.marker = ut.hstack(self.marker, extra.marker)
123
+ self.fullground = ut.hstack(self.fullground, extra.fullground)
124
+ self.background = ut.hstack(self.background, extra.background)
125
+ self.style = ut.hstack(self.style, extra.style)
126
+ self.update_size()
127
+ self.canvas = '';
128
+
129
+ def vstack(self, extra):
130
+ self.marker = ut.vstack(self.marker, extra.marker)
131
+ self.fullground = ut.vstack(self.fullground, extra.fullground)
132
+ self.background = ut.vstack(self.background, extra.background)
133
+ self.style = ut.vstack(self.style, extra.style)
134
+ self.update_size()
135
+ self.canvas = ''
136
+
137
+ def to_html(self): # turns a matrix of character in html form
138
+ code = lambda color: "rgb" + str(color).replace(" ", "")
139
+ #html = "<body>\n<p style=\"font-family:courier; font-size:11pt;\">\n\n"
140
+ html = "<body> \n <code style = style=\"font-family:courier; \"font-size : 10pt;\"> \n\n"
141
+ for r in range(self.rows - 1, -1, -1):
142
+ for c in range(self.cols):
143
+ marker = self.get_marker(c, r)
144
+ color, style, background = self.get_colors(c, r)
145
+ marker = "&nbsp;" if marker == ut.space else marker
146
+ marker = '<b>' + marker + '</b>' if style == 'bold' else marker
147
+ marker = '<i>' + marker + '</i>' if style == 'italic' else marker
148
+ color = 'black' if color == ut.no_color else color
149
+ background = 'white' if background == ut.no_color else background
150
+ color = ut.to_rgb(color)
151
+ background = ut.to_rgb(background)
152
+ color = code(color)
153
+ background = code(background)
154
+ html += "<span style = \"color:" + color + "; background-color: " + background + "\">" + marker + "</span>"
155
+ html += " <br>\n\n"
156
+ html += "<code> \n </body>"
157
+ return html
158
+
159
+ def join_matrices(matrices): # from a matrix of matrix_class() objects to a single matrix
160
+ cols, rows = ut.matrix_size(matrices)
161
+ M = matrix_class()
162
+ for r in range(rows):
163
+ m_rows = matrices[r][0].rows
164
+ m = matrix_class()
165
+ m.set_size(0, m_rows)
166
+ m.set_matrices()
167
+ for c in range(cols):
168
+ m.hstack(matrices[r][c])
169
+ M.vstack(m)
170
+ return M
171
+