scipl 1.0.0__tar.gz

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-1.0.0/LICENSE ADDED
@@ -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.
scipl-1.0.0/PKG-INFO ADDED
@@ -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
scipl-1.0.0/README.md ADDED
@@ -0,0 +1 @@
1
+ # Scipl
@@ -0,0 +1,27 @@
1
+ [build-system]
2
+ requires = ["setuptools>=61.0"]
3
+ build-backend = "setuptools.build_meta"
4
+
5
+ [project]
6
+ name = "scipl"
7
+ dynamic = ["version"]
8
+ description = "Scientific plotting script."
9
+ readme = "README.md"
10
+ requires-python = ">=3.10"
11
+ license = "MIT"
12
+ authors = [
13
+ {name = "Tomáš Jíra", email = "tom.jira@gmail.com"},
14
+ ]
15
+ dependencies = [
16
+ "numpy",
17
+ "matplotlib",
18
+ ]
19
+
20
+ [project.urls]
21
+ Homepage = "https://github.com/tjira/scipl"
22
+
23
+ [project.scripts]
24
+ scipl = "scipl.__main__:main"
25
+
26
+ [tool.setuptools.dynamic]
27
+ version = {attr = "scipl.__version__"}
@@ -0,0 +1 @@
1
+ __version__ = "1.0.0"
@@ -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,11 @@
1
+ LICENSE
2
+ README.md
3
+ pyproject.toml
4
+ scipl/__init__.py
5
+ scipl/__main__.py
6
+ scipl.egg-info/PKG-INFO
7
+ scipl.egg-info/SOURCES.txt
8
+ scipl.egg-info/dependency_links.txt
9
+ scipl.egg-info/entry_points.txt
10
+ scipl.egg-info/requires.txt
11
+ scipl.egg-info/top_level.txt
@@ -0,0 +1,2 @@
1
+ [console_scripts]
2
+ scipl = scipl.__main__:main
@@ -0,0 +1,2 @@
1
+ numpy
2
+ matplotlib
@@ -0,0 +1 @@
1
+ scipl
scipl-1.0.0/setup.cfg ADDED
@@ -0,0 +1,4 @@
1
+ [egg_info]
2
+ tag_build =
3
+ tag_date = 0
4
+