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.
- maxplotlib/__init__.py +3 -0
- maxplotlib/backends/matplotlib/utils.py +136 -0
- maxplotlib/backends/matplotlib/utils_old.py +852 -0
- maxplotlib/backends/plotly/__init__.py +0 -0
- maxplotlib/backends/plotly/utils.py +0 -0
- maxplotlib/canvas/__init__.py +0 -0
- maxplotlib/canvas/canvas.py +526 -0
- maxplotlib/colors/__init__.py +0 -0
- maxplotlib/colors/colors.py +85 -0
- maxplotlib/linestyle/__init__.py +0 -0
- maxplotlib/linestyle/linestyle.py +58 -0
- maxplotlib/objects/__init__.py +0 -0
- maxplotlib/objects/layer.py +20 -0
- maxplotlib/objects/node.py +0 -0
- maxplotlib/objects/path.py +0 -0
- maxplotlib/subfigure/__init__.py +0 -0
- maxplotlib/subfigure/line_plot.py +357 -0
- maxplotlib/subfigure/subfigure.py +3 -0
- maxplotlib/subfigure/tikz_figure.py +497 -0
- maxplotlib/tests/test_canvas.py +7 -0
- maxplotlib/tests/test_imports.py +12 -0
- maxplotlib/tests/test_plot.py +0 -0
- maxplotlibx-0.1.dist-info/METADATA +64 -0
- maxplotlibx-0.1.dist-info/RECORD +27 -0
- maxplotlibx-0.1.dist-info/WHEEL +5 -0
- maxplotlibx-0.1.dist-info/licenses/LICENSE +21 -0
- maxplotlibx-0.1.dist-info/top_level.txt +1 -0
|
@@ -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"])
|