tikzplot42 0.4.3__tar.gz → 0.4.5__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.
- {tikzplot42-0.4.3/src/tikzplot42.egg-info → tikzplot42-0.4.5}/PKG-INFO +1 -1
- {tikzplot42-0.4.3 → tikzplot42-0.4.5}/pyproject.toml +1 -1
- {tikzplot42-0.4.3 → tikzplot42-0.4.5}/src/tikzplot/axes.py +229 -50
- {tikzplot42-0.4.3 → tikzplot42-0.4.5}/src/tikzplot/axes.pyi +28 -10
- {tikzplot42-0.4.3 → tikzplot42-0.4.5}/src/tikzplot/axes3d.py +4 -4
- tikzplot42-0.4.5/src/tikzplot/colors.py +228 -0
- {tikzplot42-0.4.3 → tikzplot42-0.4.5}/src/tikzplot/elements.py +59 -51
- {tikzplot42-0.4.3 → tikzplot42-0.4.5}/src/tikzplot/elements.pyi +3 -3
- {tikzplot42-0.4.3 → tikzplot42-0.4.5}/src/tikzplot/figure.py +14 -2
- {tikzplot42-0.4.3 → tikzplot42-0.4.5}/src/tikzplot/figure.pyi +7 -1
- {tikzplot42-0.4.3 → tikzplot42-0.4.5}/src/tikzplot/plots.py +14 -2
- {tikzplot42-0.4.3 → tikzplot42-0.4.5}/src/tikzplot/plots.pyi +4 -2
- {tikzplot42-0.4.3 → tikzplot42-0.4.5}/src/tikzplot/texts.py +2 -2
- {tikzplot42-0.4.3 → tikzplot42-0.4.5/src/tikzplot42.egg-info}/PKG-INFO +1 -1
- {tikzplot42-0.4.3 → tikzplot42-0.4.5}/src/tikzplot42.egg-info/SOURCES.txt +2 -0
- tikzplot42-0.4.5/tests/test12.py +32 -0
- tikzplot42-0.4.5/tests/test13.py +28 -0
- tikzplot42-0.4.3/src/tikzplot/colors.py +0 -60
- {tikzplot42-0.4.3 → tikzplot42-0.4.5}/LICENSE +0 -0
- {tikzplot42-0.4.3 → tikzplot42-0.4.5}/README.md +0 -0
- {tikzplot42-0.4.3 → tikzplot42-0.4.5}/setup.cfg +0 -0
- {tikzplot42-0.4.3 → tikzplot42-0.4.5}/src/tikzplot/__init__.py +0 -0
- {tikzplot42-0.4.3 → tikzplot42-0.4.5}/src/tikzplot/__init__.pyi +0 -0
- {tikzplot42-0.4.3 → tikzplot42-0.4.5}/src/tikzplot/axes3d.pyi +0 -0
- {tikzplot42-0.4.3 → tikzplot42-0.4.5}/src/tikzplot/colorbar.py +0 -0
- {tikzplot42-0.4.3 → tikzplot42-0.4.5}/src/tikzplot/colorbar.pyi +0 -0
- {tikzplot42-0.4.3 → tikzplot42-0.4.5}/src/tikzplot/config.py +0 -0
- {tikzplot42-0.4.3 → tikzplot42-0.4.5}/src/tikzplot/config.pyi +0 -0
- {tikzplot42-0.4.3 → tikzplot42-0.4.5}/src/tikzplot/latex_special.py +0 -0
- {tikzplot42-0.4.3 → tikzplot42-0.4.5}/src/tikzplot/py.typed +0 -0
- {tikzplot42-0.4.3 → tikzplot42-0.4.5}/src/tikzplot/state.py +0 -0
- {tikzplot42-0.4.3 → tikzplot42-0.4.5}/src/tikzplot/styles.py +0 -0
- {tikzplot42-0.4.3 → tikzplot42-0.4.5}/src/tikzplot/styles.pyi +0 -0
- {tikzplot42-0.4.3 → tikzplot42-0.4.5}/src/tikzplot42.egg-info/dependency_links.txt +0 -0
- {tikzplot42-0.4.3 → tikzplot42-0.4.5}/src/tikzplot42.egg-info/requires.txt +0 -0
- {tikzplot42-0.4.3 → tikzplot42-0.4.5}/src/tikzplot42.egg-info/top_level.txt +0 -0
- {tikzplot42-0.4.3 → tikzplot42-0.4.5}/tests/test1.py +0 -0
- {tikzplot42-0.4.3 → tikzplot42-0.4.5}/tests/test10.py +0 -0
- {tikzplot42-0.4.3 → tikzplot42-0.4.5}/tests/test11.py +0 -0
- {tikzplot42-0.4.3 → tikzplot42-0.4.5}/tests/test2.py +0 -0
- {tikzplot42-0.4.3 → tikzplot42-0.4.5}/tests/test3.py +0 -0
- {tikzplot42-0.4.3 → tikzplot42-0.4.5}/tests/test4.py +0 -0
- {tikzplot42-0.4.3 → tikzplot42-0.4.5}/tests/test5.py +0 -0
- {tikzplot42-0.4.3 → tikzplot42-0.4.5}/tests/test6.py +0 -0
- {tikzplot42-0.4.3 → tikzplot42-0.4.5}/tests/test7.py +0 -0
- {tikzplot42-0.4.3 → tikzplot42-0.4.5}/tests/test8.py +0 -0
- {tikzplot42-0.4.3 → tikzplot42-0.4.5}/tests/test9.py +0 -0
- {tikzplot42-0.4.3 → tikzplot42-0.4.5}/tests/test_styles.py +0 -0
|
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "tikzplot42"
|
|
7
|
-
version = "0.4.
|
|
7
|
+
version = "0.4.5"
|
|
8
8
|
description = "TikzPlot to make TikZ/PGFPlots plots with matplotlib.pyplot-like syntax."
|
|
9
9
|
authors = [
|
|
10
10
|
{ name = "Zan Ambrozic", email = "zan.ambrozic7@gmail.com" }
|
|
@@ -1,3 +1,6 @@
|
|
|
1
|
+
from typing import Any
|
|
2
|
+
from xml.dom import XMLNS_NAMESPACE
|
|
3
|
+
|
|
1
4
|
import numpy as _np
|
|
2
5
|
import matplotlib.pyplot as _plt
|
|
3
6
|
|
|
@@ -7,6 +10,7 @@ from .config import TikzConfig
|
|
|
7
10
|
from .colorbar import Colorbar
|
|
8
11
|
from .state import _next_imshow_num, main_name
|
|
9
12
|
from .latex_special import tex_text
|
|
13
|
+
from .colors import _tex_color
|
|
10
14
|
|
|
11
15
|
class BaseAxes:
|
|
12
16
|
def __init__(self):
|
|
@@ -22,17 +26,20 @@ class BaseAxes:
|
|
|
22
26
|
self._axis_args.add(f"/pgf/number format/.cd, 1000 sep={{{TikzConfig.THOUSANDS_SEP}}}")
|
|
23
27
|
|
|
24
28
|
self._add_legend = []
|
|
29
|
+
self._legend_lab_col: Any = None
|
|
25
30
|
self._coordinates = {}
|
|
26
31
|
self._cmap_bar = None
|
|
27
32
|
|
|
28
33
|
self._ext_ymin = False
|
|
29
34
|
self._ext_ymax = False
|
|
30
35
|
|
|
31
|
-
|
|
36
|
+
self._reverse_elements = []
|
|
37
|
+
|
|
38
|
+
def _plot(self, x, y, settings={}, xerr=None, yerr=None, **style):
|
|
32
39
|
if isinstance(self, Axes) and self._polar:
|
|
33
40
|
x = _np.rad2deg(x)
|
|
34
41
|
e = Graph(self, (x, y), settings, xerr=xerr, yerr=yerr, **style)
|
|
35
|
-
if TikzConfig.USE_GROUPPLOTS and ("axvspan"
|
|
42
|
+
if TikzConfig.USE_GROUPPLOTS and ("axvspan" in settings or "axhspan" in settings):
|
|
36
43
|
self._elements.insert(0, e)
|
|
37
44
|
else:
|
|
38
45
|
self._elements.append(e)
|
|
@@ -88,7 +95,7 @@ class BaseAxes:
|
|
|
88
95
|
self._cmap_bar = kwargs["cmap"]
|
|
89
96
|
except: pass
|
|
90
97
|
|
|
91
|
-
return self._plot(x, y, **kwargs, ls="", settings=
|
|
98
|
+
return self._plot(x, y, **kwargs, ls="", settings={"scatter": None})
|
|
92
99
|
|
|
93
100
|
def semilogy(self, x, y, *args, **kwargs):
|
|
94
101
|
kws = {"fmt", "base", "alpha", "color", "c", "linestyle", "ls", "linewidth", "lw", "marker", "markersize", "ms", "label"}
|
|
@@ -126,9 +133,9 @@ class BaseAxes:
|
|
|
126
133
|
if o == "horizontal":
|
|
127
134
|
vert = False
|
|
128
135
|
if vert:
|
|
129
|
-
return self._plot(x,y,settings=
|
|
136
|
+
return self._plot(x,y,settings={"ycomb": None}, **kwargs)
|
|
130
137
|
else:
|
|
131
|
-
return self._plot(y,x,settings=
|
|
138
|
+
return self._plot(y,x,settings={"xcomb": None}, **kwargs)
|
|
132
139
|
|
|
133
140
|
def fill_between(self, x, y1, y2=None, **kwargs):
|
|
134
141
|
kws = {"fmt", "alpha", "color", "c", "label"}
|
|
@@ -166,7 +173,7 @@ class BaseAxes:
|
|
|
166
173
|
self._plot(xs,ys,path_name=name2, alpha=0)
|
|
167
174
|
else:
|
|
168
175
|
name2 = inst
|
|
169
|
-
e = Graph(self, f"fill between [of={name1} and {name2}]",settings=
|
|
176
|
+
e = Graph(self, f"fill between [of={name1} and {name2}]",settings={}, xerr=None, yerr=None, **kwargs)
|
|
170
177
|
self._elements.append(e)
|
|
171
178
|
return e
|
|
172
179
|
|
|
@@ -215,41 +222,142 @@ class BaseAxes:
|
|
|
215
222
|
self._plot([xs[i]]*2, [ymins[i], ymaxs[i]], None, None, None, c=colorss[i], ls=lss[i])
|
|
216
223
|
|
|
217
224
|
def hist(self, x, bins=10, density=False,**kwargs):
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
225
|
+
kws = {"alpha", "color", "c", "label", "facecolor", "fc", "edgecolor", "ec", "orientation", "rwidth", "cumulative", "range", "histtype", "weights", "cumulative", "align", "stacked", "fill"}
|
|
226
|
+
kwargs = self._check_kwargs("hist", kws, **kwargs)
|
|
227
|
+
if isinstance(x, (list, tuple)) and len(x) > 0 and isinstance(x[0], (list, tuple, _np.ndarray)):
|
|
228
|
+
try:
|
|
229
|
+
datasets = [_np.asarray(ds, dtype=_np.float64) for ds in x]
|
|
230
|
+
if any(ds.ndim != 1 for ds in datasets):
|
|
231
|
+
raise ValueError("Nested datasets must all be 1-dimensional.")
|
|
232
|
+
except (ValueError, TypeError):
|
|
233
|
+
x_arr = _np.asarray(x)
|
|
234
|
+
if x_arr.ndim == 2:
|
|
235
|
+
datasets = [x_arr[:, i] for i in range(x_arr.shape[1])]
|
|
236
|
+
else:
|
|
237
|
+
raise ValueError("Invalid dataset structure.")
|
|
238
|
+
else:
|
|
239
|
+
x_arr = _np.asarray(x)
|
|
240
|
+
if x_arr.ndim == 1:
|
|
241
|
+
datasets = [x_arr]
|
|
242
|
+
elif x_arr.ndim == 2:
|
|
243
|
+
datasets = [x_arr[:, i] for i in range(x_arr.shape[1])]
|
|
244
|
+
else:
|
|
245
|
+
raise ValueError(f"Input must be 1D or 2D, got {x_arr.ndim}D.")
|
|
246
|
+
|
|
247
|
+
stack = kwargs.pop("stacked", False)
|
|
248
|
+
datas = {}
|
|
249
|
+
for kw in ["color", "c", "facecolor", "fc", "edgecolor", "ec", "label"]:
|
|
250
|
+
if kw in kwargs:
|
|
251
|
+
if isinstance(kwargs[kw], (list)):
|
|
252
|
+
if len(kwargs[kw]) != len(datasets):
|
|
253
|
+
raise Warning(f"Length of {kw} does not match number of datasets.")
|
|
254
|
+
prop = kwargs.pop(kw)
|
|
255
|
+
else:
|
|
256
|
+
prop = [kwargs.pop(kw)] * len(datasets)
|
|
257
|
+
for i in range(len(datasets)):
|
|
258
|
+
if i not in datas:
|
|
259
|
+
datas[i] = {}
|
|
260
|
+
datas[i][kw] = prop[i]
|
|
226
261
|
all_data = _np.concatenate(datasets)
|
|
227
|
-
edges = _np.histogram_bin_edges(all_data, bins=bins)
|
|
262
|
+
edges = _np.histogram_bin_edges(all_data, bins=bins, weights=kwargs.get("weights", None), range=kwargs.get("range", None))
|
|
228
263
|
widths = edges[1:] - edges[:-1]
|
|
229
|
-
|
|
264
|
+
offset = 0
|
|
265
|
+
settings = {}
|
|
266
|
+
hist_type = kwargs.pop("histtype", "bar")
|
|
267
|
+
if hist_type not in ["bar", "barstacked", "step", "stepfilled"]:
|
|
268
|
+
raise Warning(f"Invalid histtype: {hist_type}.")
|
|
230
269
|
if "orientation" in kwargs and kwargs["orientation"] == "horizontal":
|
|
231
|
-
settings
|
|
270
|
+
settings["xbar"] = None
|
|
232
271
|
else:
|
|
233
|
-
settings
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
272
|
+
settings["ybar"] = None
|
|
273
|
+
if ("rwidth" in kwargs or (len(datasets) > 1 and not stack)) and isinstance(bins, int):
|
|
274
|
+
if stack or len(datasets) == 1:
|
|
275
|
+
settings["bar width"] = f"{widths.mean()*kwargs['rwidth']}"
|
|
276
|
+
else:
|
|
277
|
+
if "rwidth" in kwargs:
|
|
278
|
+
settings["bar width"] = f"{widths.mean()*kwargs['rwidth']/(len(datasets)+1)}"
|
|
279
|
+
offset = widths.mean() * kwargs['rwidth'] / (len(datasets) + 1)
|
|
280
|
+
else:
|
|
281
|
+
settings["bar width"] = f"{widths.mean()/(len(datasets)+1)}"
|
|
282
|
+
offset = widths.mean() / (len(datasets) + 1)
|
|
237
283
|
else:
|
|
238
|
-
|
|
284
|
+
if "xbar" in settings:
|
|
285
|
+
settings.pop("xbar")
|
|
286
|
+
settings["xbar interval"] = None
|
|
287
|
+
elif "ybar" in settings:
|
|
288
|
+
settings.pop("ybar")
|
|
289
|
+
settings["ybar interval"] = None
|
|
239
290
|
if "range" in kwargs:
|
|
240
|
-
if
|
|
291
|
+
if "xbar" in settings:
|
|
241
292
|
self.set_ylim(kwargs["range"])
|
|
242
293
|
elif isinstance(self, Axes):
|
|
243
294
|
self.set_xlim(kwargs["range"])
|
|
244
295
|
elif isinstance(self, Secondary):
|
|
245
296
|
self._primary.set_xlim(kwargs["range"])
|
|
297
|
+
base_settings = settings.copy()
|
|
246
298
|
outputs = []
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
299
|
+
old_counts = _np.zeros(len(edges), dtype=_np.float64)
|
|
300
|
+
totals, _ = _np.histogram(all_data, edges, density=False, weights=kwargs.get("weights", None), range=kwargs.get("range", None))
|
|
301
|
+
tot_sum = totals.sum()
|
|
302
|
+
for i in range(len(datasets)):
|
|
303
|
+
data = datasets[i]
|
|
304
|
+
settings = base_settings.copy()
|
|
305
|
+
kws = datas.get(i, {})
|
|
306
|
+
if "label" in kws:
|
|
307
|
+
if "xbar" in settings or "xbar interval" in settings:
|
|
308
|
+
settings["xbar legend"] = None
|
|
309
|
+
else:
|
|
310
|
+
settings["ybar legend"] = None
|
|
311
|
+
else:
|
|
312
|
+
settings["forget plot"] = None
|
|
313
|
+
fill = kws.pop("facecolor", kws.pop("fc", kws.pop("color", kws.pop("c", None))))
|
|
314
|
+
draw = kws.pop("edgecolor", kws.pop("ec", None))
|
|
315
|
+
if fill:
|
|
316
|
+
fill = self._match_color(fill)
|
|
317
|
+
settings["fill"] = fill
|
|
318
|
+
if draw and hist_type != "stepfilled":
|
|
319
|
+
draw = self._match_color(draw)
|
|
320
|
+
settings["draw"] = draw
|
|
321
|
+
else:
|
|
322
|
+
settings["draw"] = "none"
|
|
323
|
+
counts, _ = _np.histogram(data, edges, density=density, weights=kwargs.get("weights", None), range=kwargs.get("range", None))
|
|
324
|
+
if "xbar interval" in settings or "ybar interval" in settings: # edges for interval
|
|
325
|
+
if "rwidth" in kwargs:
|
|
326
|
+
xs = [edges[0] + widths[0]*(1-kwargs["rwidth"])/2]
|
|
327
|
+
new_counts = []
|
|
328
|
+
for j in range(len(widths)): # Changed 'i' to 'j' to avoid overwriting dataset index 'i'
|
|
329
|
+
xs.append(xs[-1] + widths[j]*kwargs["rwidth"])
|
|
330
|
+
new_counts.append(counts[j])
|
|
331
|
+
if j < len(counts)-1:
|
|
332
|
+
xs.append(xs[-1] + (widths[j] + widths[j+1])*(1-kwargs["rwidth"])/2)
|
|
333
|
+
new_counts.append(0)
|
|
334
|
+
counts = new_counts + [0]
|
|
335
|
+
else:
|
|
336
|
+
xs = edges
|
|
337
|
+
counts = _np.concatenate([counts, [0]])
|
|
338
|
+
else: # centers
|
|
339
|
+
xs = (edges[:-1] + edges[1:]) / 2
|
|
340
|
+
if offset > 0:
|
|
341
|
+
settings["bar shift"] = f"{offset*(i - len(datasets)/2 + 0.5)}"
|
|
250
342
|
if "cumulative" in kwargs and kwargs["cumulative"]:
|
|
251
343
|
counts = _np.cumsum(counts)
|
|
252
|
-
|
|
344
|
+
if stack:
|
|
345
|
+
if density:
|
|
346
|
+
set_counts, _ = _np.histogram(data, edges, density=False, weights=kwargs.get("weights", None), range=kwargs.get("range", None))
|
|
347
|
+
counts = counts * _np.sum(set_counts) / tot_sum
|
|
348
|
+
counts = _np.asarray(counts, dtype=_np.float64)
|
|
349
|
+
counts += old_counts
|
|
350
|
+
old_counts = counts.copy()
|
|
351
|
+
if hist_type == "step":
|
|
352
|
+
kwargs.pop("facecolor", None)
|
|
353
|
+
kwargs.pop("fc", None)
|
|
354
|
+
kwargs.pop("fill", None)
|
|
355
|
+
self.step([edges[0]] + list(edges), [0] + list(counts), where="pre", **kws)
|
|
356
|
+
else:
|
|
357
|
+
e = self._plot(xs, counts, settings=settings, **kws)
|
|
358
|
+
outputs.append(e)
|
|
359
|
+
if outputs and stack:
|
|
360
|
+
self._reverse_elements.append([id(e) for e in outputs])
|
|
253
361
|
return outputs
|
|
254
362
|
|
|
255
363
|
def step(self, x, y, *args, **kwargs):
|
|
@@ -257,7 +365,7 @@ class BaseAxes:
|
|
|
257
365
|
kwargs = self._check_kwargs("step", kws, **kwargs)
|
|
258
366
|
WHERE_DICT = {"pre": "left", "post": "right", "mid": "mid"}
|
|
259
367
|
where = WHERE_DICT.get(kwargs.pop("where", "pre"), None)
|
|
260
|
-
settings =
|
|
368
|
+
settings = {f"const plot mark {where}": None}
|
|
261
369
|
if len(args) == 1:
|
|
262
370
|
kwargs["fmt"] = args[0]
|
|
263
371
|
return self._plot(x,y,settings=settings, **kwargs)
|
|
@@ -266,7 +374,7 @@ class BaseAxes:
|
|
|
266
374
|
kws = {"fmt", "base", "alpha", "color", "c", "linestyle", "ls", "linewidth", "lw", "label"}
|
|
267
375
|
kwargs = self._check_kwargs("axvline", kws, **kwargs)
|
|
268
376
|
self._ext_ymin = self._ext_ymax = True
|
|
269
|
-
self._plot(x, (ymin, ymax), settings="axvline", **kwargs)
|
|
377
|
+
self._plot(x, (ymin, ymax), settings={"axvline": None}, **kwargs)
|
|
270
378
|
|
|
271
379
|
def axhline(self, y, xmin=0, xmax=1, **kwargs):
|
|
272
380
|
kws = {"fmt", "base", "alpha", "color", "c", "linestyle", "ls", "linewidth", "lw", "label"}
|
|
@@ -275,7 +383,7 @@ class BaseAxes:
|
|
|
275
383
|
self._primary._ext_xmin = self._primary._ext_xmax = True
|
|
276
384
|
else:
|
|
277
385
|
self._ext_xmin = self._ext_xmax = True
|
|
278
|
-
self._plot((xmin, xmax), y, settings="axhline", **kwargs)
|
|
386
|
+
self._plot((xmin, xmax), y, settings={"axhline": None}, **kwargs)
|
|
279
387
|
|
|
280
388
|
def axvspan(self, xmin, xmax, ymin=0, ymax=1, **kwargs):
|
|
281
389
|
kws = {"c", "color", "alpha", "label"}
|
|
@@ -283,7 +391,7 @@ class BaseAxes:
|
|
|
283
391
|
self._ext_ymin = self._ext_ymax = True
|
|
284
392
|
if TikzConfig.USE_GROUPPLOTS:
|
|
285
393
|
self._axis_args.add("set layers")
|
|
286
|
-
self._plot([xmin, xmax], [ymin, ymax], settings="axvspan", **kwargs)
|
|
394
|
+
self._plot([xmin, xmax], [ymin, ymax], settings={"axvspan": None}, **kwargs)
|
|
287
395
|
|
|
288
396
|
def axhspan(self, ymin, ymax, xmin=0, xmax=1, **kwargs):
|
|
289
397
|
kws = {"c", "color", "alpha", "label"}
|
|
@@ -294,7 +402,7 @@ class BaseAxes:
|
|
|
294
402
|
self._ext_xmin = self._ext_xmax = True
|
|
295
403
|
if TikzConfig.USE_GROUPPLOTS:
|
|
296
404
|
self._axis_args.add("set layers")
|
|
297
|
-
self._plot([xmin, xmax], [ymin, ymax], settings="axhspan", **kwargs)
|
|
405
|
+
self._plot([xmin, xmax], [ymin, ymax], settings={"axhspan": None}, **kwargs)
|
|
298
406
|
|
|
299
407
|
def set_ylabel(self, label):
|
|
300
408
|
self._axis_options["ylabel"] = f"{{{tex_text(label)}}}"
|
|
@@ -354,7 +462,19 @@ class BaseAxes:
|
|
|
354
462
|
_LEGEND_LOC_MAP = ["best", "upper right", "upper left", "lower_left", "lower right", "right", "center left", "center right", "lower center", "upper center", "center"]
|
|
355
463
|
_ANCHOR_MAP = {"top": "north", "bottom": "south", "upper": "north", "lower": "south", "left": "west", "right": "east", "center": "center"}
|
|
356
464
|
|
|
465
|
+
def _match_color(self, input):
|
|
466
|
+
if isinstance(self, Axes) or isinstance(self, Secondary):
|
|
467
|
+
if input == "none":
|
|
468
|
+
return "none"
|
|
469
|
+
ccode, op = _tex_color(input, self._style)
|
|
470
|
+
if isinstance(ccode, str):
|
|
471
|
+
return ccode
|
|
472
|
+
r,g,b = ccode
|
|
473
|
+
self._add_col(r,g,b)
|
|
474
|
+
return f"c{r:.3f}{g:.3f}{b:.3f}".replace(".", "")
|
|
475
|
+
|
|
357
476
|
def legend(self, *args, **kwargs):
|
|
477
|
+
legend_string = {}
|
|
358
478
|
if "loc" in kwargs:
|
|
359
479
|
loc = kwargs["loc"]
|
|
360
480
|
lx = ly = posit = None
|
|
@@ -381,20 +501,34 @@ class BaseAxes:
|
|
|
381
501
|
elif "east" in posit:
|
|
382
502
|
lx = 1 - TikzConfig.LEGEND_REL_X
|
|
383
503
|
|
|
384
|
-
legend_string = []
|
|
385
504
|
if lx is not None and ly is not None:
|
|
386
|
-
legend_string
|
|
505
|
+
legend_string["at"] = "{(" + f"{lx},{ly}" + r")}"
|
|
387
506
|
if posit is not None and len(posit):
|
|
388
|
-
legend_string
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
507
|
+
legend_string["anchor"] = posit
|
|
508
|
+
|
|
509
|
+
if "facecolor" in kwargs and (isinstance(self, Axes) or isinstance(self, Secondary)):
|
|
510
|
+
ccode = self._match_color(kwargs["facecolor"])
|
|
511
|
+
if ccode is not None:
|
|
512
|
+
legend_string["fill"] = ccode
|
|
513
|
+
if "edgecolor" in kwargs and (isinstance(self, Axes) or isinstance(self, Secondary)):
|
|
514
|
+
ccode = self._match_color(kwargs["edgecolor"])
|
|
515
|
+
if ccode is not None:
|
|
516
|
+
legend_string["draw"] = ccode
|
|
517
|
+
if "labelcolor" in kwargs and (isinstance(self, Axes) or isinstance(self, Secondary)):
|
|
518
|
+
ccode = self._match_color(kwargs["labelcolor"])
|
|
519
|
+
if ccode is not None:
|
|
520
|
+
self._legend_lab_col = ccode
|
|
521
|
+
if "frameon" in kwargs and not kwargs["frameon"]:
|
|
522
|
+
legend_string["draw"] = "none"
|
|
523
|
+
if "legend style" in self._axis_options:
|
|
524
|
+
self._axis_options["legend style"].update(legend_string)
|
|
525
|
+
else:
|
|
526
|
+
self._axis_options["legend style"] = legend_string
|
|
393
527
|
self._legend_on = True
|
|
394
528
|
if "ncols" in kwargs:
|
|
395
529
|
self._axis_options["legend columns"] = kwargs["ncols"]
|
|
396
530
|
if len(args) == 2:
|
|
397
|
-
self._add_legend = args
|
|
531
|
+
self._add_legend = list(args)
|
|
398
532
|
elif len(args) == 1:
|
|
399
533
|
labs = args[0]
|
|
400
534
|
if len(labs) > len(self._elements):
|
|
@@ -433,16 +567,36 @@ class BaseAxes:
|
|
|
433
567
|
return ""
|
|
434
568
|
for i in range(len(axs)):
|
|
435
569
|
output += f"\n\\addlegendimage{{{axs[i]._style_string()}}}"
|
|
436
|
-
|
|
570
|
+
if self._legend_lab_col:
|
|
571
|
+
output += f"\n\\addlegendentry[{self._legend_lab_col}]{{{tex_text(labs[i])}}}"
|
|
572
|
+
else:
|
|
573
|
+
output += f"\n\\addlegendentry{{{tex_text(labs[i])}}}"
|
|
437
574
|
return output
|
|
438
575
|
|
|
439
576
|
def _content_tex(self, filename):
|
|
440
|
-
|
|
441
|
-
|
|
577
|
+
element_strings = {id(e): e._to_tex(filename, self._legend_lab_col) for e in self._elements}
|
|
578
|
+
seq_map = {seq[0]: seq for seq in self._reverse_elements}
|
|
579
|
+
output_list = []
|
|
580
|
+
visited = set()
|
|
581
|
+
for e in self._elements:
|
|
582
|
+
e_id = id(e)
|
|
583
|
+
if e_id in visited:
|
|
584
|
+
continue
|
|
585
|
+
if e_id in seq_map:
|
|
586
|
+
seq = seq_map[e_id]
|
|
587
|
+
for el in reversed(seq):
|
|
588
|
+
output_list.append(element_strings[el])
|
|
589
|
+
visited.add(el)
|
|
590
|
+
else:
|
|
591
|
+
output_list.append(element_strings[e_id])
|
|
592
|
+
visited.add(e_id)
|
|
593
|
+
|
|
594
|
+
output = "\n".join(output_list)
|
|
595
|
+
output += self._add_legend_entries()
|
|
442
596
|
for coord in self._coordinates:
|
|
443
597
|
x,y = self._coordinates[coord]
|
|
444
|
-
|
|
445
|
-
return
|
|
598
|
+
output += f"\n\\coordinate ({coord}) at ({x},{y});"
|
|
599
|
+
return output
|
|
446
600
|
|
|
447
601
|
def _get_hard_range(self,which):
|
|
448
602
|
arg = f"{which[0]}mode"
|
|
@@ -519,6 +673,10 @@ class BaseAxes:
|
|
|
519
673
|
if attr in kwargs:
|
|
520
674
|
defined[attr](kwargs.pop(attr))
|
|
521
675
|
|
|
676
|
+
def _reoreder_last_elements(self, n):
|
|
677
|
+
if n <= 0: return
|
|
678
|
+
self._elements = self._elements[:-n] + self._elements[:-n-1:-1]
|
|
679
|
+
|
|
522
680
|
class Axes(BaseAxes):
|
|
523
681
|
|
|
524
682
|
def __init__(self, nrows, ncols, index, fig, polar):
|
|
@@ -654,7 +812,7 @@ class Axes(BaseAxes):
|
|
|
654
812
|
if kwargs:
|
|
655
813
|
accepted_kwargs = {"color", "c", "linestyle", "ls", "linewidth", "lw", "alpha"}
|
|
656
814
|
kwargs = self._check_kwargs("grid", accepted_kwargs, **kwargs)
|
|
657
|
-
g = Graph(self, None,
|
|
815
|
+
g = Graph(self, None, {}, None, None, **kwargs)._style_string()
|
|
658
816
|
self._axis_options[f"{selector}grid style"] = f"{{{g}}}"
|
|
659
817
|
|
|
660
818
|
def set_minorticks_num(self, num):
|
|
@@ -733,7 +891,7 @@ class Axes(BaseAxes):
|
|
|
733
891
|
_plt.axis("off")
|
|
734
892
|
_plt.imshow(*args, **kwargs)
|
|
735
893
|
im_name = f"{str(main_name()[1]).removesuffix('.py')}_{TikzConfig.IMSHOW_SAVENAME}{_next_imshow_num()}.pdf"
|
|
736
|
-
_plt.savefig(im_name,bbox_inches='tight', pad_inches=0)
|
|
894
|
+
_plt.savefig(im_name, bbox_inches='tight', pad_inches=0)
|
|
737
895
|
return im_name
|
|
738
896
|
|
|
739
897
|
def _axis_option_string(self):
|
|
@@ -754,7 +912,7 @@ class Axes(BaseAxes):
|
|
|
754
912
|
if "extent" in self._imshow[1]:
|
|
755
913
|
bounds = self._imshow[1]["extent"]
|
|
756
914
|
xm, xM, ym, yM = bounds
|
|
757
|
-
self._elements.insert(0, Graph(self, f"graphics [xmin={xm}, xmax={xM}, ymin={ym}, ymax={yM}] {{{im_name}}}",settings=
|
|
915
|
+
self._elements.insert(0, Graph(self, f"graphics [xmin={xm}, xmax={xM}, ymin={ym}, ymax={yM}] {{{im_name}}}", settings={}, xerr=None, yerr=None, onlayer="axis background"))
|
|
758
916
|
axis_opt_str = ""
|
|
759
917
|
if self._axis_args:
|
|
760
918
|
axis_opt_str += ",\n".join(self._axis_args)
|
|
@@ -787,7 +945,13 @@ class Axes(BaseAxes):
|
|
|
787
945
|
self._axis_options["ymax"] = self._fig._next_limname("ymax", self._axis_options.get("ymax", yM))
|
|
788
946
|
if self._axis_options:
|
|
789
947
|
if axis_opt_str: axis_opt_str += ",\n"
|
|
790
|
-
|
|
948
|
+
for k, v in self._axis_options.items():
|
|
949
|
+
if isinstance(v, dict):
|
|
950
|
+
axis_opt_str += f"{k}={{"
|
|
951
|
+
axis_opt_str += ",\n".join(f"{kk}={vv}" for kk, vv in v.items())
|
|
952
|
+
axis_opt_str += "},\n"
|
|
953
|
+
else:
|
|
954
|
+
axis_opt_str += f"{k}={v},\n"
|
|
791
955
|
if self._colorbar:
|
|
792
956
|
axis_opt_str += self._colorbar
|
|
793
957
|
elif self._cmap_bar:
|
|
@@ -859,6 +1023,15 @@ class Axes(BaseAxes):
|
|
|
859
1023
|
defined[attr](kwargs.pop(attr))
|
|
860
1024
|
|
|
861
1025
|
super().set(**kwargs)
|
|
1026
|
+
|
|
1027
|
+
def set_facecolor(self, color):
|
|
1028
|
+
ccode, _ = _tex_color(color, self._style)
|
|
1029
|
+
if isinstance(ccode, str):
|
|
1030
|
+
self._axis_options["axis background/.style"] = f"{{fill={ccode}}}"
|
|
1031
|
+
else:
|
|
1032
|
+
r,g,b = ccode
|
|
1033
|
+
self._add_col(r,g,b)
|
|
1034
|
+
self._axis_options["axis background/.style"] = f"{{fill=c{r:.3f}{g:.3f}{b:.3f}}}".replace(".", "")
|
|
862
1035
|
|
|
863
1036
|
class Secondary(BaseAxes):
|
|
864
1037
|
def __init__(self, primary):
|
|
@@ -900,7 +1073,13 @@ class Secondary(BaseAxes):
|
|
|
900
1073
|
self._axis_options["xmax"] = self._primary._axis_options["xmax"]
|
|
901
1074
|
if self._axis_options:
|
|
902
1075
|
if axis_opt_str: axis_opt_str += ",\n"
|
|
903
|
-
|
|
1076
|
+
for k, v in self._axis_options.items():
|
|
1077
|
+
if isinstance(v, dict):
|
|
1078
|
+
axis_opt_str += f"{k}={{"
|
|
1079
|
+
axis_opt_str += ",\n".join(f"{kk}={vv}" for kk, vv in v.items())
|
|
1080
|
+
axis_opt_str += "},\n"
|
|
1081
|
+
else:
|
|
1082
|
+
axis_opt_str += f"{k}={v},\n"
|
|
904
1083
|
return axis_opt_str
|
|
905
1084
|
|
|
906
1085
|
def _padding(self):
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
from typing import Any, Optional, Sequence, Tuple, Union, Literal
|
|
2
2
|
import numpy as np
|
|
3
|
-
from pyrsistent import T
|
|
4
3
|
from .colorbar import Colorbar
|
|
5
4
|
|
|
6
5
|
ArrayLike = Union[Sequence[float], np.ndarray]
|
|
@@ -277,15 +276,24 @@ class BaseAxes:
|
|
|
277
276
|
def hist(
|
|
278
277
|
self,
|
|
279
278
|
x: Union[ArrayLike, Sequence[ArrayLike]],
|
|
280
|
-
bins: int =
|
|
281
|
-
density: bool = ...,
|
|
279
|
+
bins: int | Sequence[float] = 10,
|
|
282
280
|
*,
|
|
283
|
-
|
|
281
|
+
weight: ArrayLike | None = None,
|
|
282
|
+
density: bool = False,
|
|
283
|
+
cumulative: bool = False,
|
|
284
|
+
histtype: Literal["bar", "barstacked", "step", "stepfilled"] = "bar",
|
|
284
285
|
orientation: Literal["horizontal","vertical"] = "vertical",
|
|
285
|
-
rwidth:
|
|
286
|
-
range:
|
|
287
|
-
color:
|
|
288
|
-
|
|
286
|
+
rwidth: float | None = None,
|
|
287
|
+
range: Tuple[float,float] | None = None,
|
|
288
|
+
color: ColorLike = ...,
|
|
289
|
+
facecolor: ColorLike = ...,
|
|
290
|
+
fc: ColorLike = ...,
|
|
291
|
+
edgecolor: ColorLike = ...,
|
|
292
|
+
ec: ColorLike = ...,
|
|
293
|
+
align: Literal["left", "mid", "right"] = ...,
|
|
294
|
+
stacked: bool = False,
|
|
295
|
+
fill: bool = True,
|
|
296
|
+
#**kwargs: Any
|
|
289
297
|
) -> None:
|
|
290
298
|
"""
|
|
291
299
|
Draw histogram to the selected axis.
|
|
@@ -482,7 +490,7 @@ class BaseAxes:
|
|
|
482
490
|
Set y-axis tick labels.
|
|
483
491
|
"""
|
|
484
492
|
...
|
|
485
|
-
def legend(self, *args: Any, loc: Optional[Union[int,str,Tuple[float,float]]] = ...) -> None:
|
|
493
|
+
def legend(self, *args: Any, loc: Optional[Union[int,str,Tuple[float,float]]] = ..., facecolor: Optional[ColorLike] = ..., edgecolor: Optional[ColorLike] = ..., labelcolor: Optional[ColorLike] = ..., frameon: Optional[bool] = ...) -> None:
|
|
486
494
|
"""
|
|
487
495
|
Show legend for the selected axis. Despite arguments requires at least one plotted element on the axis (not necesarily with label) to show up (LaTeX does not allow legend on empty axis).
|
|
488
496
|
|
|
@@ -510,7 +518,7 @@ class BaseAxes:
|
|
|
510
518
|
def _get_limit(self, which: Literal["xmin","xmax","ymin","ymax"]) -> Tuple[float,bool,str]: ...
|
|
511
519
|
def _set_range(self, which: Literal["xmin","xmax","ymin","ymax"], value: Union[float, int]): ...
|
|
512
520
|
def _num_points(self) -> list[int]: ...
|
|
513
|
-
|
|
521
|
+
def _add_col(self, r: float, g: float, b: float) -> None: ...
|
|
514
522
|
|
|
515
523
|
class Axes(BaseAxes):
|
|
516
524
|
def __init__(self, nrows: int, ncols: int, index: int, fig: Any, pol: bool) -> None: ...
|
|
@@ -663,6 +671,16 @@ class Axes(BaseAxes):
|
|
|
663
671
|
Initialize secondary y-axis.
|
|
664
672
|
"""
|
|
665
673
|
...
|
|
674
|
+
def set_facecolor(self, color: ColorLike) -> None:
|
|
675
|
+
"""
|
|
676
|
+
Set axis background color.
|
|
677
|
+
|
|
678
|
+
Parameters
|
|
679
|
+
----------
|
|
680
|
+
color: all matplotlib color formats (without X11/xkcd)
|
|
681
|
+
Background color of axis: RGB/RGBA (tuple), HEX (str), grayscale (float), single-char (str), name (str), default cycle ("CX", X int), none for invisible
|
|
682
|
+
"""
|
|
683
|
+
...
|
|
666
684
|
def _export_imshow(self, *args: Any, **kwargs: Any) -> str: ...
|
|
667
685
|
def _axis_options_string(self) -> str: ...
|
|
668
686
|
def _margins(self) -> tuple[float, float, float, float]: ...
|
|
@@ -74,7 +74,7 @@ class Axes3:
|
|
|
74
74
|
if _add_settgs is not None:
|
|
75
75
|
self._axis_options = _add_settgs | self._axis_options
|
|
76
76
|
|
|
77
|
-
def _plot(self, xs, ys, zs, zdir="z", settings=
|
|
77
|
+
def _plot(self, xs, ys, zs, zdir="z", settings={}, xerr=None, yerr=None, zerr=None, **style):
|
|
78
78
|
if isinstance(zs, (float,int)):
|
|
79
79
|
zs = [zs] * len(xs)
|
|
80
80
|
if zdir == "y":
|
|
@@ -110,12 +110,12 @@ class Axes3:
|
|
|
110
110
|
def plot_surface(self, X, Y, Z, **kwargs):
|
|
111
111
|
kws = {"alpha", "color", "c", "linestyle", "ls", "linewidth", "lw", "label"}
|
|
112
112
|
kwargs = self._check_kwargs("plot", kws, **kwargs)
|
|
113
|
-
return self._plot(X, Y, Z, settings=
|
|
113
|
+
return self._plot(X, Y, Z, settings={"surf": None, "mesh/rows": X.shape[0]} , **kwargs)
|
|
114
114
|
|
|
115
115
|
def plot_wireframe(self, X, Y, Z, **kwargs):
|
|
116
116
|
kws = {"alpha", "color", "c", "linestyle", "ls", "linewidth", "lw", "label"}
|
|
117
117
|
kwargs = self._check_kwargs("plot", kws, **kwargs)
|
|
118
|
-
return self._plot(X, Y, Z, settings=
|
|
118
|
+
return self._plot(X, Y, Z, settings={"mesh": None, "mesh/rows": X.shape[0]} , **kwargs)
|
|
119
119
|
|
|
120
120
|
def errorbar(self, x, y, z, zerr=None, yerr=None, xerr=None, **kwargs):
|
|
121
121
|
kws = {"fmt", "alpha", "color", "c", "linestyle", "ls", "linewidth", "lw", "marker", "markersize", "ms", "label"}
|
|
@@ -171,7 +171,7 @@ class Axes3:
|
|
|
171
171
|
self._plot(xs,ys,path_name=name2, alpha=0)
|
|
172
172
|
else:
|
|
173
173
|
name2 = inst"""
|
|
174
|
-
e = Graph3(self, f"fill between [of={name1} and {name2}]",settings=
|
|
174
|
+
e = Graph3(self, f"fill between [of={name1} and {name2}]",settings={}, xerr=None, yerr=None, zerr=None, **kwargs)
|
|
175
175
|
self._elements.append(e)
|
|
176
176
|
return e
|
|
177
177
|
|