tikzplot42 0.2.8__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.
tikzplot/colorbar.py ADDED
@@ -0,0 +1,261 @@
1
+ import numpy as _np
2
+ from .elements import Graph
3
+ from .axes3d import Axes3
4
+ from .config import TikzConfig
5
+
6
+ class _Colorbar:
7
+ def __init__(self, im=None, **kwargs):
8
+ self._axis = None
9
+ self._cmap = None
10
+ self._lower = 0
11
+ self._upper = 1
12
+ self._ticks = None
13
+ self._tick_labels = None
14
+ self._label = None
15
+ self._width = 0.3
16
+ self._horizontal = False
17
+ self._rel_len = 1
18
+ self._divs = 0 # 0 for contiuous
19
+
20
+ if im is not None:
21
+ self._axis, self._cmap, self._lower, self._upper = im
22
+
23
+ if "axis" in kwargs:
24
+ self._axis = kwargs["axis"]
25
+ if "cmap" in kwargs:
26
+ self._cmap = kwargs["cmap"]
27
+ if "lower" in kwargs:
28
+ self._lower = kwargs["lower"]
29
+ if "upper" in kwargs:
30
+ self._upper = kwargs["upper"]
31
+ if "ticks" in kwargs:
32
+ self._ticks = kwargs["ticks"]
33
+ if "tick_labels" in kwargs:
34
+ self._tick_labels = kwargs["tick_labels"]
35
+ if "label" in kwargs:
36
+ self._label = kwargs["label"]
37
+ if "width" in kwargs:
38
+ self._width = kwargs["width"]
39
+ if "horizontal" in kwargs and kwargs["horizontal"]:
40
+ self._horizontal = True
41
+ if "rel_len" in kwargs:
42
+ self._rel_len = kwargs["rel_len"]
43
+ if "divisions" in kwargs:
44
+ self._divs = kwargs["divisions"]
45
+ if self._axis:
46
+ self._axis._show_colorbar(str(self))
47
+
48
+ _discrete = {'Pastel1':9, 'Pastel2':8, 'Paired':12, 'Accent':8, 'Dark2':8, 'Set1': 9, 'Set2':8, 'Set3':12, 'tab10':10, 'tab20':20, 'tab20b':20, 'tab20c':20}
49
+ _dictionary = {
50
+ 'viridis': [(0.267, 0.0049, 0.3294), (0.2297, 0.3224, 0.5457), (0.1276, 0.5669, 0.5506), (0.3692, 0.7889, 0.3829), (0.9932, 0.9062, 0.1439)],
51
+ 'plasma': [(0.0504, 0.0298, 0.528), (0.4949, 0.012, 0.6579), (0.7982, 0.2802, 0.4695), (0.9734, 0.5858, 0.2515), (0.94, 0.9752, 0.1313)],
52
+ 'inferno': [(0.0015, 0.0005, 0.0139), (0.3415, 0.0623, 0.4294), (0.7357, 0.2159, 0.3302), (0.9784, 0.5579, 0.0349), (0.9884, 0.9984, 0.6449)],
53
+ 'magma': [(0.0015, 0.0005, 0.0139), (0.3167, 0.0717, 0.4854), (0.7164, 0.215, 0.4753), (0.9867, 0.5356, 0.3822), (0.9871, 0.9914, 0.7495)],
54
+ 'cividis': [(0.0, 0.1351, 0.3048), (0.2637, 0.3078, 0.4228), (0.4887, 0.4853, 0.471), (0.7365, 0.6806, 0.424), (0.9957, 0.9093, 0.2178)],
55
+
56
+ 'Greys': [(1.0, 1.0, 1.0), (0.0, 0.0, 0.0)],
57
+ 'Purples': [(0.9882, 0.9843, 0.9922), (0.2471, 0.0, 0.4902)],
58
+ 'Blues': [(0.9686, 0.9843, 1.0), (0.0314, 0.1882, 0.4196)],
59
+ 'Greens': [(0.9686, 0.9882, 0.9608), (0.0, 0.2667, 0.1059)],
60
+ 'Oranges': [(1.0, 0.9608, 0.9216), (0.498, 0.1529, 0.0157)],
61
+ 'Reds': [(1.0, 0.9608, 0.9412), (0.4039, 0.0, 0.051)],
62
+ 'YlOrBr': [(1.0, 1.0, 0.898), (0.4, 0.1451, 0.0235)],
63
+ 'YlOrRd': [(1.0, 1.0, 0.8), (0.502, 0.0, 0.149)],
64
+ 'OrRd': [(1.0, 0.9686, 0.9255), (0.498, 0.0, 0.0)],
65
+ 'PuRd': [(0.9686, 0.9569, 0.9765), (0.4039, 0.0, 0.1216)],
66
+ 'RdPu': [(1.0, 0.9686, 0.9529), (0.2863, 0.0, 0.4157)],
67
+ 'BuPu': [(0.9686, 0.9882, 0.9922), (0.302, 0.0, 0.2941)],
68
+ 'GnBu': [(0.9686, 0.9882, 0.9412), (0.0314, 0.251, 0.5059)],
69
+ 'PuBu': [(1.0, 0.9686, 0.9843), (0.0078, 0.2196, 0.3451)],
70
+ 'YlGnBu': [(1.0, 1.0, 0.851), (0.0314, 0.1137, 0.3451)],
71
+ 'PuBuGn': [(1.0, 0.9686, 0.9843), (0.0039, 0.2745, 0.2118)],
72
+ 'BuGn': [(0.9686, 0.9882, 0.9922), (0.0, 0.2667, 0.1059)],
73
+ 'YlGn': [(1.0, 1.0, 0.898), (0.0, 0.2706, 0.1608)],
74
+
75
+ 'binary': [(1.0, 1.0, 1.0), (0.498, 0.498, 0.498), (0.0, 0.0, 0.0)],
76
+ 'gist_yarg': [(1.0, 1.0, 1.0), (0.498, 0.498, 0.498), (0.0, 0.0, 0.0)],
77
+ 'gist_gray': [(0.0, 0.0, 0.0), (0.502, 0.502, 0.502), (1.0, 1.0, 1.0)],
78
+ 'gray': [(0.0, 0.0, 0.0), (0.502, 0.502, 0.502), (1.0, 1.0, 1.0)],
79
+ 'bone': [(0.0, 0.0, 0.0), (0.4392, 0.4841, 0.5642), (1.0, 1.0, 1.0)],
80
+ 'pink': [(0.1178, 0.0, 0.0), (0.8173, 0.674, 0.5785), (1.0, 1.0, 1.0)],
81
+ 'spring': [(1.0, 0.0, 1.0), (1.0, 0.502, 0.498), (1.0, 1.0, 0.0)],
82
+ 'summer': [(0.0, 0.5, 0.4), (0.502, 0.751, 0.4), (1.0, 1.0, 0.4)],
83
+ 'autumn': [(1.0, 0.0, 0.0), (1.0, 0.502, 0.0), (1.0, 1.0, 0.0)],
84
+ 'winter': [(0.0, 0.0, 1.0), (0.0, 0.502, 0.749), (0.0, 1.0, 0.5)],
85
+ 'cool': [(0.0, 1.0, 1.0), (0.502, 0.498, 1.0), (1.0, 0.0, 1.0)],
86
+ 'Wistia': [(0.8941, 1.0, 0.4784), (1.0, 0.7403, 0.0), (0.9882, 0.498, 0.0)],
87
+ 'hot': [(0.0416, 0.0, 0.0), (1.0, 0.3593, 0.0), (1.0, 1.0, 1.0)],
88
+ 'afmhot': [(0.0, 0.0, 0.0), (1.0, 0.5039, 0.0039), (1.0, 1.0, 1.0)],
89
+ 'gist_heat': [(0.0, 0.0, 0.0), (0.7529, 0.0039, 0.0), (1.0, 1.0, 1.0)],
90
+ 'copper': [(0.0, 0.0, 0.0), (0.6201, 0.3921, 0.2497), (1.0, 0.7812, 0.4975)],
91
+
92
+ 'PiYG': [(0.5569, 0.0039, 0.3216), (0.9673, 0.9685, 0.9656), (0.1529, 0.3922, 0.098)],
93
+ 'PRGn': [(0.251, 0.0, 0.2941), (0.9663, 0.9681, 0.9659), (0.0, 0.2667, 0.1059)],
94
+ 'BrBG': [(0.3294, 0.1882, 0.0196), (0.9572, 0.9599, 0.9596), (0.0, 0.2353, 0.1882)],
95
+ 'PuOr': [(0.498, 0.2314, 0.0314), (0.9662, 0.9664, 0.9677), (0.1765, 0.0, 0.2941)],
96
+ 'RdGy': [(0.4039, 0.0, 0.1216), (0.9976, 0.9976, 0.9976), (0.102, 0.102, 0.102)],
97
+ 'RdBu': [(0.4039, 0.0, 0.1216), (0.9657, 0.9672, 0.9681), (0.0196, 0.1882, 0.3804)],
98
+ 'RdYlBu': [(0.6471, 0.0, 0.149), (0.9976, 0.9991, 0.7534), (0.1922, 0.2118, 0.5843)],
99
+ 'RdYlGn': [(0.6471, 0.0, 0.149), (0.9971, 0.9988, 0.745), (0.0, 0.4078, 0.2157)],
100
+ 'Spectral': [(0.6196, 0.0039, 0.2588), (0.9981, 0.9992, 0.746), (0.3686, 0.3098, 0.6353)],
101
+ 'coolwarm': [(0.2298, 0.2987, 0.7537), (0.8674, 0.8644, 0.8626), (0.7057, 0.0156, 0.1502)],
102
+ 'bwr': [(0.0, 0.0, 1.0), (1.0, 0.9961, 0.9961), (1.0, 0.0, 0.0)],
103
+ 'seismic': [(0.0, 0.0, 0.3), (1.0, 0.9922, 0.9922), (0.5, 0.0, 0.0)],
104
+
105
+ 'twilight': [(0.8858, 0.85, 0.888), (0.5383, 0.678, 0.7711), (0.3732, 0.3814, 0.706), (0.2867, 0.0824, 0.3933), (0.3154, 0.0794, 0.2681), (0.6457, 0.2616, 0.3125), (0.7905, 0.5983, 0.4862), (0.8857, 0.85, 0.8857)],
106
+ 'twilight_shifted': [(0.1874, 0.0771, 0.2162), (0.36, 0.2069, 0.6029), (0.4114, 0.5368, 0.7467), (0.7387, 0.796, 0.8214), (0.8399, 0.7604, 0.7137), (0.7388, 0.4205, 0.3491), (0.4981, 0.1357, 0.3141), (0.1849, 0.0794, 0.2131)],
107
+ 'hsv': [(1.0, 0.0, 0.0), (1.0, 0.8338, 0.0), (0.3092, 1.0, 0.0), (0.0, 1.0, 0.5246), (0.0, 0.6184, 1.0), (0.2154, 0.0, 1.0), (1.0, 0.0, 0.9276), (1.0, 0.0, 0.0938)],
108
+
109
+ 'flag': [(1.0, 0.0, 0.0), (1.0, 0.9998, 1.0), (0.0, 0.037, 1.0), (0.0, 0.0, 0.0), (0.9897, 0.0, 0.0), (1.0, 0.9957, 0.9791), (0.0316, 0.1107, 1.0), (0.0, 0.0, 0.0425), (0.9464, 0.0, 0.0), (1.0, 0.9862, 0.9352), (0.0761, 0.1837, 1.0), (0.0, 0.0, 0.0877), (0.9007, 0.0, 0.0), (1.0, 0.9713, 0.8889), (0.123, 0.2558, 1.0), (0.0, 0.0, 0.135), (1.0, 0.0923, 0.0209), (0.9897, 0.9973, 1.0), (0.0, 0.0, 1.0), (0.0, 0.0, 0.0), (1.0, 0.0185, 0.0), (1.0, 1.0, 1.0), (0.0, 0.0185, 1.0), (0.0, 0.0, 0.0), (1.0, 0.0, 0.0), (1.0, 0.9973, 0.9897), (0.0209, 0.0923, 1.0), (0.0, 0.0, 0.0316), (0.9575, 0.0, 0.0), (1.0, 0.9891, 0.9464), (0.0648, 0.1656, 1.0), (0.0, 0.0, 0.0761), (1.0, 0.1837, 0.0761), (0.9352, 0.9862, 1.0), (0.0, 0.0, 0.9464), (0.0425, 0.0, 0.0), (1.0, 0.1107, 0.0316), (0.9791, 0.9957, 1.0), (0.0, 0.0, 0.9897), (0.0, 0.0, 0.0), (1.0, 0.037, 0.0), (1.0, 0.9998, 1.0), (0.0, 0.0, 1.0), (0.0, 0.0, 0.0), (1.0, 0.0, 0.0), (1.0, 0.9985, 1.0), (0.0103, 0.0739, 1.0), (0.0, 0.0, 0.0209), (1.0, 0.2737, 0.135), (0.877, 0.9667, 1.0), (0.0, 0.0, 0.8889), (0.0993, 0.0, 0.0), (1.0, 0.2019, 0.0877), (0.9239, 0.983, 1.0), (0.0, 0.0, 0.9352), (0.0536, 0.0, 0.0), (1.0, 0.129, 0.0425), (0.9684, 0.9939, 1.0), (0.0, 0.0, 0.9791), (0.0103, 0.0, 0.0), (1.0, 0.0554, 0.0), (1.0, 0.9993, 1.0), (0.0, 0.0, 1.0), (0.0, 0.0, 0.0)],
110
+ 'prism': [(1.0, 0.0, 0.0), (1.0, 0.5116, 0.0), (0.889, 1.0, 0.0), (0.1678, 0.887, 0.0), (0.0, 0.1863, 0.9124), (0.4142, 0.0, 0.9965), (1.0, 0.0, 0.1136), (1.0, 0.4354, 0.0), (0.9619, 1.0, 0.0), (0.228, 0.9359, 0.0), (0.0, 0.2631, 0.8441), (0.3427, 0.0, 1.0), (1.0, 0.0, 0.2261), (1.0, 0.3582, 0.0), (1.0, 0.987, 0.0), (0.293, 0.9784, 0.0), (0.0, 0.1493, 0.9423), (0.4501, 0.0, 0.9717), (1.0, 0.0, 0.0582), (1.0, 0.4728, 0.0), (0.9267, 1.0, 0.0), (0.198, 0.9129, 0.0), (0.0, 0.2255, 0.8786), (0.3772, 0.0, 1.0), (1.0, 0.0, 0.1714), (1.0, 0.396, 0.0), (0.9981, 1.0, 0.0), (0.2607, 0.9585, 0.0), (0.0, 0.3027, 0.8056), (0.3075, 0.0, 1.0), (1.0, 0.0, 0.2827), (1.0, 0.3185, 0.0), (0.8908, 1.0, 0.0), (0.1692, 0.8883, 0.0), (0.0, 0.1881, 0.9109), (0.4125, 0.0, 0.9976), (1.0, 0.0, 0.1163), (1.0, 0.4336, 0.0), (0.9636, 1.0, 0.0), (0.2295, 0.937, 0.0), (0.0, 0.2649, 0.8424), (0.3411, 0.0, 1.0), (1.0, 0.0, 0.2287), (1.0, 0.3563, 0.0), (1.0, 0.9861, 0.0), (0.2946, 0.9793, 0.0), (0.0, 0.3425, 0.7648), (0.2732, 0.0, 1.0), (1.0, 0.0, 0.061), (1.0, 0.471, 0.0), (0.9284, 1.0, 0.0), (0.1994, 0.914, 0.0), (0.0, 0.2273, 0.877), (0.3755, 0.0, 1.0), (1.0, 0.0, 0.1741), (1.0, 0.3941, 0.0), (0.9997, 1.0, 0.0), (0.2623, 0.9595, 0.0), (0.0, 0.3046, 0.8037), (0.3059, 0.0, 1.0), (1.0, 0.0, 0.2854), (1.0, 0.3166, 0.0), (1.0, 0.966, 0.0), (0.3295, 0.9983, 0.0)],
111
+ 'gist_earth': [(0.0, 0.0, 0.0), (0.0732, 0.1893, 0.4691), (0.1464, 0.4028, 0.489), (0.2122, 0.5313, 0.4381), (0.264, 0.5945, 0.3036), (0.4849, 0.6552, 0.3242), (0.6659, 0.7034, 0.3589), (0.752, 0.6459, 0.3949), (0.8694, 0.7323, 0.6555), (0.9922, 0.9843, 0.9843)],
112
+ 'terrain': [(0.2, 0.2, 0.6), (0.0536, 0.4928, 0.8928), (0.0, 0.7392, 0.5824), (0.3333, 0.8667, 0.4667), (0.7725, 0.9545, 0.5545), (0.8863, 0.8544, 0.5386), (0.6667, 0.5733, 0.42), (0.5608, 0.4378, 0.4115), (0.7804, 0.7189, 0.7057), (1.0, 1.0, 1.0)],
113
+ 'gist_stern': [(0.0, 0.0, 0.0), (0.7255, 0.1098, 0.2196), (0.1784, 0.2196, 0.4392), (0.3333, 0.3333, 0.6667), (0.4431, 0.4431, 0.8863), (0.5569, 0.5569, 0.758), (0.6667, 0.6667, 0.2908), (0.7804, 0.7804, 0.1713), (0.8902, 0.8902, 0.5856), (1.0, 1.0, 1.0)],
114
+ 'gnuplot': [(0.0, 0.0, 0.0), (0.3314, 0.0013, 0.6365), (0.4686, 0.0106, 0.9818), (0.5774, 0.037, 0.866), (0.6657, 0.087, 0.3497), (0.7462, 0.1727, 0.0), (0.8165, 0.2963, 0.0), (0.8834, 0.4753, 0.0), (0.9435, 0.7054, 0.0), (1.0, 1.0, 0.0)],
115
+ 'gnuplot2': [(0.0, 0.0, 0.0), (0.0, 0.0, 0.4392), (0.0, 0.0, 0.8784), (0.2604, 0.0, 1.0), (0.6036, 0.0463, 0.9537), (0.9589, 0.2737, 0.7263), (1.0, 0.4933, 0.5067), (1.0, 0.7208, 0.2792), (1.0, 0.9404, 0.0596), (1.0, 1.0, 1.0)],
116
+ 'CMRmap': [(0.0, 0.0, 0.0), (0.1318, 0.1318, 0.4392), (0.2635, 0.15, 0.6892), (0.5, 0.1833, 0.5833), (0.818, 0.2273, 0.3092), (0.9545, 0.3637, 0.0818), (0.9, 0.5833, 0.0333), (0.9, 0.7865, 0.1973), (0.9122, 0.9122, 0.5608), (1.0, 1.0, 1.0)],
117
+ 'cubehelix': [(0.0, 0.0, 0.0), (0.1036, 0.095, 0.2062), (0.0826, 0.2728, 0.3077), (0.17, 0.4368, 0.2237), (0.4588, 0.4806, 0.1997), (0.7577, 0.477, 0.4378), (0.83, 0.5632, 0.7763), (0.7639, 0.7573, 0.9494), (0.8107, 0.9218, 0.9374), (1.0, 1.0, 1.0)],
118
+ 'brg': [(0.0, 0.0, 1.0), (0.2196, 0.0, 0.7804), (0.4392, 0.0, 0.5608), (0.6667, 0.0, 0.3333), (0.8863, 0.0, 0.1137), (0.8863, 0.1137, 0.0), (0.6667, 0.3333, 0.0), (0.4392, 0.5608, 0.0), (0.2196, 0.7804, 0.0), (0.0, 1.0, 0.0)],
119
+ 'gist_rainbow': [(1.0, 0.0, 0.16), (1.0, 0.4314, 0.0), (0.9751, 1.0, 0.0), (0.3604, 1.0, 0.0), (0.0, 1.0, 0.2319), (0.0, 1.0, 0.8433), (0.0, 0.5616, 1.0), (0.0565, 0.0, 1.0), (0.6532, 0.0, 1.0), (1.0, 0.0, 0.75)],
120
+ 'rainbow': [(0.5, 0.0, 1.0), (0.2804, 0.3382, 0.9852), (0.0608, 0.6365, 0.9411), (0.1667, 0.866, 0.866), (0.3863, 0.9841, 0.7674), (0.6137, 0.9841, 0.6412), (0.8333, 0.866, 0.5), (1.0, 0.6365, 0.3382), (1.0, 0.3382, 0.1716), (1.0, 0.0, 0.0)],
121
+ 'jet': [(0.0, 0.0, 0.5), (0.0, 0.0, 0.9991), (0.0, 0.3784, 1.0), (0.0, 0.8333, 1.0), (0.3004, 1.0, 0.6673), (0.6673, 1.0, 0.3004), (1.0, 0.9012, 0.0), (1.0, 0.48, 0.0), (0.9991, 0.0733, 0.0), (0.5, 0.0, 0.0)],
122
+ 'turbo': [(0.19, 0.0718, 0.2322), (0.2733, 0.3801, 0.8404), (0.2138, 0.6589, 0.9796), (0.1034, 0.896, 0.715), (0.4432, 0.9955, 0.3734), (0.7856, 0.9358, 0.2034), (0.98, 0.73, 0.2216), (0.9619, 0.4109, 0.0931), (0.7912, 0.1637, 0.0139), (0.4796, 0.0158, 0.0106)],
123
+ 'nipy_spectral': [(0.0, 0.0, 0.0), (0.4287, 0.0, 0.6131), (0.0, 0.183, 0.8667), (0.0, 0.6445, 0.7334), (0.0, 0.6092, 0.0732), (0.0, 0.885, 0.0), (0.8, 0.9778, 0.0), (1.0, 0.6784, 0.0), (0.8928, 0.0, 0.0), (0.8, 0.8, 0.8)],
124
+ 'gist_ncar': [(0.0, 0.0, 0.502), (0.0, 0.0551, 1.0), (0.0, 0.9982, 0.897), (0.1499, 0.9408, 0.0), (0.5897, 1.0, 0.1093), (1.0, 0.913, 0.0), (1.0, 0.4404, 0.022), (1.0, 0.0, 0.7644), (0.8772, 0.4538, 0.9435), (0.9961, 0.9725, 0.9961)],
125
+
126
+ 'Pastel1': [(0.9843, 0.7059, 0.6824), (0.702, 0.8039, 0.8902), (0.8, 0.9216, 0.7725), (0.8706, 0.7961, 0.8941), (0.9961, 0.851, 0.651), (1.0, 1.0, 0.8), (0.898, 0.8471, 0.7412), (0.9922, 0.8549, 0.9255), (0.949, 0.949, 0.949)],
127
+ 'Pastel2': [(0.702, 0.8863, 0.8039), (0.9922, 0.8039, 0.6745), (0.7961, 0.8353, 0.9098), (0.9569, 0.7922, 0.8941), (0.902, 0.9608, 0.7882), (1.0, 0.949, 0.6824), (0.9451, 0.8863, 0.8), (0.8, 0.8, 0.8)],
128
+ 'Paired': [(0.651, 0.8078, 0.8902), (0.1216, 0.4706, 0.7059), (0.698, 0.8745, 0.5412), (0.2, 0.6275, 0.1725), (0.9843, 0.6039, 0.6), (0.8902, 0.102, 0.1098), (0.9922, 0.749, 0.4353), (1.0, 0.498, 0.0), (0.7922, 0.698, 0.8392), (0.4157, 0.2392, 0.6039), (1.0, 1.0, 0.6), (0.6941, 0.349, 0.1569)],
129
+ 'Accent': [(0.498, 0.7882, 0.498), (0.7451, 0.6824, 0.8314), (0.9922, 0.7529, 0.5255), (1.0, 1.0, 0.6), (0.2196, 0.4235, 0.6902), (0.9412, 0.0078, 0.498), (0.749, 0.3569, 0.0902), (0.4, 0.4, 0.4)],
130
+ 'Dark2': [(0.1059, 0.6196, 0.4667), (0.851, 0.3725, 0.0078), (0.4588, 0.4392, 0.702), (0.9059, 0.1608, 0.5412), (0.4, 0.651, 0.1176), (0.902, 0.6706, 0.0078), (0.651, 0.4627, 0.1137), (0.4, 0.4, 0.4)],
131
+ 'Set1': [(0.8941, 0.102, 0.1098), (0.2157, 0.4941, 0.7216), (0.302, 0.6863, 0.2902), (0.5961, 0.3059, 0.6392), (1.0, 0.498, 0.0), (1.0, 1.0, 0.2), (0.651, 0.3373, 0.1569), (0.9686, 0.5059, 0.749), (0.6, 0.6, 0.6)],
132
+ 'Set2': [(0.4, 0.7608, 0.6471), (0.9882, 0.5529, 0.3843), (0.5529, 0.6275, 0.7961), (0.9059, 0.5412, 0.7647), (0.651, 0.8471, 0.3294), (1.0, 0.851, 0.1843), (0.898, 0.7686, 0.5804), (0.702, 0.702, 0.702)],
133
+ 'Set3': [(0.5529, 0.8275, 0.7804), (1.0, 1.0, 0.702), (0.7451, 0.7294, 0.8549), (0.9843, 0.502, 0.4471), (0.502, 0.6941, 0.8275), (0.9922, 0.7059, 0.3843), (0.702, 0.8706, 0.4118), (0.9882, 0.8039, 0.898), (0.851, 0.851, 0.851), (0.7373, 0.502, 0.7412), (0.8, 0.9216, 0.7725), (1.0, 0.9294, 0.4353)],
134
+ 'tab10': [(0.1216, 0.4667, 0.7059), (1.0, 0.498, 0.0549), (0.1725, 0.6275, 0.1725), (0.8392, 0.1529, 0.1569), (0.5804, 0.4039, 0.7412), (0.549, 0.3373, 0.2941), (0.8902, 0.4667, 0.7608), (0.498, 0.498, 0.498), (0.7373, 0.7412, 0.1333), (0.0902, 0.7451, 0.8118)],
135
+ 'tab20': [(0.1216, 0.4667, 0.7059), (0.6824, 0.7804, 0.9098), (1.0, 0.498, 0.0549), (1.0, 0.7333, 0.4706), (0.1725, 0.6275, 0.1725), (0.5961, 0.8745, 0.5412), (0.8392, 0.1529, 0.1569), (1.0, 0.5961, 0.5882), (0.5804, 0.4039, 0.7412), (0.7725, 0.6902, 0.8353), (0.549, 0.3373, 0.2941), (0.7686, 0.6118, 0.5804), (0.8902, 0.4667, 0.7608), (0.9686, 0.7137, 0.8235), (0.498, 0.498, 0.498), (0.7804, 0.7804, 0.7804), (0.7373, 0.7412, 0.1333), (0.8588, 0.8588, 0.5529), (0.0902, 0.7451, 0.8118), (0.6196, 0.8549, 0.898)],
136
+ 'tab20b': [(0.2235, 0.2314, 0.4745), (0.3216, 0.3294, 0.6392), (0.4196, 0.4314, 0.8118), (0.6118, 0.6196, 0.8706), (0.3882, 0.4745, 0.2235), (0.549, 0.6353, 0.3216), (0.7098, 0.8118, 0.4196), (0.8078, 0.8588, 0.6118), (0.549, 0.4275, 0.1922), (0.7412, 0.6196, 0.2235), (0.9059, 0.7294, 0.3216), (0.9059, 0.7961, 0.5804), (0.5176, 0.2353, 0.2235), (0.6784, 0.2863, 0.2902), (0.8392, 0.3804, 0.4196), (0.9059, 0.5882, 0.6118), (0.4824, 0.2549, 0.451), (0.6471, 0.3176, 0.5804), (0.8078, 0.4275, 0.7412), (0.8706, 0.6196, 0.8392)],
137
+ 'tab20c': [(0.1922, 0.5098, 0.7412), (0.4196, 0.6824, 0.8392), (0.6196, 0.7922, 0.8824), (0.7765, 0.8588, 0.9373), (0.902, 0.3333, 0.051), (0.9922, 0.5529, 0.2353), (0.9922, 0.6824, 0.4196), (0.9922, 0.8157, 0.6353), (0.1922, 0.6392, 0.3294), (0.4549, 0.7686, 0.4627), (0.6314, 0.851, 0.6078), (0.7804, 0.9137, 0.7529), (0.4588, 0.4196, 0.6941), (0.6196, 0.6039, 0.7843), (0.7373, 0.7412, 0.8627), (0.8549, 0.8549, 0.9216), (0.3882, 0.3882, 0.3882), (0.5882, 0.5882, 0.5882), (0.7412, 0.7412, 0.7412), (0.851, 0.851, 0.851)]
138
+
139
+
140
+ }
141
+
142
+ def _get_samples(self, colors, n):
143
+ if n == len(colors):
144
+ return colors
145
+
146
+ colors_arr = _np.array(colors)
147
+ x_orig = _np.linspace(0, 1, len(colors))
148
+ x_new = _np.linspace(0, 1, n)
149
+
150
+ r = _np.interp(x_new, x_orig, colors_arr[:, 0])
151
+ g = _np.interp(x_new, x_orig, colors_arr[:, 1])
152
+ b = _np.interp(x_new, x_orig, colors_arr[:, 2])
153
+
154
+ return list(zip(r, g, b))
155
+
156
+ def _generate_tex_colormap(self, cmap_name):
157
+ if isinstance(cmap_name, str):
158
+ rev = False
159
+ if cmap_name.endswith("_r"):
160
+ rev = True
161
+ cmap_name = cmap_name.removesuffix("_r")
162
+ if cmap_name not in self._dictionary:
163
+ raise Exception(f"% Error: {cmap_name} not found in _dictionary")
164
+ colors = self._dictionary[cmap_name]
165
+ if rev: colors=list(reversed(colors))
166
+ elif isinstance(cmap_name, list):
167
+ colors = cmap_name
168
+ else:
169
+ raise Exception(f"% Error: cmap_name must be a string or a list of colors")
170
+ output = [r"{urgb}{"]
171
+ if isinstance(cmap_name, str) and cmap_name in self._discrete:
172
+ n = self._discrete[cmap_name]
173
+ self._divs = n
174
+ elif self._divs > 0:
175
+ colors = self._get_samples(colors, self._divs)
176
+ if self._divs == 0:
177
+ for r, g, b in colors:
178
+ output.append(f" rgb=({r:.4f}, {g:.4f}, {b:.4f})")
179
+ else:
180
+ lims = _np.linspace(0,1, self._divs+1, endpoint=True)
181
+ lims[-1] += 0.001
182
+ for i in range(self._divs):
183
+ r,g,b = colors[i]
184
+ output.append(f" rgb({lims[i]})=({r:.4f}, {g:.4f}, {b:.4f}) rgb({lims[i+1]-0.001})=({r:.4f}, {g:.4f}, {b:.4f})")
185
+ output.append("}")
186
+ return "\n".join(output)
187
+
188
+ def __str__(self):
189
+ tridim = isinstance(self._axis, Axes3)
190
+ lines = []
191
+ lines.append(f"colormap={self._generate_tex_colormap(self._cmap)},")
192
+ lines.append(f"colorbar{' horizontal' if self._horizontal else ''},")
193
+ lines.append(r"colorbar style={")
194
+ if TikzConfig.USE_DECIMAL_COMMA:
195
+ lines.append("/pgf/number format/use comma,")
196
+ if self._horizontal:
197
+ lines.append(f"height={self._width}cm,")
198
+ lines.append(f"anchor=north,")
199
+ lines.append(f"at={{(p{self._axis._get_index()}.south)}},")
200
+ lines.append(f"yshift=-{TikzConfig.CBAR_Y_OFFSET * (not tridim) + TikzConfig.CBAR3_Z_OFFSET * tridim}cm,")
201
+ else:
202
+ lines.append(f"width={self._width}cm,")
203
+ lines.append(f"anchor=west,")
204
+ lines.append(f"at={{(p{self._axis._get_index()}.east)}},")
205
+ lines.append(f"xshift={TikzConfig.CBAR_X_OFFSET * (not tridim) + + TikzConfig.CBAR3_H_OFFSET * tridim}cm,")
206
+ if self._rel_len:
207
+ lines.append(f"{'width' if self._horizontal else 'height'}={self._rel_len}*\\pgfkeysvalueof{{/pgfplots/parent axis {'width' if self._horizontal else 'height'}}},")
208
+ if self._label:
209
+ lines.append(f"title={{{self._label}}},")
210
+ offset = 4 - 2 * (self._ticks == [] or self._tick_labels == [])
211
+ if self._horizontal:
212
+ lines.append(f"title style={{at={{(0.5, -{offset})}}, anchor=base}},")
213
+ else:
214
+ lines.append(f"title style={{at={{({offset},0.5)}}, anchor=base, yshift=-7pt, rotate=-90}},")
215
+ if self._ticks is not None:
216
+ lines.append(f"{'x' if self._horizontal else 'y'}tick={{{','.join(str(a) for a in self._ticks)}}},")
217
+ if self._tick_labels and len(self._tick_labels) == len(self._ticks):
218
+ lines.append(f"{'x' if self._horizontal else 'y'}ticklabels={{{','.join(str(a) for a in self._tick_labels)}}},")
219
+ if self._tick_labels == []:
220
+ lines.append(f"{'x' if self._horizontal else 'y'}ticklabels=\\empty,")
221
+ if self._divs > 0:
222
+ lines.append(f"{'x' if self._horizontal else 'y'}tick =\\empty,")
223
+ lines.append(r"},")
224
+ lines.append(f"point meta min={{{self._lower}}},")
225
+ lines.append(f"point meta max={{{self._upper}}}")
226
+
227
+ return "\n".join(lines)
228
+
229
+ def color(self, value):
230
+ norm_val = (value - self._lower) / (self._upper - self._lower)
231
+ norm_val = _np.clip(norm_val, 0, 1)
232
+ is_reversed = False
233
+ if isinstance(self._cmap, str):
234
+ cmap_name = self._cmap
235
+ if cmap_name.endswith("_r"):
236
+ is_reversed = True
237
+ cmap_name = cmap_name.removesuffix("_r")
238
+ colors = self._dictionary[cmap_name]
239
+ elif isinstance(self._cmap, list):
240
+ colors = self._cmap
241
+ else:
242
+ raise Exception(f"% Error: cmap_name must be a string or a list of colors")
243
+ if is_reversed:
244
+ colors = list(reversed(colors))
245
+ n_colors = len(colors)
246
+ if n_colors == 1:
247
+ return colors[0]
248
+ elif self._divs == 0:
249
+ float_idx = norm_val * (n_colors - 1)
250
+ idx_low = int(_np.floor(float_idx))
251
+ idx_high = int(_np.ceil(float_idx))
252
+ weight = float_idx - idx_low
253
+ c_low = _np.array(colors[idx_low])
254
+ c_high = _np.array(colors[idx_high])
255
+ rgb = (1 - weight) * c_low + weight * c_high
256
+ else:
257
+ idx = int(norm_val * self._divs)
258
+ rgb = self._get_samples(colors, self._divs)[idx]
259
+ return tuple(rgb)
260
+
261
+ Colorbar = _Colorbar
tikzplot/colorbar.pyi ADDED
@@ -0,0 +1,128 @@
1
+ from typing import Any, Iterable, Optional, Sequence, Tuple
2
+ import numpy.typing as npt
3
+ from .axes import Axes
4
+ from .axes3d import Axes3
5
+
6
+ ArrayLike = npt.ArrayLike
7
+
8
+
9
+ class Colorbar:
10
+ """
11
+ PGFPlots-compatible colorbar generator.
12
+
13
+ This class converts a colormap definition into TikZ/PGFPlots
14
+ colorbar configuration and provides utilities for color mapping.
15
+
16
+ Typically constructed via:
17
+
18
+ Colorbar(im, **kwargs)
19
+
20
+ where `im` is a tuple describing an image:
21
+ (axis, cmap, lower, upper)
22
+ """
23
+
24
+ def __init__(
25
+ self,
26
+ im: Optional[Tuple[Axes, str, float, float]] = ...,
27
+ *,
28
+ axis: Optional[Axes | Axes3] = ...,
29
+ cmap: Optional[str] = ...,
30
+ lower: Optional[float] = ...,
31
+ upper: Optional[float] = ...,
32
+ ticks: Optional[Sequence[ float]] = ...,
33
+ tick_labels: Optional[Sequence[str | float]] = ...,
34
+ label: Optional[str] = ...,
35
+ width: float = ...,
36
+ horizontal: bool = ...,
37
+ rel_len: float = ...,
38
+ divisions: int = ...
39
+ ) -> None:
40
+ """
41
+ Parameters
42
+ ----------
43
+ im : imshow() return: tuple(axis, cmap, lower, upper), optional
44
+ Tuple describing the associated image:
45
+ - axis : parent axis object
46
+ - cmap : name of the colormap
47
+ - lower : minimum value of the color scale
48
+ - upper : maximum value of the color scale
49
+
50
+ axis: reference to axis, optional
51
+ Axis to which the color bar is plotted.
52
+
53
+ cmap : str, optional
54
+ Name of the colormap to use.
55
+ Supports reversed colormaps via suffix "_r".
56
+
57
+ lower : float, optional
58
+ Minimum value of the color scale.
59
+
60
+ upper : float, optional
61
+ Maximum value of the color scale.
62
+
63
+ ticks : sequence of str, optional
64
+ Positions of ticks on the colorbar.
65
+ Must be provided as strings for direct PGFPlots usage.
66
+
67
+ tick_labels : sequence of str, optional
68
+ Labels corresponding to `ticks`.
69
+ Must have the same length as `ticks`.
70
+
71
+ Special cases:
72
+ - empty list `[]` → disables tick labels
73
+
74
+ label : str, optional
75
+ Title of the colorbar.
76
+
77
+ width : float, default = 0.3
78
+ Thickness of the colorbar (in cm).
79
+
80
+ - vertical colorbar → width
81
+ - horizontal colorbar → height
82
+
83
+ horizontal : bool, default = False
84
+ If True, renders a horizontal colorbar.
85
+ Otherwise, a vertical colorbar is used.
86
+
87
+ rel_len : float, default = 1
88
+ Relative length of the colorbar with respect to the parent axis.
89
+
90
+ Internally mapped to:
91
+ width or height = rel_len * parent axis dimension
92
+ divisions: int, optional
93
+ May be used with continuous colormaps do discretize number of colors, 0 for continuous.
94
+ """
95
+ ...
96
+
97
+ def _generate_tex_colormap(self, cmap_name: str) -> str:
98
+ """
99
+ Generate a PGFPlots-compatible colormap definition.
100
+
101
+ Parameters
102
+ ----------
103
+ cmap_name : str
104
+ Name of the colormap.
105
+ Supports reversed maps using suffix "_r".
106
+
107
+ Returns
108
+ -------
109
+ str
110
+ TikZ colormap definition string.
111
+ """
112
+ ...
113
+
114
+ def color(self, value: float) -> Tuple[float, float, float]:
115
+ """
116
+ Map a scalar value to an RGB color using the current colormap.
117
+
118
+ Parameters
119
+ ----------
120
+ value : float
121
+ Value within the range [lower, upper].
122
+
123
+ Returns
124
+ -------
125
+ tuple of float
126
+ RGB color as (r, g, b), each in [0, 1].
127
+ """
128
+ ...
tikzplot/colors.py ADDED
@@ -0,0 +1,58 @@
1
+ from .config import TikzConfig
2
+
3
+ _COLOR_MAP = {'b':'blue', 'g':'teal', 'r':'red', 'c':'cyan', 'm':'magenta', 'y':'yellow', 'k':'black', 'w':'white', "orange":"orange", "green": "green", "cyan":"cyan", "peru": "brown", "lime": "lime", "gray": "gray", "magenta": "magetna", "purple": "violet"}
4
+ _DEFAULT_CYCLE = ['#1f77b4','#ff7f0e','#2ca02c','#d62728','#9467bd','#8c564b','#e377c2','#7f7f7f','#bcbd22','#17becf']
5
+
6
+ def _tex_color(input):
7
+ def color_string(r,g,b):
8
+ if TikzConfig.USE_XCOLOR:
9
+ return (r,g,b)
10
+ else:
11
+ return f"rgb:red,{r};green,{g};blue,{b}"
12
+
13
+ def hex_to_rgb(hex):
14
+ if hex[0] == "#":
15
+ hex = hex[1:]
16
+ hex = hex.upper()
17
+ rgb = []
18
+ for i in (0, 2, 4):
19
+ decimal = int(hex[i:i+2], 16) / 255
20
+ rgb.append(decimal)
21
+ return color_string(rgb[0],rgb[1],rgb[2])
22
+
23
+ if isinstance(input, tuple):
24
+ opacity = False
25
+ if len(input) == 1:
26
+ input = input[0]
27
+ elif len(input) == 2:
28
+ opacity= input[1]
29
+ input = input[0]
30
+ else:
31
+ r,g,b = input[:3]
32
+ if len(input) == 4:
33
+ opacity = input[3]
34
+ return color_string(r,g,b), opacity
35
+ s = str(input)
36
+ if s[0] == "#":
37
+ opacity = False
38
+ if len(s) == 4:
39
+ hex = s[1] * 2 + s[2] * 2 + s[3] * 2
40
+ else:
41
+ hex = s[:8]
42
+ if len(s) > 8:
43
+ opacity = int(s[8:]) / 100
44
+ return hex_to_rgb(hex), opacity
45
+ if s.isdigit():
46
+ i = float(s)
47
+ return color_string(i,i,i), False
48
+ if s.startswith("C") and s[1:].isdigit():
49
+ index = int(s[1:]) % len(_DEFAULT_CYCLE)
50
+ return hex_to_rgb(_DEFAULT_CYCLE[index]), False
51
+ if s.lower() == "none":
52
+ return color_string(0,0,0), 0
53
+ if s in _COLOR_MAP.keys():
54
+ return _COLOR_MAP[s], False
55
+ if s in _COLOR_MAP.values():
56
+ return s, False
57
+ print(f"Unrecognized color {input}")
58
+ return None, False
tikzplot/colors.pyi ADDED
@@ -0,0 +1 @@
1
+ from .config import TikzConfig as TikzConfig
tikzplot/config.py ADDED
@@ -0,0 +1,101 @@
1
+ import json
2
+ from pathlib import Path
3
+
4
+ class _TikzConfig:
5
+
6
+ def __init__(self):
7
+
8
+ self.USE_DECIMAL_COMMA: bool = False
9
+
10
+ self.LEGEND_REL_X: float = 0.03
11
+ self.LEGEND_REL_Y: float = 0.03
12
+
13
+ self.LEFT_PADDING: float = 0.1
14
+ self.RIGHT_PADDING: float = 0.1
15
+ self.TOP_PADDING: float = 0.1
16
+ self.BOTTOM_PADDING: float = 0.1
17
+ self.Y_LABEL_PADDING: float = 0.6
18
+ self.SEC_Y_PADDING: float = 0.8
19
+ self.SEC_Y_LABEL_PADDING: float = 0.6
20
+ self.TITLE_PADDING: float = 0.6
21
+ self.X_LABEL_PADDING: float = 0.6
22
+ self.XTICK_PADDING: float = 0.7
23
+ self.YTICK_PADDING: float = 0.7
24
+
25
+ self.DEFAULT_WIDTH: float = 12
26
+ self.DEFAULT_HEIGHT: float = 10
27
+
28
+ self.SHARED_AXIS_REL_MARGIN: float = 0.03
29
+
30
+ self.SAVE_DATAPOINTS: bool = True
31
+ self.DATAPOINTS_DIR: str = "datapoints" # ignored if SAVE_DATAPOINTS == False
32
+ self.UPDATE_DATA_ONLY: bool = False # ignored if SAVE_DATAPOINTS == False
33
+ self.UPDATE_STYLE_ONLY: bool = False # ignored if SAVE_DATAPOINTS == False
34
+ self.SHOW_SAVENAME: str = "showplot"
35
+ self.IMSHOW_SAVENAME: str = "imshow"
36
+
37
+ self.REDUCE_NUM_POINTS: bool = True
38
+ self.REDUCE_METHOD: int = 1 # 0: remove based on index; 1: remove based on plot distance; 2: remove based on curvature (good for line plots)
39
+ self.MAX_POINTS_PER_FIGURE: int = 10000
40
+ self.MAX_POINTS_PER_ELEMENT: int = 1000
41
+
42
+ self.STANDALONE: bool = False
43
+ self.TIKZ_COMPAT: float = 1.18 # only for standalone, used to change the setting in preambule, but does not guarantee the compatibility of the generated code wito older versions of pgfplots.
44
+ self.USE_XCOLOR: bool = True
45
+ self.USE_GROUPPLOTS: bool = True
46
+ self.SCHOOL_AXIS: bool = False
47
+ self.SCHOOL_AXIS_LABEL_MARGIN: float = 0.1
48
+
49
+ self.CBAR_X_OFFSET: float = 0.05
50
+ self.CBAR_Y_OFFSET: float = 0.2
51
+ self.CBAR_X_MARGIN: float = 0.5
52
+ self.CBAR_Y_MARGIN: float = 0.5
53
+
54
+ self.CBAR3_Z_OFFSET: float = 0.2 # for 3D vertical
55
+ self.CBAR3_H_OFFSET: float = 0.2 # for 3D horizontal
56
+
57
+ self.DEFAULT_3D_ROLL: float = 0
58
+ self.DEFAULT_3D_AZIM: float = 0
59
+ self.DEFAULT_3D_ELEV: float = 0
60
+
61
+ self._config_file: Path = Path.home() / ".tikz_userconf.json"
62
+
63
+ self._load_user_config()
64
+
65
+ def modifyParam(self, **kwargs):
66
+ for k, v in kwargs.items():
67
+ if not hasattr(self, k):
68
+ raise ValueError(f"Unknown TikzConfig parameter: {k}")
69
+ setattr(self, k, v)
70
+
71
+ def setPermanent(self, **kwargs):
72
+
73
+ self.modifyParam(**kwargs)
74
+
75
+ data = self._read_file()
76
+ data.update(kwargs)
77
+
78
+ with open(self._config_file, "w") as f:
79
+ json.dump(data, f, indent=2)
80
+
81
+ def _load_user_config(self):
82
+
83
+ if not self._config_file.exists():
84
+ return
85
+
86
+ with open(self._config_file) as f:
87
+ data = json.load(f)
88
+
89
+ for k, v in data.items():
90
+ if hasattr(self, k):
91
+ setattr(self, k, v)
92
+
93
+ def _read_file(self):
94
+
95
+ if not self._config_file.exists():
96
+ return {}
97
+
98
+ with open(self._config_file) as f:
99
+ return json.load(f)
100
+
101
+ TikzConfig = _TikzConfig()
tikzplot/config.pyi ADDED
@@ -0,0 +1,95 @@
1
+ # config.pyi
2
+
3
+ from typing import Any, Dict
4
+ from pathlib import Path
5
+
6
+ from typing import TypedDict, Unpack, Any, ClassVar, Protocol
7
+
8
+ class _ConfigParams(TypedDict, total=False):
9
+ USE_DECIMAL_COMMA: bool
10
+
11
+ LEGEND_REL_X: float
12
+ LEGEND_REL_Y: float
13
+
14
+ LEFT_PADDING: float
15
+ RIGHT_PADDING: float
16
+ TOP_PADDING: float
17
+ BOTTOM_PADDING: float
18
+ Y_LABEL_PADDING: float
19
+ SEC_Y_PADDING: float
20
+ SEC_Y_LABEL_PADDING: float
21
+ TITLE_PADDING: float
22
+ X_LABEL_PADDING: float
23
+
24
+ DEFAULT_WIDTH: float
25
+ DEFAULT_HEIGHT: float
26
+
27
+ SHARED_AXIS_REL_MARGIN: float
28
+
29
+ SAVE_DATAPOINTS: bool
30
+ DATAPOINTS_DIR: str
31
+ UPDATE_DATA_ONLY: bool
32
+ UPDATE_STYLE_ONLY: bool
33
+
34
+ SHOW_SAVENAME: str
35
+ IMSHOW_SAVENAME: str
36
+
37
+ REDUCE_NUM_POINTS: bool
38
+ REDUCE_METHOD: int
39
+ MAX_POINTS_PER_FIGURE: int
40
+ MAX_POINTS_PER_ELEMENT: int
41
+
42
+ STANDALONE: bool
43
+ TIKZ_COMPAT: float
44
+ USE_XCOLOR: bool
45
+ USE_GROUPPLOTS: bool
46
+ SCHOOL_AXIS: bool
47
+ SCHOOL_AXIS_LABEL_MARGIN: float
48
+
49
+ CBAR_X_OFFSET: float
50
+ CBAR_Y_OFFSET: float
51
+ CBAR_X_MARGIN: float
52
+ CBAR_Y_MARGIN: float
53
+
54
+ CBAR3_Z_OFFSET: float
55
+ CBAR3_H_OFFSET: float
56
+
57
+ DEFAULT_3D_ROLL: float
58
+ DEFAULT_3D_AZIM: float
59
+ DEFAULT_3D_ELEV: float
60
+
61
+
62
+
63
+
64
+ class TikzConfig:
65
+
66
+ def modifyParam(self, **kwargs: Unpack[_ConfigParams]) -> None:
67
+ """
68
+ Modify configuration parameters temporarily.
69
+
70
+ Parameters
71
+ ----------
72
+ kwargs:
73
+ Key-value pairs of configuration parameters to update.
74
+
75
+ Raises
76
+ ------
77
+ ValueError
78
+ If an unknown parameter is provided.
79
+ """
80
+ ...
81
+
82
+ def setPermanent(self, **kwargs: Unpack[_ConfigParams]) -> None:
83
+ """
84
+ Modify configuration parameters permanently.
85
+
86
+ Updates the in-memory configuration and writes changes
87
+ to the user configuration file (~/.tikz_userconf.json).
88
+
89
+ Parameters
90
+ ----------
91
+ kwargs:
92
+ Key-value pairs of configuration parameters to update.
93
+ """
94
+ ...
95
+