maxplotlibx 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,852 @@
1
+ # import sys; from os.path import dirname; sys.path.append(f'{dirname(__file__)}/../../')
2
+
3
+ # import matplotlib.pylab as pylab
4
+ import math
5
+ import pickle
6
+ from pathlib import Path
7
+
8
+ import _pickle as cPickle
9
+ import matplotlib.colors as mcolors
10
+ import matplotlib.pyplot as plt
11
+ import numpy as np
12
+ from matplotlib.collections import PatchCollection
13
+ from mpl_toolkits.mplot3d import Axes3D
14
+ from mpl_toolkits.mplot3d.art3d import Line3DCollection, Poly3DCollection
15
+
16
+
17
+ class Color:
18
+ def __init__(self, hex_color):
19
+ self.hx = hex_color
20
+ self.rgb = tuple(int(hex_color.lstrip("#")[i : i + 2], 16) for i in (0, 2, 4))
21
+
22
+ self.rgb_dec = [i / 255 for i in self.rgb]
23
+ self.rgb_dec_str = ["{:.6f}".format(i) for i in self.rgb_dec]
24
+
25
+ self.rgb_inv = tuple(np.subtract((256, 256, 256), self.rgb))
26
+ self.rgb_dec_inv = [1.0 - c for c in self.rgb_dec]
27
+ # self.pgf_col_str = '\definecolor{currentstroke}{rgb}{'
28
+ self.pgf_col_str = "{rgb}{"
29
+ self.pgf_col_str += self.rgb_dec_str[0] + ","
30
+ self.pgf_col_str += self.rgb_dec_str[1] + ","
31
+ self.pgf_col_str += self.rgb_dec_str[2] + "}%"
32
+
33
+ def invert(self):
34
+ inverted_color = Color(self.hx)
35
+
36
+ def define_color_str(self, name):
37
+ hex_str = self.hx.replace("#", "")
38
+ out_str = "\\definecolor{" + name + "}{HTML}{" + hex_str + "}"
39
+ out_str += " " * (70 - len(out_str)) + "% https://www.colorhexa.com/" + hex_str
40
+ return out_str
41
+
42
+ def __str__(self):
43
+ return self.hx
44
+
45
+
46
+ # https://matplotlib.org/stable/gallery/color/named_colors.html
47
+ def mcolors2mplcolors(colors):
48
+ names = sorted(colors, key=lambda c: tuple(mcolors.rgb_to_hsv(mcolors.to_rgb(c))))
49
+ col_dict = dict()
50
+ for name in names:
51
+ col_dict[name] = Color(colors[name])
52
+ return col_dict
53
+
54
+
55
+ def import_colors(cmap="pastel"):
56
+ col_dict = dict()
57
+ col_dict["pastel"] = mcolors2mplcolors(mcolors.CSS4_COLORS)
58
+ col_dict["cmap2"] = mcolors2mplcolors(mcolors.CSS4_COLORS)
59
+ col_dict["thesis_colors"] = mcolors2mplcolors(mcolors.CSS4_COLORS)
60
+
61
+ col_dict["pastel"]["white"] = Color("#ffffff")
62
+ col_dict["pastel"]["black"] = Color("#000000")
63
+ col_dict["pastel"]["yellow"] = Color("#FFFFB3")
64
+ col_dict["pastel"]["dkyellow"] = Color("#FFED6F")
65
+ col_dict["pastel"]["purple"] = Color("#BEBADA")
66
+ col_dict["pastel"]["dkpurple"] = Color("#BC80BD")
67
+ col_dict["pastel"]["red"] = Color("#FB8072")
68
+ col_dict["pastel"]["ltred"] = Color("#FFCCCB")
69
+ col_dict["pastel"]["dkred"] = Color("#CB0505")
70
+ col_dict["pastel"]["orange"] = Color("#FDB462")
71
+ col_dict["pastel"]["dkgold"] = Color("#B8860B")
72
+ col_dict["pastel"]["blue"] = Color("#80B1D3")
73
+ col_dict["pastel"]["dkblue"] = Color("#00008B")
74
+ col_dict["pastel"]["deepskyblue"] = Color("#1f78b4")
75
+ col_dict["pastel"]["green"] = Color("#B3DE69")
76
+ col_dict["pastel"]["ltgreen"] = Color("#CCEBC5")
77
+ col_dict["pastel"]["dkgreen"] = Color("#006400")
78
+ col_dict["pastel"]["bluegreen"] = Color("#8DD3C7")
79
+ col_dict["pastel"]["pink"] = Color("#FCCDE5")
80
+ col_dict["pastel"]["ltgray"] = Color("#D9D9D9")
81
+ col_dict["pastel"]["dkgray"] = Color("#515151")
82
+ col_dict["pastel"]["brown"] = Color("#D2691E")
83
+
84
+ col_dict["cmap2"]["white"] = Color("#ffffff")
85
+ col_dict["cmap2"]["black"] = Color("#000000")
86
+ col_dict["cmap2"]["yellow"] = Color("#ffff99")
87
+ col_dict["cmap2"]["dkyellow"] = Color("#FFED6F")
88
+ col_dict["cmap2"]["ltpurple"] = Color("#cab2d6")
89
+ col_dict["cmap2"]["purple"] = Color("#6a3d9a")
90
+ col_dict["cmap2"]["dkpurple"] = Color("#BC80BD")
91
+ col_dict["cmap2"]["red"] = Color("#e31a1c")
92
+ col_dict["cmap2"]["ltred"] = Color("#fb9a99")
93
+ col_dict["cmap2"]["dkred"] = Color("#CB0505")
94
+ col_dict["cmap2"]["ltorange"] = Color("#fdbf6f")
95
+ col_dict["cmap2"]["orange"] = Color("#ff7f00")
96
+ col_dict["cmap2"]["blue"] = Color("#1f78b4")
97
+ col_dict["cmap2"]["dkblue"] = Color("#00008B")
98
+ col_dict["cmap2"]["deepskyblue"] = Color("#1f78b4")
99
+ col_dict["cmap2"]["green"] = Color("#33a02c")
100
+ col_dict["cmap2"]["ltgreen"] = Color("#b2df8a")
101
+ col_dict["cmap2"]["dkgreen"] = Color("#006400")
102
+ col_dict["cmap2"]["bluegreen"] = Color("#8DD3C7")
103
+ col_dict["cmap2"]["pink"] = Color("#FCCDE5")
104
+ col_dict["cmap2"]["ltgray"] = Color("#D9D9D9")
105
+ col_dict["cmap2"]["dkgray"] = Color("#515151")
106
+ col_dict["cmap2"]["brown"] = Color("#b15928")
107
+
108
+
109
+ def import_col_list(cmap="cmap2"):
110
+ col_dict = import_colors(cmap)
111
+ col_list = [
112
+ col_dict["black"],
113
+ col_dict["blue"],
114
+ col_dict["red"],
115
+ col_dict["green"],
116
+ col_dict["orange"],
117
+ col_dict["purple"],
118
+ col_dict["gray"],
119
+ col_dict["brown"],
120
+ # col_dict['green'],
121
+ ]
122
+ return col_list
123
+
124
+
125
+ def id2color(id, cmap="cmap2"):
126
+ col_list = import_col_list(cmap=cmap)
127
+ return col_list[id % len(col_list)].hx
128
+
129
+
130
+ #
131
+ # ,------.,--. ,--.
132
+ # | .---'`--' ,---. ,--.,--.,--.--. ,---. ,---. ,---. ,-' '-.,--.,--. ,---.
133
+ # | `--, ,--.| .-. || || || .--'| .-. : ( .-' | .-. :'-. .-'| || || .-. |
134
+ # | |` | |' '-' '' '' '| | \ --. .-' `)\ --. | | ' '' '| '-' '
135
+ # `--' `--'.`- / `----' `--' `----' `----' `----' `--' `----' | |-'
136
+ # `---' `--'
137
+
138
+
139
+ linestyles = dict()
140
+ linestyles["solid"] = "solid" # Same as (0, ()) or '-'
141
+ linestyles["dotted"] = "dotted" # Same as (0, (1, 1)) or '.'
142
+ linestyles["dashed"] = "dashed" # Same as '--'
143
+ linestyles["dashdot"] = "dashdot" # Same as '-.'
144
+ linestyles["loosely dotted"] = (0, (1, 10))
145
+ linestyles["dotted"] = (0, (1, 1))
146
+ linestyles["densely dotted"] = (0, (1, 1))
147
+
148
+ linestyles["loosely dashed"] = (0, (5, 10))
149
+ linestyles["dashed"] = (0, (5, 5))
150
+ linestyles["densely dashed"] = (0, (5, 1))
151
+
152
+ linestyles["loosely dashdotted"] = (0, (3, 10, 1, 10))
153
+ linestyles["dashdotted"] = (0, (3, 5, 1, 5))
154
+ linestyles["densely dashdotted"] = (0, (3, 1, 1, 1))
155
+
156
+ linestyles["dashdotdotted"] = (0, (3, 5, 1, 5, 1, 5))
157
+ linestyles["loosely dashdotdotted"] = (0, (3, 10, 1, 10, 1, 10))
158
+ linestyles["densely dashdotdotted"] = (0, (3, 1, 1, 1, 1, 1))
159
+
160
+ linestyle_list = [linestyles[l] for l in linestyles]
161
+ linestyle_list_ordered = [
162
+ linestyles["solid"],
163
+ linestyles["densely dashdotted"],
164
+ linestyles["dashed"],
165
+ linestyles["dotted"],
166
+ ]
167
+
168
+
169
+ class figure:
170
+ def __init__(
171
+ self,
172
+ load_file="",
173
+ nx_subplots=1,
174
+ ny_subplots=1,
175
+ width=426.79135,
176
+ figsize=None,
177
+ scale_width=1,
178
+ dpi=300,
179
+ threeD=False,
180
+ ratio="golden",
181
+ legend=True,
182
+ axes_grid=False,
183
+ gridspec_kw={"wspace": 0.08, "hspace": 0.1},
184
+ legend_position="upper right",
185
+ filename="MaxFigureClassInstance",
186
+ directory="./",
187
+ cmap="cmap2",
188
+ fontsize=14,
189
+ tex_fonts=True,
190
+ ):
191
+ # if width == 'singlecol':
192
+ # width = 426.79135 / 2.0
193
+ # if width == 'doublecol':
194
+ # width = 426.79135
195
+
196
+ self.nx_subplots = nx_subplots
197
+ self.ny_subplots = ny_subplots
198
+ self.width = width * scale_width
199
+ self.dpi = dpi
200
+ self.threeD = threeD
201
+ self.ratio = ratio
202
+ self.legend = legend
203
+ self.filename = filename
204
+ self.directory = directory
205
+ self.axes_grid = axes_grid
206
+ self.gridspec_kw = gridspec_kw
207
+ self.cmap = cmap
208
+ self.col_list = import_colors(self.cmap)
209
+
210
+ self.axes_grid_which = "major"
211
+ self.grid_alpha = 1.0
212
+ self.grid_linestyle = linestyles["densely dotted"]
213
+ self.fontsize = fontsize
214
+ # print(self.directory)
215
+ if len(self.directory) > 0:
216
+ if not self.directory[-1] == "/":
217
+ self.directory += "/"
218
+
219
+ #
220
+ # plt.style.use('seaborn')
221
+ #
222
+ if not figsize == None:
223
+ self.width = figsize[0]
224
+ self.ratio = figsize[0] / figsize[1]
225
+
226
+ if tex_fonts:
227
+ self.setup_tex_fonts()
228
+
229
+ if not load_file == "":
230
+ self.load(load_file)
231
+ elif threeD:
232
+ self.create_3dplot()
233
+ else:
234
+ self.create_lineplot()
235
+
236
+ def setup_tex_fonts(self):
237
+ self.tex_fonts = {
238
+ # Use LaTeX to write all text
239
+ "text.usetex": True,
240
+ "font.family": "serif",
241
+ "pgf.rcfonts": False, # don't setup fonts from rc parameters
242
+ # Use 10pt font in plots, to match 10pt font in document
243
+ "axes.labelsize": self.fontsize,
244
+ "font.size": self.fontsize,
245
+ # Make the legend/label fonts a little smaller
246
+ "legend.fontsize": self.fontsize,
247
+ "xtick.labelsize": self.fontsize,
248
+ "ytick.labelsize": self.fontsize,
249
+ }
250
+ self.setup_plotstyle(
251
+ tex_fonts=self.tex_fonts,
252
+ axes_grid=self.axes_grid,
253
+ axes_grid_which=self.axes_grid_which,
254
+ grid_alpha=self.grid_alpha,
255
+ grid_linestyle=self.grid_linestyle,
256
+ )
257
+
258
+ def create_lineplot(self):
259
+ self.fig, self.axs = plt.subplots(
260
+ self.ny_subplots,
261
+ self.nx_subplots,
262
+ figsize=self.set_size(
263
+ self.width,
264
+ ratio=self.ratio, #
265
+ ), # sharex=True,#sharex='all', sharey='all',
266
+ dpi=self.dpi,
267
+ constrained_layout=False,
268
+ gridspec_kw=self.gridspec_kw,
269
+ )
270
+
271
+ def create_3dplot(self):
272
+ self.fig = plt.figure(figsize=self.set_size(self.width), dpi=self.dpi)
273
+ self.axs = self.fig.add_subplot(111, projection="3d")
274
+
275
+ def setup_plotstyle(
276
+ self,
277
+ tex_fonts=True,
278
+ axes_grid=True,
279
+ axes_grid_which="major",
280
+ grid_alpha=0.0,
281
+ grid_linestyle="dotted",
282
+ ):
283
+ if tex_fonts:
284
+ plt.rcParams.update(self.tex_fonts)
285
+
286
+ plt.rcParams["axes.grid"] = axes_grid # False ## display grid or not
287
+ # gridlines at major, minor or both ticks
288
+ plt.rcParams["axes.grid.which"] = axes_grid_which
289
+ plt.rcParams["grid.alpha"] = grid_alpha # transparency, between 0.0 and 1.0
290
+ plt.rcParams["grid.linestyle"] = grid_linestyle
291
+
292
+ plt.rcParams["xtick.direction"] = "in"
293
+ plt.rcParams["ytick.direction"] = "in"
294
+
295
+ # This is to avoid the overlapping tick labels.
296
+ plt.rcParams["xtick.major.pad"] = 8
297
+ plt.rcParams["ytick.major.pad"] = 8
298
+ # plt.rc('text.latex', preamble=r'\usepackage{wasysym}')
299
+
300
+ def set_common_xlabel(self, xlabel="common X"):
301
+ self.fig.text(
302
+ 0.5,
303
+ -0.075,
304
+ xlabel,
305
+ va="center",
306
+ ha="center",
307
+ fontsize=self.fontsize,
308
+ )
309
+ # fig.text(0.04, 0.5, 'common Y', va='center', ha='center', rotation='vertical', fontsize=rcParams['axes.labelsize'])
310
+
311
+ def set_size(self, width, fraction=1, ratio="golden"):
312
+ """Set figure dimensions to avoid scaling in LaTeX.
313
+ Parameters
314
+ ----------
315
+ width: float
316
+ Document textwidth or columnwidth in pts
317
+ fraction: float, optional
318
+ Fraction of the width which you wish the figure to occupy
319
+ Returns
320
+ -------
321
+ fig_dim: tuple
322
+ Dimensions of figure in inches
323
+ """
324
+ #
325
+ # Width of figure (in pts)
326
+ if width == "thesis":
327
+ width_pt = 426.79135
328
+ elif width == "beamer":
329
+ width_pt = 307.28987
330
+ else:
331
+ width_pt = width
332
+
333
+ # Width of figure
334
+ fig_width_pt = width_pt * fraction
335
+
336
+ # Convert from pt to inches
337
+ inches_per_pt = 1 / 72.27
338
+
339
+ # Golden ratio to set aesthetic figure height
340
+ # https://disq.us/p/2940ij3
341
+ golden_ratio = (5**0.5 - 1) / 2
342
+
343
+ # Figure width in inches
344
+ fig_width_in = fig_width_pt * inches_per_pt
345
+
346
+ if ratio == "golden":
347
+ # Figure height in inches
348
+ fig_height_in = fig_width_in * golden_ratio
349
+
350
+ elif ratio == "square":
351
+ # Figure height in inches
352
+ fig_height_in = fig_width_in
353
+ # print('ratio',ratio)
354
+ if type(ratio) == int or type(ratio) == float:
355
+ fig_height_in = fig_width_in * ratio
356
+
357
+ fig_dim = (fig_width_in, fig_height_in)
358
+
359
+ return fig_dim
360
+
361
+ def get_axis(self, subfigure):
362
+ if subfigure == -1:
363
+ return self.axs
364
+ elif not isinstance(subfigure, list):
365
+ return self.axs[subfigure]
366
+ elif isinstance(subfigure, list) and len(subfigure) == 2:
367
+ return self.axs[subfigure[0], subfigure[1]]
368
+
369
+ def get_limits(self, ax=None):
370
+ if ax == None:
371
+ xxmin, xxmax = self.axs.get_xlim()
372
+ yymin, yymax = self.axs.get_ylim()
373
+ else:
374
+ xxmin, xxmax = ax.get_xlim()
375
+ yymin, yymax = ax.get_ylim()
376
+ arr = [xxmin, xxmax, yymin, yymax]
377
+ return arr
378
+
379
+ def set_labels(self, delta, point, subfigure=-1, axis="x"):
380
+ ax = self.get_axis(subfigure)
381
+ plt.sca(ax)
382
+ if axis == "x":
383
+ xmin, xmax = ax.get_xlim()
384
+ width = int((xmax - xmin) / delta + 1) * delta
385
+ locs, labels = plt.xticks()
386
+ i0 = int(xmin / delta)
387
+ i1 = int(xmax / delta)
388
+ xvec = []
389
+ xvec = np.arange(point - width, point + width + delta, delta)
390
+ xvec += point
391
+ xvec = xvec[xvec >= xmin]
392
+ xvec = xvec[xvec <= xmax]
393
+ new_labels = [i * delta for i in range(i0, i1)]
394
+ # if precision == 0: new_labels = [int(x) for x in new_labels]
395
+ plt.xticks(xvec, xvec)
396
+ if axis == "y":
397
+ return
398
+
399
+ def scale_axis(
400
+ self,
401
+ subfigure=-1,
402
+ axis="x",
403
+ axs_in=None,
404
+ scale=1.0,
405
+ shift=0,
406
+ precision=2,
407
+ delta=-1,
408
+ includepoint=-1,
409
+ nticks=5,
410
+ locs_labels=None,
411
+ ):
412
+ # https://matplotlib.org/3.1.1/api/_as_gen/matplotlib.pyplot.xticks.html
413
+ # if subfigure_x == -1 and subfigure_y == -1 and nx_subplots > 1 and ny_subplots > 1:
414
+ # print('enter subfigure_x and subfigure_y!')
415
+ # return
416
+ # if subfigure_x == -1 and subfigure_y == -1:
417
+ # ax = self.axs[]
418
+ if subfigure == -1:
419
+ ax = self.axs
420
+ elif not isinstance(subfigure, list):
421
+ ax = self.axs[subfigure]
422
+ elif isinstance(subfigure, list) and len(subfigure) == 2:
423
+ ax = self.axs[subfigure[0], subfigure[1]]
424
+
425
+ if not axs_in == None:
426
+ ax = axs_in
427
+ # print("precision", precision, precision, precision)
428
+ plt.sca(ax)
429
+ if axis == "x":
430
+ if locs_labels == None:
431
+ xmin, xmax = ax.get_xlim()
432
+ locs, labels = plt.xticks()
433
+ if delta == -1 and includepoint == -1:
434
+ new_labels = [round((x + shift) * scale, precision) for x in locs]
435
+ if precision == 0:
436
+ new_labels = [int(x) for x in new_labels]
437
+ else:
438
+ if delta == -1:
439
+ delta = (xmax - xmin) / (nticks - 1)
440
+ if includepoint == -1:
441
+ includepoint = xmin
442
+ width = int((xmax - xmin) / delta + 1) * delta
443
+ i0 = int(xmin / delta)
444
+ i1 = int(xmax / delta + 1)
445
+ locs = np.arange(
446
+ includepoint - width,
447
+ includepoint + width + delta,
448
+ delta,
449
+ )
450
+ locs = locs[locs >= xmin - 1e-12]
451
+ locs = locs[locs <= xmax + 1e-12]
452
+
453
+ new_labels = [round((x + shift) * scale, precision) for x in locs]
454
+ if precision == 0:
455
+ new_labels = [int(y) for y in new_labels]
456
+ new_labels = [f"${l}$" for l in new_labels]
457
+ # plt.xticks(locs,new_labels)
458
+ ax.set_xticks(locs)
459
+ ax.set_xticklabels(new_labels)
460
+ ax.axis(xmin=xmin, xmax=xmax)
461
+ else:
462
+ # plt.xticks(locs_labels['locs'],locs_labels['labels'])
463
+ ax.set_xticks(locs_labels["locs"])
464
+ ax.set_xticklabels(locs_labels["labels"])
465
+
466
+ if axis == "y":
467
+ if locs_labels == None:
468
+ ymin, ymax = ax.get_ylim()
469
+ locs, labels = plt.yticks()
470
+ if delta == -1 and includepoint == -1:
471
+ new_labels = [round((y + shift) * scale, precision) for y in locs]
472
+ if precision == 0:
473
+ new_labels = [int(y) for y in new_labels]
474
+ else:
475
+ if delta == -1:
476
+ delta = (ymax - ymin) / (nticks - 1)
477
+ if includepoint == -1:
478
+ includepoint = ymin
479
+ width = int((ymax - ymin) / delta + 1) * delta
480
+ i0 = int(ymin / delta)
481
+ i1 = int(ymax / delta + 1)
482
+ locs = np.arange(
483
+ includepoint - width,
484
+ includepoint + width + delta,
485
+ delta,
486
+ )
487
+ locs = locs[locs >= ymin - 1e-12]
488
+ locs = locs[locs <= ymax + 1e-12]
489
+
490
+ new_labels = [round((y + shift) * scale, precision) for y in locs]
491
+ if precision == 0:
492
+ new_labels = [int(y) for y in new_labels]
493
+ new_labels = [f"${l}$" for l in new_labels]
494
+ # plt.yticks(locs,new_labels)
495
+
496
+ ax.set_yticks(locs)
497
+ ax.set_yticklabels(new_labels)
498
+
499
+ ax.axis(ymin=ymin, ymax=ymax)
500
+ else:
501
+ # plt.yticks(locs_labels['locs'],locs_labels['labels'])
502
+ ax.set_yticks(locs_labels["locs"])
503
+ ax.set_yticklabels(locs_labels["labels"])
504
+
505
+ def adjustFigAspect(self, aspect=1):
506
+ """
507
+ Adjust the subplot parameters so that the figure has the correct
508
+ aspect ratio.
509
+ """
510
+ xsize, ysize = self.fig.get_size_inches()
511
+ minsize = min(xsize, ysize)
512
+ xlim = 0.4 * minsize / xsize
513
+ ylim = 0.4 * minsize / ysize
514
+ if aspect < 1:
515
+ xlim *= aspect
516
+ else:
517
+ ylim /= aspect
518
+ self.fig.subplots_adjust(
519
+ left=0.5 - xlim,
520
+ right=0.5 + xlim,
521
+ bottom=0.5 - ylim,
522
+ top=0.5 + ylim,
523
+ )
524
+
525
+ def add_figure_label(
526
+ self,
527
+ label,
528
+ pos="top left",
529
+ bbox=dict(facecolor="white", edgecolor="gray", boxstyle="round"),
530
+ ha="left",
531
+ va="top",
532
+ ax=None,
533
+ ):
534
+ limits = self.get_limits(ax)
535
+ # print(limits)
536
+ lx = limits[1] - limits[0]
537
+ ly = limits[3] - limits[2]
538
+
539
+ if isinstance(pos, str):
540
+ if "top" in pos:
541
+ y = limits[2] + 0.90 * ly
542
+ elif "center in pos":
543
+ y = limits[2] + 0.5 * ly
544
+ else:
545
+ y = limits[2] + 0.05 * ly
546
+
547
+ if "left" in pos:
548
+ x = limits[0] + 0.1 * lx
549
+ else:
550
+ x = limits[0] + 0.95 * lx
551
+ else:
552
+ x = limits[0] + pos[0] * lx
553
+ y = limits[2] + pos[1] * ly
554
+
555
+ # print(x,y)
556
+ if ax == None:
557
+ ax = self.axs
558
+ ax.text(
559
+ x,
560
+ y,
561
+ f"{label}",
562
+ rotation=0,
563
+ ha=ha,
564
+ va=va,
565
+ bbox=bbox,
566
+ fontsize=self.fontsize,
567
+ )
568
+
569
+ def savefig(
570
+ self,
571
+ filename="",
572
+ formats=["png"],
573
+ format="",
574
+ create_sh_file=False,
575
+ print_imgcat=True,
576
+ format_folder=False,
577
+ tight_layout=True,
578
+ ):
579
+ # self.update_figure()
580
+ # self.fig.tight_layout()
581
+ # print(self.directory)
582
+
583
+ if "/" in self.filename:
584
+ tmp = self.filename
585
+ spl = tmp.split("/")
586
+ self.filename = spl[-1]
587
+ self.directory = tmp.replace(spl[-1], "")
588
+
589
+ if not self.directory == "":
590
+ Path(self.directory).mkdir(parents=True, exist_ok=True)
591
+
592
+ if isinstance(format, list):
593
+ formats = format
594
+ format = ""
595
+ if not format == "":
596
+ formats = [format]
597
+ if filename == "":
598
+ filename = self.filename
599
+
600
+ if formats == "all" or formats == ["all"]:
601
+ self.dump()
602
+ formats = ["jpg", "pdf", "pgf", "png", "svg", "txt", "pickle", "tex"]
603
+
604
+ if isinstance(formats, str):
605
+ formats = [formats]
606
+
607
+ if format_folder:
608
+ for format in formats:
609
+ # print('self.directory',self.directory)
610
+ Path(self.directory + "/" + format).mkdir(parents=True, exist_ok=True)
611
+
612
+ _dir = self.directory
613
+ for format in formats:
614
+ if format_folder:
615
+ self.directory = "{}{}/".format(_dir, format)
616
+ # print('pl',format)
617
+ if format in [
618
+ "eps",
619
+ "jpeg",
620
+ "jpg",
621
+ "pdf",
622
+ "png",
623
+ "ps",
624
+ "raw",
625
+ "rgba",
626
+ "svg",
627
+ "svgz",
628
+ "tif",
629
+ "tiff",
630
+ ]:
631
+ # self.fig.savefig(self.directory + filename + '.' + format,bbox_inches='tight', transparent=False)
632
+ if tight_layout:
633
+ self.fig.savefig(
634
+ self.directory + filename + "." + format,
635
+ bbox_inches="tight",
636
+ )
637
+ else:
638
+ self.fig.savefig(self.directory + filename + "." + format)
639
+ elif format == "pgf":
640
+ # Save pgf figure
641
+ self.fig.savefig(
642
+ self.directory + filename + "." + format,
643
+ bbox_inches="tight",
644
+ )
645
+
646
+ # Replace pgf figure colors with colorlet
647
+ # This is based af.
648
+ # col_list = self.col_list
649
+ file_str = "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n"
650
+ file_str += "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n"
651
+ file_str += "%% Do not forget to add the following lines"
652
+ for cmap in ["pastel", "cmap2"]:
653
+ col_list = import_colors(cmap)
654
+ file_str += "\n\n%% Definitions for " + cmap + "\n\n"
655
+ for col in col_list:
656
+ file_str += "%" + col_list[col].define_color_str(col) + "\n"
657
+ file_str += "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n"
658
+ file_str += "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n\n\n"
659
+ with open(self.directory + filename + "." + format, "r") as f:
660
+ for line in f:
661
+ file_str += line
662
+ for cmap in ["pastel", "cmap2"]:
663
+ col_list = import_colors(cmap)
664
+ for col in col_list:
665
+ if col_list[col].pgf_col_str in line:
666
+ # print(line)
667
+ file_str += (
668
+ "\\colorlet{currentstroke}{" + col + "}%\n"
669
+ )
670
+ file_str += (
671
+ "\\colorlet{currentfill}{" + col + "}%\n"
672
+ )
673
+ file_str += "\\colorlet{textcolor}{" + col + "}%\n"
674
+
675
+ with open(self.directory + filename + "." + format, "w") as f:
676
+ f.write(file_str)
677
+ elif format in ["txt", "dat", "csv"]:
678
+ self.matplotlib2txt(self.directory + filename, format)
679
+ elif format == "pickle":
680
+ pickle.dump(self.fig, open(self.directory + filename + ".pickle", "wb"))
681
+ elif format == "tex":
682
+ import tikzplotlib
683
+
684
+ # tikzplotlib.clean_figure()
685
+ tikzplotlib.save(self.directory + filename + ".tex")
686
+ else:
687
+ try:
688
+ plt.savefig(
689
+ self.directory + filename + "." + format,
690
+ bbox_inches="tight",
691
+ )
692
+ except Exception as e:
693
+ print(
694
+ "ERROR: Could not save figure: "
695
+ + self.directory
696
+ + filename
697
+ + "."
698
+ + format,
699
+ )
700
+ print(e)
701
+
702
+ imgcat_formats = ["png"]
703
+ if create_sh_file:
704
+ with open("show_latest_image.sh", "w") as f:
705
+ for format in formats:
706
+ if format in imgcat_formats:
707
+ f.write(
708
+ "imgcat " + self.directory + filename + "." + format + "\n",
709
+ )
710
+
711
+ if print_imgcat and ("png" in formats or "pdf" in formats):
712
+ if format_folder:
713
+ self.directory = "{}{}/".format(_dir, "png")
714
+ self.imgcat(formats)
715
+ self.directory = _dir
716
+
717
+ # if format in formats:
718
+ # print('imgcat ' + filename + '.' + format)
719
+
720
+ def imgcat(self, formats="png"):
721
+ imgcat_formats = ["png"]
722
+ if isinstance(formats, str):
723
+ formats = [formats]
724
+ for format in formats:
725
+ if format in imgcat_formats:
726
+ print("imgcat " + self.directory + self.filename + "." + format)
727
+
728
+ def matplotlib2txt(self, filename, format="txt"):
729
+ # ax = plt.gca() # get axis handle
730
+
731
+ x_unit = "mm"
732
+ y_unit = "mm"
733
+
734
+ max_len_arr = 0
735
+
736
+ # Create a vector with each axis
737
+ axs_vec = []
738
+ if self.nx_subplots > 1 and self.ny_subplots > 1:
739
+ for i in range(self.nx_subplots):
740
+ for j in range(self.ny_subplots):
741
+ axs_vec.append(self.axs[i, j])
742
+ elif self.nx_subplots > 1 or self.ny_subplots > 1:
743
+ for i in range(self.nx_subplots * self.ny_subplots):
744
+ axs_vec.append(self.axs[i])
745
+ else:
746
+ axs_vec.append(self.axs)
747
+
748
+ # Save all the data
749
+ line_names = []
750
+ line_xdata = []
751
+ line_ydata = []
752
+ for iax, ax in enumerate(axs_vec):
753
+ for line in ax.lines:
754
+ line_names.append(line)
755
+ line_xdata.append(line.get_xdata())
756
+ line_ydata.append(line.get_ydata())
757
+ max_len_arr = max(max_len_arr, len(line.get_xdata()))
758
+ # print(line_names)
759
+ data_mat = np.empty((len(line_names) * 2, max_len_arr))
760
+ data_mat[:, :] = np.NaN
761
+ i = 0
762
+
763
+ header = ""
764
+
765
+ for name, xdata, ydata in zip(line_names, line_xdata, line_ydata):
766
+ data_mat[2 * i, 0 : len(xdata)] = xdata
767
+ data_mat[2 * i + 1, 0 : len(ydata)] = ydata
768
+
769
+ header += "Axial position, " + str(name) + ","
770
+
771
+ i += 1
772
+
773
+ np.savetxt(filename + "." + format, data_mat.T, header=header, delimiter=",")
774
+
775
+ def dump(
776
+ self,
777
+ filename="",
778
+ ):
779
+ if filename == "":
780
+ filename = self.filename + "_dump.txt"
781
+ Path(self.directory + "/dump").mkdir(parents=True, exist_ok=True)
782
+ with open(self.directory + "dump/" + filename, "wb") as file:
783
+ file.write(cPickle.dumps(self.__dict__))
784
+
785
+ def load(self, filename):
786
+ with open(filename, "rb") as file:
787
+ self.__dict__ = cPickle.loads(file.read())
788
+
789
+ def get_lines(self):
790
+ lines = plt.gca().lines
791
+ out = []
792
+ for i, line in enumerate(lines):
793
+ line_dict = dict()
794
+ line_dict["line"] = line
795
+ line_dict["line_name"] = str(line)
796
+ line_dict["line_xdat"] = line.get_xdata()
797
+ line_dict["line_ydat"] = line.get_ydata()
798
+ out.append(line_dict)
799
+ return out
800
+
801
+ def add_label_box(
802
+ self,
803
+ label="Test",
804
+ xpos=0.05,
805
+ ypos=0.95,
806
+ rotation=0,
807
+ ha="left",
808
+ va="top",
809
+ bbox=dict(facecolor="white", edgecolor="gray", boxstyle="round"),
810
+ ):
811
+ self.axs.text(
812
+ xpos,
813
+ ypos,
814
+ label,
815
+ rotation=rotation,
816
+ ha=ha,
817
+ va=va,
818
+ transform=self.axs.transAxes,
819
+ bbox=bbox,
820
+ )
821
+ # print(label)
822
+
823
+
824
+ def fmt_scientific(x, pos):
825
+ a, b = "{:.1e}".format(x).split("e")
826
+ b = int(b)
827
+ return r"${} \times 10^{{{}}}$".format(a, b)
828
+
829
+
830
+ def fmt_10pow(x, pos):
831
+ a, b = "{:.1e}".format(x).split("e")
832
+ b = int(b)
833
+ return r"$10^{{{}}}$".format(b)
834
+
835
+
836
+ def fmt_int(x, pos, num_dec):
837
+ return r"${}$".format(int(x))
838
+
839
+
840
+ def fmt_1dec(x, pos):
841
+ return r"${}$".format(round(x, 1))
842
+
843
+
844
+ def fmt_2dec(x, pos):
845
+ return r"${}$".format(round(x, 2))
846
+
847
+
848
+ if __name__ == "__main__":
849
+ print("Testing maxplotlib")
850
+ mfig = figure(filename="mpl_test")
851
+ mfig.axs.plot([0, 1, 2, 3], [0, 0, 1, 1])
852
+ mfig.savefig(formats=["png"])