scipl 1.0.0__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.
- scipl/__init__.py +1 -0
- scipl/__main__.py +282 -0
- scipl-1.0.0.dist-info/METADATA +15 -0
- scipl-1.0.0.dist-info/RECORD +8 -0
- scipl-1.0.0.dist-info/WHEEL +5 -0
- scipl-1.0.0.dist-info/entry_points.txt +2 -0
- scipl-1.0.0.dist-info/licenses/LICENSE +21 -0
- scipl-1.0.0.dist-info/top_level.txt +1 -0
scipl/__init__.py
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
__version__ = "1.0.0"
|
scipl/__main__.py
ADDED
|
@@ -0,0 +1,282 @@
|
|
|
1
|
+
#!/usr/bin/env python
|
|
2
|
+
|
|
3
|
+
# general imports
|
|
4
|
+
import argparse as ap, matplotlib.animation as anm, matplotlib.pyplot as plt, matplotlib.ticker as tck, numpy as np
|
|
5
|
+
|
|
6
|
+
# additional imports
|
|
7
|
+
from mpl_toolkits.axes_grid1.inset_locator import mark_inset
|
|
8
|
+
|
|
9
|
+
# set rcParams
|
|
10
|
+
plt.rcParams.update({
|
|
11
|
+
"text.usetex": True,
|
|
12
|
+
"font.family": "serif",
|
|
13
|
+
"font.serif": ["Libertinus Serif"],
|
|
14
|
+
"text.latex.preamble": r"\usepackage{braket}"
|
|
15
|
+
})
|
|
16
|
+
|
|
17
|
+
def main():
|
|
18
|
+
|
|
19
|
+
# create the parser
|
|
20
|
+
parser = ap.ArgumentParser(
|
|
21
|
+
prog="plot.py", description="Scientific plotting script.",
|
|
22
|
+
formatter_class=lambda prog: ap.HelpFormatter(prog, max_help_position=128),
|
|
23
|
+
add_help=False, allow_abbrev=False
|
|
24
|
+
)
|
|
25
|
+
|
|
26
|
+
# add the arguments for the parser
|
|
27
|
+
parser.add_argument("-h", "--help", action="help", default=ap.SUPPRESS, help="This help message.")
|
|
28
|
+
parser.add_argument("-o", "--output", type=str, help="The output file to save the plot.")
|
|
29
|
+
parser.add_argument("-a", "--animate", type=int, help="Animate the plot.")
|
|
30
|
+
|
|
31
|
+
# add the plotting arguments
|
|
32
|
+
parser.add_argument("--colormap", type=str, nargs=2, default=["tab10", "10"], help="The colormap to use for the plot.")
|
|
33
|
+
parser.add_argument("--dpi", type=int, default=256, help="The DPI of the plot.")
|
|
34
|
+
parser.add_argument("--figsize", type=float, nargs=2, default=[6, 8], help="The dimensions of the plot in inches.")
|
|
35
|
+
parser.add_argument("--fontsize_label", type=int, nargs="+", help="The font size for the x and y axis labels.")
|
|
36
|
+
parser.add_argument("--fontsize_title", type=int, nargs="+", help="The font size for the title of each subplot.")
|
|
37
|
+
parser.add_argument("--fontsize_legend", type=int, nargs="+", help="The font size for the legend of each subplot.")
|
|
38
|
+
parser.add_argument("--fontsize_tick", type=int, nargs="+", help="The font size for the ticks of each subplot.")
|
|
39
|
+
parser.add_argument("--fps", type=int, default=30, help="Frames per second for the animation.")
|
|
40
|
+
parser.add_argument("--title", type=str, nargs="+", help="The title of each subplot.")
|
|
41
|
+
parser.add_argument("--xlabel", type=str, nargs="+", help="The an x-axis labels for each subplot.")
|
|
42
|
+
parser.add_argument("--xlim", type=float, nargs="+", help="The x-axis limits for each subplot.")
|
|
43
|
+
parser.add_argument("--legpos", type=float, nargs="+", help="The bbox position of the legend boxes.")
|
|
44
|
+
parser.add_argument("--xticklabelon", type=int, nargs="+", help="Whether to show the x-axis tick labels for each subplot.")
|
|
45
|
+
parser.add_argument("--ylabel", type=str, nargs="+", help="The an y-axis label for each subplot.")
|
|
46
|
+
parser.add_argument("--ylim", type=float, nargs="+", help="The y-axis limits for each subplot.")
|
|
47
|
+
parser.add_argument("--yticklabelon", type=int, nargs="+", help="Whether to show the y-axis tick labels for each subplot.")
|
|
48
|
+
parser.add_argument("--zoominset", type=str, nargs="+", help="Zoomed inset axes specification")
|
|
49
|
+
|
|
50
|
+
# additional file arguments
|
|
51
|
+
parser.add_argument("--alphas", nargs="+", help="Alpha values for the plotted lines.")
|
|
52
|
+
parser.add_argument("--colors", nargs="+", help="Individual colors for the plotted lines.")
|
|
53
|
+
parser.add_argument("--errors", nargs="+", help="Error bars for the plotted lines.")
|
|
54
|
+
parser.add_argument("--fits", nargs="+", help="Fit lines to the plotted data.")
|
|
55
|
+
parser.add_argument("--legends", nargs="+", help="Labels of the plotted lines.")
|
|
56
|
+
parser.add_argument("--markers", nargs="+", help="Markers for the plotted lines.")
|
|
57
|
+
parser.add_argument("--offsets", nargs="+", help="Vertical offsets for the plotted lines.")
|
|
58
|
+
parser.add_argument("--scales", nargs="+", help="Scales for the plotted lines.")
|
|
59
|
+
parser.add_argument("--styles", nargs="+", help="Styles for the plotted lines.")
|
|
60
|
+
parser.add_argument("--widths", nargs="+", help="Widths of the plotted lines.")
|
|
61
|
+
parser.add_argument("--xcols", nargs="+", help="The columns of the data files to use as x values for each line.")
|
|
62
|
+
parser.add_argument("--subplots", nargs="+", help="Divide the lines into subplots.", default=["111"])
|
|
63
|
+
|
|
64
|
+
# add positional arguments and parse the arguments
|
|
65
|
+
parser.add_argument("files", nargs="+", help="The data files to plot."); args = parser.parse_args()
|
|
66
|
+
|
|
67
|
+
# function to load the data from the input string as well as the columns to plot and also some helper functions
|
|
68
|
+
def load(fname): tmp = fname.split(":"); data = np.loadtxt(tmp[0], ndmin=2, skiprows=1); return data, np.array(tmp[1].split(","), int) if len(tmp) == 2 and tmp[1] else np.arange(data.shape[1] - 1)
|
|
69
|
+
dcit, indc, trng = lambda d, c: ((x, j) for x, y in zip(d, c) for j in y), lambda l, e: [i for i, sl in enumerate(l) if e in sl], lambda s: range((a := list(map(int, s.split("-"))))[0], a[-1] + 1)
|
|
70
|
+
|
|
71
|
+
# load the data with plotted columns
|
|
72
|
+
data, data_cols = zip(*[load(file) for file in args.files]);
|
|
73
|
+
|
|
74
|
+
# load the error bars if provided
|
|
75
|
+
data_errors, cols_errors = zip(*[load(file) for file in args.errors[1:]]) if args.errors else ((), ())
|
|
76
|
+
|
|
77
|
+
# get the line indices for the error bars, colors, offsets, scales, and alphas
|
|
78
|
+
line_errors = (list(map(lambda x: int(x), args.errors [0].split(","))) if args.errors [0] not in ["all", "every"] else np.arange(sum([len(col) for col in cols_errors])) ) if args.errors else []
|
|
79
|
+
line_fits = (list(map(lambda x: trng(x), args.fits [0].split(","))) if args.fits [0] not in ["all", "every"] else np.arange(len(list(dcit(data, data_cols))))[np.newaxis].T) if args.fits else []
|
|
80
|
+
line_colors = (list(map(lambda x: trng(x), args.colors [0].split(","))) if args.colors [0] not in ["all", "every"] else np.arange(len(list(dcit(data, data_cols))))[np.newaxis].T) if args.colors else []
|
|
81
|
+
line_offsets = (list(map(lambda x: trng(x), args.offsets[0].split(","))) if args.offsets[0] not in ["all", "every"] else np.arange(len(list(dcit(data, data_cols))))[np.newaxis].T) if args.offsets else []
|
|
82
|
+
line_scales = (list(map(lambda x: trng(x), args.scales [0].split(","))) if args.scales [0] not in ["all", "every"] else np.arange(len(list(dcit(data, data_cols))))[np.newaxis].T) if args.scales else []
|
|
83
|
+
line_alphas = (list(map(lambda x: trng(x), args.alphas [0].split(","))) if args.alphas [0] not in ["all", "every"] else np.arange(len(list(dcit(data, data_cols))))[np.newaxis].T) if args.alphas else []
|
|
84
|
+
line_legends = (list(map(lambda x: trng(x), args.legends[0].split(","))) if args.legends[0] not in ["all", "every"] else np.arange(len(list(dcit(data, data_cols))))[np.newaxis].T) if args.legends else []
|
|
85
|
+
line_widths = (list(map(lambda x: trng(x), args.widths [0].split(","))) if args.widths [0] not in ["all", "every"] else np.arange(len(list(dcit(data, data_cols))))[np.newaxis].T) if args.widths else []
|
|
86
|
+
line_styles = (list(map(lambda x: trng(x), args.styles [0].split(","))) if args.styles [0] not in ["all", "every"] else np.arange(len(list(dcit(data, data_cols))))[np.newaxis].T) if args.styles else []
|
|
87
|
+
line_markers = (list(map(lambda x: trng(x), args.markers[0].split(","))) if args.markers[0] not in ["all", "every"] else np.arange(len(list(dcit(data, data_cols))))[np.newaxis].T) if args.markers else []
|
|
88
|
+
line_xcols = (list(map(lambda x: trng(x), args.xcols [0].split(","))) if args.xcols [0] not in ["all", "every"] else np.arange(len(list(dcit(data, data_cols))))[np.newaxis].T) if args.xcols else []
|
|
89
|
+
|
|
90
|
+
# add the scales and offsets to the initial lines in the data
|
|
91
|
+
for (f, s) in ((frame, args.animate if args.animate else 0) for frame in range((data[0].shape[1] - 1) // args.animate if args.animate else 1)):
|
|
92
|
+
for i, (data_i, j) in enumerate(dcit(data, data_cols)):
|
|
93
|
+
data_i[:, j + f * s + 1] *= float(args.scales [indc(line_scales, i)[0] + 1 if args.scales[0] != "all" else 1]) if indc(line_scales, i) else 1
|
|
94
|
+
for (f, s) in ((frame, args.animate if args.animate else 0) for frame in range((data[0].shape[1] - 1) // args.animate if args.animate else 1)):
|
|
95
|
+
for i, (data_i, j) in enumerate(dcit(data, data_cols)):
|
|
96
|
+
data_i[:, j + f * s + 1] += float(args.offsets[indc(line_offsets, i)[0] + 1 if args.offsets[0] != "all" else 1]) if indc(line_offsets, i) else 0
|
|
97
|
+
|
|
98
|
+
# create the figure and the container for plots and error bars
|
|
99
|
+
fig = plt.figure(dpi=args.dpi if args.output else 96, figsize=(args.figsize[1], args.figsize[0])); axes, plots, ebars = {}, [], []
|
|
100
|
+
|
|
101
|
+
# fill the axes dictionary
|
|
102
|
+
for sp in args.subplots: axes[sp] = (fig.add_subplot(int(sp)) if len(sp) == 3 else fig.add_subplot(*[int(num) for num in sp.split("-")])) if sp not in axes else axes[sp]
|
|
103
|
+
|
|
104
|
+
# set the colormap
|
|
105
|
+
cmap = plt.get_cmap(args.colormap[0])(np.linspace(0, 1, int(args.colormap[1])))
|
|
106
|
+
|
|
107
|
+
# loop over data and its columns to plot
|
|
108
|
+
for i, (data_i, j) in enumerate(dcit(data, data_cols)):
|
|
109
|
+
|
|
110
|
+
# extract the color from the colormap
|
|
111
|
+
color = cmap[len([line for line in axes[args.subplots[len(plots) % len(args.subplots)]].get_lines() if not isinstance(line.get_color(), str)]) % len(cmap)]
|
|
112
|
+
|
|
113
|
+
# extract the alpha, color, legend, marker, style, xcol, and width for the current line
|
|
114
|
+
alpha = float(args.alphas [indc(line_alphas, i)[0] + 1 if args.alphas [0] != "all" else 1]) if indc(line_alphas, i) else 1
|
|
115
|
+
color = str(args.colors [indc(line_colors, i)[0] + 1 if args.colors [0] != "all" else 1]) if indc(line_colors, i) else color
|
|
116
|
+
legend = str(args.legends[indc(line_legends, i)[0] + 1 if args.legends[0] != "all" else 1]) if indc(line_legends, i) else ""
|
|
117
|
+
marker = str(args.markers[indc(line_markers, i)[0] + 1 if args.markers[0] != "all" else 1]) if indc(line_markers, i) else ""
|
|
118
|
+
style = str(args.styles [indc(line_styles, i)[0] + 1 if args.styles [0] != "all" else 1]) if indc(line_styles, i) else "-"
|
|
119
|
+
xcol = int(args.xcols [indc(line_xcols, i)[0] + 1 if args.xcols [0] != "all" else 1]) if indc(line_xcols, i) else 0
|
|
120
|
+
width = float(args.widths [indc(line_widths, i)[0] + 1 if args.widths [0] != "all" else 1]) if indc(line_widths, i) else 2.2
|
|
121
|
+
|
|
122
|
+
# extract the plot params for the line
|
|
123
|
+
kwargs = {"alpha": alpha, "color": color, "label": legend, "linestyle": style, "linewidth": width, "marker": marker}
|
|
124
|
+
|
|
125
|
+
# plot the data and append the plot to the list
|
|
126
|
+
plots.append(axes[args.subplots[len(plots) % len(args.subplots)]].plot(data_i[:, xcol], data_i[:, j + 1], **kwargs))
|
|
127
|
+
|
|
128
|
+
# loop over data again to plot the fits if provided
|
|
129
|
+
for i, (data_i, j) in enumerate(dcit(data, data_cols)):
|
|
130
|
+
|
|
131
|
+
# extract the color from the colormap
|
|
132
|
+
color = cmap[len([line for line in axes[args.subplots[len(plots) % len(args.subplots)]].get_lines() if not isinstance(line.get_color(), str)]) % len(cmap)]
|
|
133
|
+
|
|
134
|
+
# extract the fit expression and the x column for the current line
|
|
135
|
+
fitf = str(args.fits [indc(line_fits, i)[0] + 1 if args.fits [0] != "all" else 1]) if indc(line_fits, i) else None
|
|
136
|
+
xcol = int(args.xcols [indc(line_xcols, i)[0] + 1 if args.xcols [0] != "all" else 1]) if indc(line_xcols, i) else 0
|
|
137
|
+
|
|
138
|
+
# extract the alpha, color, legend, marker, style, and width for the current fit
|
|
139
|
+
alpha = float(args.alphas [indc(line_alphas, i + len(data_cols))[0] + 1 if args.alphas [0] != "all" else 1]) if indc(line_alphas, i + len(data_cols)) else 1
|
|
140
|
+
color = str(args.colors [indc(line_colors, i + len(data_cols))[0] + 1 if args.colors [0] != "all" else 1]) if indc(line_colors, i + len(data_cols)) else color
|
|
141
|
+
legend = str(args.legends[indc(line_legends, i + len(data_cols))[0] + 1 if args.legends[0] != "all" else 1]) if indc(line_legends, i + len(data_cols)) else ""
|
|
142
|
+
marker = str(args.markers[indc(line_markers, i + len(data_cols))[0] + 1 if args.markers[0] != "all" else 1]) if indc(line_markers, i + len(data_cols)) else ""
|
|
143
|
+
style = str(args.styles [indc(line_styles, i + len(data_cols))[0] + 1 if args.styles [0] != "all" else 1]) if indc(line_styles, i + len(data_cols)) else "-"
|
|
144
|
+
width = float(args.widths [indc(line_widths, i + len(data_cols))[0] + 1 if args.widths [0] != "all" else 1]) if indc(line_widths, i + len(data_cols)) else 2.2
|
|
145
|
+
|
|
146
|
+
# check if there is a fit for the current line
|
|
147
|
+
if fitf:
|
|
148
|
+
|
|
149
|
+
# import the fitting libraries
|
|
150
|
+
import scipy as sc, sympy as sp
|
|
151
|
+
|
|
152
|
+
# scaling the function to bring the x values in between 0 and 1 to improve the fit stability
|
|
153
|
+
scalef = lambda x: (x - x.min()) / (x.max() - x.min())
|
|
154
|
+
|
|
155
|
+
# define the expression and the parameters for the fit
|
|
156
|
+
expr, x = sp.sympify(fitf.split(":")[0]), sp.symbols("x"); params = sorted(list(expr.free_symbols - {x}), key=lambda s: s.name)
|
|
157
|
+
|
|
158
|
+
# create the fitting function and fit the data
|
|
159
|
+
f, guess = sp.lambdify([x] + params, expr, modules="numpy"), fitf.split(":")[1].split(",") if ":" in fitf else [1] * len(params)
|
|
160
|
+
|
|
161
|
+
# fit the data and extract the optimal parameters and their covariance
|
|
162
|
+
popt, pcov = sc.optimize.curve_fit(f, scalef(data_i[:, xcol]), data_i[:, j + 1], p0=[float(g) for g in guess])
|
|
163
|
+
|
|
164
|
+
# extract the plot params for the fit
|
|
165
|
+
kwargs = {"alpha": alpha, "color": color, "label": legend, "linestyle": style, "linewidth": width, "marker": marker}
|
|
166
|
+
|
|
167
|
+
# plot the fit and append the plot to the list
|
|
168
|
+
plots.append(axes[args.subplots[len(plots) % len(args.subplots)]].plot(data_i[:, xcol], f(scalef(data_i[:, xcol]), *popt), **kwargs))
|
|
169
|
+
|
|
170
|
+
# loop over the error bars and their columns
|
|
171
|
+
for (data_errors_i, j) in dcit(data_errors, cols_errors):
|
|
172
|
+
|
|
173
|
+
# get the top and bottom lines
|
|
174
|
+
top = plots[line_errors[len(ebars)]][0].get_ydata() + data_errors_i[:, j + 1]
|
|
175
|
+
bot = plots[line_errors[len(ebars)]][0].get_ydata() - data_errors_i[:, j + 1]
|
|
176
|
+
|
|
177
|
+
# extract the color
|
|
178
|
+
color = plots[line_errors[len(ebars)]][0].get_color()
|
|
179
|
+
|
|
180
|
+
# fill the area between the top and bottom line and append the plot to the list
|
|
181
|
+
ebars.append(axes[args.subplots[len(ebars) % len(args.subplots)]].fill_between(data_errors_i[:, 0], bot, top, color=color, alpha=0.2))
|
|
182
|
+
|
|
183
|
+
# loop over the axes
|
|
184
|
+
for i, ax in enumerate(axes.values()):
|
|
185
|
+
|
|
186
|
+
# list of tuples with the data and its columns to plot on the current axis
|
|
187
|
+
axis_data_cols = [pair for j, pair in enumerate(dcit(data, data_cols)) if [args.subplots[k % len(args.subplots)] for k in range(len(list(dcit(data, data_cols))))][j] == list(axes.keys())[i]]
|
|
188
|
+
|
|
189
|
+
# calculate the number of frames
|
|
190
|
+
nframes = (data[0].shape[1] - 1) // args.animate if args.animate else 1
|
|
191
|
+
|
|
192
|
+
# calculate the y limits
|
|
193
|
+
ymin = np.min([data_i[:, j + frame * (args.animate if args.animate else 0) + 1].min() for frame in range(nframes) for data_i, j in axis_data_cols])
|
|
194
|
+
ymax = np.max([data_i[:, j + frame * (args.animate if args.animate else 0) + 1].max() for frame in range(nframes) for data_i, j in axis_data_cols])
|
|
195
|
+
|
|
196
|
+
# set the default axis limits
|
|
197
|
+
ax.set_xlim(min([line.get_xdata().min() for line in ax.lines]), max([line.get_xdata().max() for line in ax.lines])); ax.set_ylim(ymin, ymax)
|
|
198
|
+
|
|
199
|
+
# enlarge the y limit by 5 percent
|
|
200
|
+
ax.set_ylim(ax.get_ylim()[0] - 0.05 * np.diff(ax.get_ylim()), ax.get_ylim()[1] + 0.05 * np.diff(ax.get_ylim()))
|
|
201
|
+
|
|
202
|
+
# enable minor ticks
|
|
203
|
+
ax.xaxis.set_minor_locator(tck.AutoMinorLocator()); ax.yaxis.set_minor_locator(tck.AutoMinorLocator()); ax.tick_params(which="both", direction="in", top=True, right=True)
|
|
204
|
+
|
|
205
|
+
# set the tick label font size
|
|
206
|
+
ax.tick_params(axis="both", which="major", labelsize=args.fontsize_tick[i] if args.fontsize_tick and len(args.fontsize_tick) > i else 12)
|
|
207
|
+
|
|
208
|
+
# extract the fontsize of the legend
|
|
209
|
+
fontsize_legend = args.fontsize_legend[i] if args.fontsize_legend and len(args.fontsize_legend) > i else 10
|
|
210
|
+
|
|
211
|
+
# extract the legend anchor
|
|
212
|
+
anchor_legend = (args.legpos[2 * i], args.legpos[2 * i + 1]) if args.legpos and len(args.legpos) > 2 * i and not np.isnan(args.legpos[2 * i]) and not np.isnan(args.legpos[2 * i + 1]) else None
|
|
213
|
+
|
|
214
|
+
# add the legend
|
|
215
|
+
if any([line.get_label()[0] != "_" for line in ax.lines]): ax.legend(prop={"size": fontsize_legend}, bbox_to_anchor=anchor_legend, loc="upper left")
|
|
216
|
+
|
|
217
|
+
# set the title
|
|
218
|
+
if args.title and len(args.title) > i: ax.set_title(args.title[i], fontsize=args.fontsize_title[i] if args.fontsize_title and len(args.fontsize_title) > i else 16)
|
|
219
|
+
|
|
220
|
+
# set the axis labels
|
|
221
|
+
if args.xlabel and len(args.xlabel) > i: ax.set_xlabel(args.xlabel[i], fontsize=args.fontsize_label[i] if args.fontsize_label and len(args.fontsize_label) > i else 12)
|
|
222
|
+
if args.ylabel and len(args.ylabel) > i: ax.set_ylabel(args.ylabel[i], fontsize=args.fontsize_label[i] if args.fontsize_label and len(args.fontsize_label) > i else 12)
|
|
223
|
+
|
|
224
|
+
# set the axis limits
|
|
225
|
+
if args.xlim and len(args.xlim) > 2 * i and not np.isnan(args.xlim[2 * i]): ax.set_xlim(args.xlim[2 * i + 0:2 * i + 2])
|
|
226
|
+
if args.ylim and len(args.ylim) > 2 * i and not np.isnan(args.ylim[2 * i]): ax.set_ylim(args.ylim[2 * i + 0:2 * i + 2])
|
|
227
|
+
|
|
228
|
+
# enable or disable the x-axis and y-axis tick labels
|
|
229
|
+
if args.xticklabelon and len(args.xticklabelon) > i: ax.xaxis.set_tick_params(labelbottom=args.xticklabelon[i])
|
|
230
|
+
if args.yticklabelon and len(args.yticklabelon) > i: ax.yaxis.set_tick_params(labelleft =args.yticklabelon[i])
|
|
231
|
+
|
|
232
|
+
# add the inset axes if specified
|
|
233
|
+
if args.zoominset and len(args.zoominset) > i and args.zoominset[i]:
|
|
234
|
+
|
|
235
|
+
# parse the inset arguments and create the inset axes
|
|
236
|
+
zoom = list(map(float, args.zoominset[i].split(","))); axins = ax.inset_axes(zoom[:4])
|
|
237
|
+
|
|
238
|
+
# plot the same thing in the inset axes
|
|
239
|
+
for line in ax.lines:
|
|
240
|
+
axins.plot(line.get_xdata(), line.get_ydata(), color=line.get_color(), linestyle=line.get_linestyle(), linewidth=line.get_linewidth() * 0.9, marker=line.get_marker())
|
|
241
|
+
|
|
242
|
+
# disable the x and y axis tick labels in the inset axes
|
|
243
|
+
axins.xaxis.set_visible(False); axins.yaxis.set_visible(False)
|
|
244
|
+
|
|
245
|
+
# set the x and y limits of the inset axes
|
|
246
|
+
axins.set_xlim(zoom[4], zoom[5]); axins.set_ylim(zoom[6], zoom[7])
|
|
247
|
+
|
|
248
|
+
# mark the inset axes in the main axes
|
|
249
|
+
mark_inset(ax, axins, loc1=zoom[8], loc2=zoom[9], ec="0.4", zorder=1000)
|
|
250
|
+
|
|
251
|
+
# set the layout
|
|
252
|
+
fig.tight_layout()
|
|
253
|
+
|
|
254
|
+
# update function
|
|
255
|
+
def update(frame):
|
|
256
|
+
|
|
257
|
+
# loop over the data and its columns to plot
|
|
258
|
+
for i, (data_i, j) in enumerate(dcit(data, data_cols)):
|
|
259
|
+
|
|
260
|
+
# update the data
|
|
261
|
+
plots[i][0].set_ydata(data_i[:, j + frame * args.animate + 1])
|
|
262
|
+
|
|
263
|
+
# loop over the error bars and their columns
|
|
264
|
+
for i, (data_errors_i, j) in enumerate(dcit(data_errors, cols_errors)):
|
|
265
|
+
|
|
266
|
+
# update the error bars
|
|
267
|
+
top = plots[line_errors[i]][0].get_ydata() + data_errors_i[:, j + 1]
|
|
268
|
+
bot = plots[line_errors[i]][0].get_ydata() - data_errors_i[:, j + 1]
|
|
269
|
+
|
|
270
|
+
# fill the area between the top and bottom line
|
|
271
|
+
ebars[i].remove(); ebars[i] = axes[args.subplots[i % len(args.subplots)]].fill_between(data_errors_i[:, 0], bot, top, color=cmap[line_errors[i] % len(cmap)], alpha=0.2)
|
|
272
|
+
|
|
273
|
+
# create the animation
|
|
274
|
+
anim = anm.FuncAnimation(fig, update, frames=(data[0].shape[1] - 1) // args.animate, init_func=lambda: None, interval=1000 // args.fps) if args.animate else None
|
|
275
|
+
|
|
276
|
+
# set the window title
|
|
277
|
+
if not args.output: fig.canvas.manager.set_window_title("Scipl Plotter")
|
|
278
|
+
|
|
279
|
+
# save or show the plot
|
|
280
|
+
(anim.save(args.output, fps=args.fps) if args.animate else plt.savefig(args.output)) if args.output else plt.show()
|
|
281
|
+
|
|
282
|
+
if __name__ == "__main__": main()
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: scipl
|
|
3
|
+
Version: 1.0.0
|
|
4
|
+
Summary: Scientific plotting script.
|
|
5
|
+
Author-email: Tomáš Jíra <tom.jira@gmail.com>
|
|
6
|
+
License-Expression: MIT
|
|
7
|
+
Project-URL: Homepage, https://github.com/tjira/scipl
|
|
8
|
+
Requires-Python: >=3.10
|
|
9
|
+
Description-Content-Type: text/markdown
|
|
10
|
+
License-File: LICENSE
|
|
11
|
+
Requires-Dist: numpy
|
|
12
|
+
Requires-Dist: matplotlib
|
|
13
|
+
Dynamic: license-file
|
|
14
|
+
|
|
15
|
+
# Scipl
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
scipl/__init__.py,sha256=J-j-u0itpEFT6irdmWmixQqYMadNl1X91TxUmoiLHMI,22
|
|
2
|
+
scipl/__main__.py,sha256=ypdzrwi1skujcrRlgUtIrXnXfDknDMS-NvlcwmR_ffI,19820
|
|
3
|
+
scipl-1.0.0.dist-info/licenses/LICENSE,sha256=kObEhZd1-zwX1uvQJjfbxIZn-3ZGMgUTDQ_ijEczqE4,1070
|
|
4
|
+
scipl-1.0.0.dist-info/METADATA,sha256=hBAO1RpbgG9kUic-ZLrSfmIC_SJTSIgCaTxBQZENMyg,377
|
|
5
|
+
scipl-1.0.0.dist-info/WHEEL,sha256=aeYiig01lYGDzBgS8HxWXOg3uV61G9ijOsup-k9o1sk,91
|
|
6
|
+
scipl-1.0.0.dist-info/entry_points.txt,sha256=s1yA_dVzjsC8dzqocSIl8BhN7VJiAa2NXGDcIAiBxpE,46
|
|
7
|
+
scipl-1.0.0.dist-info/top_level.txt,sha256=VtInEByZjjTLu4QxuEovxyR0nceb2uu4u9nfTjnCEcc,6
|
|
8
|
+
scipl-1.0.0.dist-info/RECORD,,
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Tomáš Jíra
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
scipl
|