plotlp 0.1.2__tar.gz → 0.1.3__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.
- {plotlp-0.1.2 → plotlp-0.1.3}/PKG-INFO +3 -8
- {plotlp-0.1.2 → plotlp-0.1.3}/pyproject.toml +7 -2
- plotlp-0.1.3/src/plotlp/modules/StyledAxes_LP/StyledAxes.py +206 -0
- plotlp-0.1.3/src/plotlp/modules/StyledAxes_LP/test_StyledAxes.py +27 -0
- plotlp-0.1.3/src/plotlp/modules/StyledFigure_LP/StyledFigure.py +293 -0
- plotlp-0.1.3/src/plotlp/modules/StyledFigure_LP/test_StyledFigure.py +27 -0
- plotlp-0.1.3/src/plotlp/modules/cmap_LP/cmap.py +210 -0
- plotlp-0.1.3/src/plotlp/modules/cmap_LP/test_cmap.py +64 -0
- {plotlp-0.1.2 → plotlp-0.1.3}/src/plotlp/modules/color_LP/color.py +86 -93
- {plotlp-0.1.2 → plotlp-0.1.3}/src/plotlp/modules/color_LP/test_color.py +1 -1
- plotlp-0.1.3/src/plotlp/modules/figure_LP/figure.py +56 -0
- plotlp-0.1.3/src/plotlp/modules/figure_LP/test_figure.py +62 -0
- plotlp-0.1.3/src/plotlp/modules/imgfigure_LP/imgfigure.py +62 -0
- plotlp-0.1.3/src/plotlp/modules/imgfigure_LP/test_imgfigure.py +39 -0
- plotlp-0.1.3/src/plotlp/modules/plt_LP/__init__.py +0 -0
- plotlp-0.1.3/src/plotlp/modules/plt_LP/plt.py +24 -0
- plotlp-0.1.3/src/plotlp/modules/plt_LP/test_plt.py +27 -0
- plotlp-0.1.3/src/plotlp/modules/style_LP/__init__.py +0 -0
- {plotlp-0.1.2 → plotlp-0.1.3}/src/plotlp/modules/style_LP/style.py +2 -9
- plotlp-0.1.3/src/plotlp/modules/style_LP/styles/__init__.py +0 -0
- {plotlp-0.1.2 → plotlp-0.1.3}/src/plotlp/modules/style_LP/styles/darkLP.py +1 -1
- {plotlp-0.1.2 → plotlp-0.1.3}/src/plotlp/modules/style_LP/styles/lightLP.py +1 -1
- {plotlp-0.1.2 → plotlp-0.1.3}/src/plotlp/modules/style_LP/styles/styleLP.py +1 -1
- plotlp-0.1.3/src/plotlp/modules/subplots_LP/__init__.py +0 -0
- plotlp-0.1.3/src/plotlp/modules/subplots_LP/subplots.py +54 -0
- plotlp-0.1.3/src/plotlp/modules/subplots_LP/test_subplots.py +54 -0
- plotlp-0.1.3/src/plotlp/modules.json +56 -0
- plotlp-0.1.3/src/plotlp/py.typed +0 -0
- plotlp-0.1.3/src/plotlp/scripts/__init__.py +0 -0
- plotlp-0.1.2/src/plotlp/modules/cmap_LP/cmap.py +0 -132
- plotlp-0.1.2/src/plotlp/modules/cmap_LP/test_cmap.py +0 -79
- plotlp-0.1.2/src/plotlp/modules.json +0 -20
- {plotlp-0.1.2 → plotlp-0.1.3}/README.md +0 -0
- {plotlp-0.1.2 → plotlp-0.1.3}/src/plotlp/__init__.py +0 -0
- {plotlp-0.1.2/src/plotlp/modules → plotlp-0.1.3/src/plotlp/modules/StyledAxes_LP}/__init__.py +0 -0
- {plotlp-0.1.2/src/plotlp/modules/cmap_LP → plotlp-0.1.3/src/plotlp/modules/StyledFigure_LP}/__init__.py +0 -0
- {plotlp-0.1.2/src/plotlp/modules/color_LP → plotlp-0.1.3/src/plotlp/modules}/__init__.py +0 -0
- {plotlp-0.1.2/src/plotlp/modules/style_LP → plotlp-0.1.3/src/plotlp/modules/cmap_LP}/__init__.py +0 -0
- {plotlp-0.1.2/src/plotlp/modules/style_LP/styles → plotlp-0.1.3/src/plotlp/modules/color_LP}/__init__.py +0 -0
- {plotlp-0.1.2/src/plotlp/scripts → plotlp-0.1.3/src/plotlp/modules/figure_LP}/__init__.py +0 -0
- /plotlp-0.1.2/src/plotlp/py.typed → /plotlp-0.1.3/src/plotlp/modules/imgfigure_LP/__init__.py +0 -0
- {plotlp-0.1.2 → plotlp-0.1.3}/src/plotlp/modules/style_LP/styles/default.py +0 -0
- {plotlp-0.1.2 → plotlp-0.1.3}/src/plotlp/modules/style_LP/test_style.py +0 -0
- {plotlp-0.1.2 → plotlp-0.1.3}/src/plotlp/scripts.json +0 -0
|
@@ -1,17 +1,12 @@
|
|
|
1
1
|
Metadata-Version: 2.3
|
|
2
2
|
Name: plotlp
|
|
3
|
-
Version: 0.1.
|
|
3
|
+
Version: 0.1.3
|
|
4
4
|
Summary: A library wrapper around matplotlib for custom plots.
|
|
5
5
|
Requires-Dist: corelp
|
|
6
6
|
Requires-Dist: cycler
|
|
7
|
-
Requires-Dist: ipykernel
|
|
8
7
|
Requires-Dist: matplotlib
|
|
9
|
-
Requires-Dist:
|
|
10
|
-
Requires-Dist:
|
|
11
|
-
Requires-Dist: sphinx-design
|
|
12
|
-
Requires-Dist: sphinx-rtd-theme
|
|
13
|
-
Requires-Dist: spyder-kernels
|
|
14
|
-
Requires-Dist: toml
|
|
8
|
+
Requires-Dist: numpy
|
|
9
|
+
Requires-Dist: pillow
|
|
15
10
|
Requires-Python: >=3.12
|
|
16
11
|
Description-Content-Type: text/markdown
|
|
17
12
|
|
|
@@ -1,15 +1,20 @@
|
|
|
1
1
|
[project]
|
|
2
2
|
name = "plotlp"
|
|
3
|
-
version = "0.1.
|
|
3
|
+
version = "0.1.3"
|
|
4
4
|
description = "A library wrapper around matplotlib for custom plots."
|
|
5
5
|
readme = "README.md"
|
|
6
6
|
requires-python = ">=3.12"
|
|
7
|
-
dependencies = [ "corelp", "cycler", "
|
|
7
|
+
dependencies = [ "corelp", "cycler", "matplotlib", "numpy", "pillow",]
|
|
8
8
|
|
|
9
9
|
[build-system]
|
|
10
10
|
requires = [ "uv_build>=0.8.8,<0.9.0",]
|
|
11
11
|
build-backend = "uv_build"
|
|
12
12
|
|
|
13
|
+
[dependency-groups]
|
|
14
|
+
dev = [ "pytest",]
|
|
15
|
+
docs = [ "sphinx", "sphinx-design", "sphinx-rtd-theme", "toml",]
|
|
16
|
+
anaconda = [ "ipykernel", "spyder-kernels",]
|
|
17
|
+
|
|
13
18
|
[tool.uv]
|
|
14
19
|
required-environments = [ "sys_platform == 'linux' and platform_machine == 'x86_64'", "sys_platform == 'win32' and (platform_machine == 'AMD64' or platform_machine == 'x86_64')",]
|
|
15
20
|
|
|
@@ -0,0 +1,206 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
# -*- coding: utf-8 -*-
|
|
3
|
+
# Date : 2025-12-11
|
|
4
|
+
# Author : Lancelot PINCET
|
|
5
|
+
# GitHub : https://github.com/LancelotPincet
|
|
6
|
+
# Library : plotLP
|
|
7
|
+
# Module : StyledAxes
|
|
8
|
+
|
|
9
|
+
"""
|
|
10
|
+
A class using stored styles inside.
|
|
11
|
+
"""
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
# %% Libraries
|
|
16
|
+
from matplotlib.axes import Axes
|
|
17
|
+
from matplotlib import pyplot as plt
|
|
18
|
+
import matplotlib.projections as projections
|
|
19
|
+
import inspect
|
|
20
|
+
from corelp import prop
|
|
21
|
+
import numpy as np
|
|
22
|
+
from matplotlib.patches import Rectangle
|
|
23
|
+
from mpl_toolkits.axes_grid1.inset_locator import inset_axes
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
# %% Class
|
|
28
|
+
class StyledAxes(Axes) :
|
|
29
|
+
f'''
|
|
30
|
+
A class using stored styles inside.
|
|
31
|
+
|
|
32
|
+
Attributes
|
|
33
|
+
----------
|
|
34
|
+
style : dict
|
|
35
|
+
associated figure style.
|
|
36
|
+
polish_imscale : bool
|
|
37
|
+
True to polish automatically imscale
|
|
38
|
+
polish_grids : bool
|
|
39
|
+
True to polish automatically grids
|
|
40
|
+
polish_noborder : bool
|
|
41
|
+
True to polish automatically no boders
|
|
42
|
+
polish_equiscale : bool
|
|
43
|
+
True to polish automatically equiscale
|
|
44
|
+
|
|
45
|
+
Examples
|
|
46
|
+
--------
|
|
47
|
+
>>> from plotlp import subplots
|
|
48
|
+
...
|
|
49
|
+
>>> fig, axes = subplots(nrows=2, ncols=2) # StyledFigure, StyledAxes
|
|
50
|
+
>>> axis = fig.axis # StyledAxes, current axis of fig
|
|
51
|
+
>>> axis.polish() # applies all the polish methods for all the "polish_attr" attributes
|
|
52
|
+
>>> axis.grids() # applies the polish grids, adds major and minor grids
|
|
53
|
+
>>> axis.imscale() # applies the polish imscale, sets x and y limits to images borders
|
|
54
|
+
>>> axis.noborder() # applies the polish no border, removes axis borders
|
|
55
|
+
>>> axis.equiscale() # applies the polish equiscale, x and y unit have same size on plot
|
|
56
|
+
>>> axis.implot(image, x, y, w, h) # plots an image to the coordinates, deformes to fit the box defined
|
|
57
|
+
'''
|
|
58
|
+
|
|
59
|
+
name = "styled"
|
|
60
|
+
@property
|
|
61
|
+
def style(self) :
|
|
62
|
+
return self.figure.style
|
|
63
|
+
|
|
64
|
+
# Imshow
|
|
65
|
+
def imshow(self, X, *args, barname=None, coordinates=None, **kwargs) :
|
|
66
|
+
with plt.style.context(self.style):
|
|
67
|
+
if coordinates is not None :
|
|
68
|
+
x, y = coordinates
|
|
69
|
+
dx, dy = (x[-1]-x[0]) / (len(x)-1) / 2, (y[-1]-y[0]) / (len(y)-1) / 2
|
|
70
|
+
extent = [x[0]-dx, x[-1]+dx, y[0]-dy, y[-1]+dy]
|
|
71
|
+
kwargs.update(dict(extent=extent, aspect='auto', origin='lower'))
|
|
72
|
+
im = super().imshow(X, *args, **kwargs)
|
|
73
|
+
if coordinates is not None :
|
|
74
|
+
self.invert_yaxis()
|
|
75
|
+
Ny, Nx = X.shape
|
|
76
|
+
self.set_box_aspect(Ny / Nx)
|
|
77
|
+
self.polish_axis = False
|
|
78
|
+
if barname is not None :
|
|
79
|
+
self.figure.colorbar(im, barname=barname)
|
|
80
|
+
|
|
81
|
+
return im
|
|
82
|
+
|
|
83
|
+
# Pcolormesh
|
|
84
|
+
def pcolormesh(self, *args, cmap=None, **kwargs):
|
|
85
|
+
with plt.style.context(self.style):
|
|
86
|
+
if cmap is None:
|
|
87
|
+
cmap = plt.get_cmap(plt.rcParams['image.cmap'])
|
|
88
|
+
return super().pcolormesh(*args, cmap=cmap, **kwargs)
|
|
89
|
+
|
|
90
|
+
# Implot
|
|
91
|
+
def implot(self, img, x, y, w, h, zorder=3, **kwargs) :
|
|
92
|
+
newaxe = inset_axes(self, [x, y, w, h], transform=self.transData, zorder=zorder, axes_class=StyledAxes)
|
|
93
|
+
newaxe.set_axis_off()
|
|
94
|
+
kw = {'aspect':'auto','extent':[x, x+w, y, y+h],'origin':'lower'}
|
|
95
|
+
kw.update(kwargs)
|
|
96
|
+
im = newaxe.imshow(img, **kw)
|
|
97
|
+
clip_rect = Rectangle((0, 0), 1, 1, transform=self.transAxes, facecolor="none")
|
|
98
|
+
im.set_clip_path(clip_rect)
|
|
99
|
+
return im
|
|
100
|
+
|
|
101
|
+
|
|
102
|
+
### --- Polish functions ---
|
|
103
|
+
|
|
104
|
+
|
|
105
|
+
|
|
106
|
+
polish_axis = True
|
|
107
|
+
def polish(self) :
|
|
108
|
+
if not self.polish_axis : return
|
|
109
|
+
if self.polish_grids : self.grids()
|
|
110
|
+
if self.polish_imscale : self.imscale()
|
|
111
|
+
if self.polish_noborders : self.noborders()
|
|
112
|
+
if self.polish_equiscale : self.equiscale()
|
|
113
|
+
|
|
114
|
+
# grids
|
|
115
|
+
@prop()
|
|
116
|
+
def polish_grids(self) :
|
|
117
|
+
return len(self.lines) > 0 or len(self.collections) > 0
|
|
118
|
+
grid_major = {'linestyle':'-', 'alpha':1}
|
|
119
|
+
grid_minor = {'linestyle':'--', 'alpha':0.5}
|
|
120
|
+
def grids(self) :
|
|
121
|
+
with plt.style.context(self.style) :
|
|
122
|
+
if self.grid_major is not None and len(self.grid_major) > 0 :
|
|
123
|
+
self.grid(which='major',**self.grid_major)
|
|
124
|
+
if self.grid_minor is not None and len(self.grid_minor) > 0 :
|
|
125
|
+
self.minorticks_on() # force enabling minor ticks
|
|
126
|
+
self.grid(which='minor',**self.grid_minor)
|
|
127
|
+
|
|
128
|
+
# imscale
|
|
129
|
+
@prop()
|
|
130
|
+
def polish_imscale(self) :
|
|
131
|
+
return len(self.get_images()) > 0
|
|
132
|
+
def imscale(self) :
|
|
133
|
+
with plt.style.context(self.style) :
|
|
134
|
+
xmax, ymax = 0, 0
|
|
135
|
+
for image in self.get_images() : # Get maximum image coordinates
|
|
136
|
+
y, x = np.shape(image.get_array())[0:2]
|
|
137
|
+
ymax, xmax = max(y, ymax), max(x, xmax)
|
|
138
|
+
if self.get_autoscalex_on() :
|
|
139
|
+
self.set_xlim(-0.5, xmax - 0.5)
|
|
140
|
+
if self.get_autoscaley_on() :
|
|
141
|
+
self.set_ylim(ymax - 0.5, -0.5)
|
|
142
|
+
|
|
143
|
+
# noborders
|
|
144
|
+
@prop()
|
|
145
|
+
def polish_noborders(self) :
|
|
146
|
+
return not self.polish_grids
|
|
147
|
+
def noborders(self) :
|
|
148
|
+
with plt.style.context(self.style) :
|
|
149
|
+
self.set_axis_off()
|
|
150
|
+
|
|
151
|
+
# equiscale
|
|
152
|
+
@prop()
|
|
153
|
+
def polish_equiscale(self) :
|
|
154
|
+
return False
|
|
155
|
+
def equiscale(self) :
|
|
156
|
+
with plt.style.context(self.style) :
|
|
157
|
+
self.set_aspect(aspect='equal', adjustable='box')
|
|
158
|
+
|
|
159
|
+
|
|
160
|
+
|
|
161
|
+
### --- Regenerate parent class methods in the given style ---
|
|
162
|
+
|
|
163
|
+
|
|
164
|
+
|
|
165
|
+
def is_plottable(method_name, method_obj):
|
|
166
|
+
"""
|
|
167
|
+
Returns True if this method should be wrapped automatically.
|
|
168
|
+
"""
|
|
169
|
+
if hasattr(StyledAxes, method_name): # Already overriden
|
|
170
|
+
return False
|
|
171
|
+
if method_name.startswith("_"): # private
|
|
172
|
+
return False # handled separately
|
|
173
|
+
if not callable(method_obj):
|
|
174
|
+
return False
|
|
175
|
+
if not inspect.ismethoddescriptor(method_obj) and not inspect.isfunction(method_obj):
|
|
176
|
+
return False
|
|
177
|
+
# Heuristic: methods returning artists / sequences of artists
|
|
178
|
+
# Usually are plotting methods; we accept them all here
|
|
179
|
+
return True
|
|
180
|
+
|
|
181
|
+
def wrap_method(method_name):
|
|
182
|
+
"""
|
|
183
|
+
Returns a wrapper method that applies the style context
|
|
184
|
+
then calls the parent Axes method.
|
|
185
|
+
"""
|
|
186
|
+
def wrapper(self, *args, **kwargs):
|
|
187
|
+
with plt.style.context(self.style):
|
|
188
|
+
method = getattr(super(StyledAxes, self), method_name)
|
|
189
|
+
return method(*args, **kwargs)
|
|
190
|
+
wrapper.__name__ = method_name
|
|
191
|
+
return wrapper
|
|
192
|
+
|
|
193
|
+
# Dynamically inject each wrapper method into StyledAxes
|
|
194
|
+
for name, obj in Axes.__dict__.items():
|
|
195
|
+
if is_plottable(name, obj):
|
|
196
|
+
setattr(StyledAxes, name, wrap_method(name))
|
|
197
|
+
|
|
198
|
+
# Finally register projection
|
|
199
|
+
projections.register_projection(StyledAxes)
|
|
200
|
+
|
|
201
|
+
|
|
202
|
+
|
|
203
|
+
# %% Test function run
|
|
204
|
+
if __name__ == "__main__":
|
|
205
|
+
from corelp import test
|
|
206
|
+
test(__file__)
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
# -*- coding: utf-8 -*-
|
|
3
|
+
# Date : 2025-12-11
|
|
4
|
+
# Author : Lancelot PINCET
|
|
5
|
+
# GitHub : https://github.com/LancelotPincet
|
|
6
|
+
# Library : plotLP
|
|
7
|
+
# Module : StyledAxes
|
|
8
|
+
|
|
9
|
+
"""
|
|
10
|
+
This file allows to test StyledAxes
|
|
11
|
+
|
|
12
|
+
StyledAxes : A class using stored styles inside.
|
|
13
|
+
"""
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
# %% Libraries
|
|
18
|
+
from corelp import print, debug
|
|
19
|
+
from plotlp import StyledAxes
|
|
20
|
+
debug_folder = debug(__file__)
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
# %% Test function run
|
|
25
|
+
if __name__ == "__main__":
|
|
26
|
+
from corelp import test
|
|
27
|
+
test(__file__)
|
|
@@ -0,0 +1,293 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
# -*- coding: utf-8 -*-
|
|
3
|
+
# Date : 2025-12-11
|
|
4
|
+
# Author : Lancelot PINCET
|
|
5
|
+
# GitHub : https://github.com/LancelotPincet
|
|
6
|
+
# Library : plotLP
|
|
7
|
+
# Module : StyledFigure
|
|
8
|
+
|
|
9
|
+
"""
|
|
10
|
+
A class defining figures with custom styles included inside.
|
|
11
|
+
"""
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
# %% Libraries
|
|
16
|
+
from matplotlib.figure import Figure
|
|
17
|
+
from matplotlib import pyplot as plt
|
|
18
|
+
import numpy as np
|
|
19
|
+
from plotlp import style as get_style
|
|
20
|
+
from plotlp import StyledAxes # do not remove even if unused
|
|
21
|
+
from mpl_toolkits.axes_grid1 import make_axes_locatable
|
|
22
|
+
from corelp import selfkwargs, prop
|
|
23
|
+
import gc
|
|
24
|
+
from io import BytesIO
|
|
25
|
+
from pathlib import Path
|
|
26
|
+
from PIL import Image
|
|
27
|
+
import string
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
# %% Class
|
|
32
|
+
class StyledFigure(Figure) :
|
|
33
|
+
f'''
|
|
34
|
+
A class defining figures with custom styles included inside.
|
|
35
|
+
|
|
36
|
+
Parameters
|
|
37
|
+
----------
|
|
38
|
+
figsize : tuple
|
|
39
|
+
figure size [inch] (x, y).
|
|
40
|
+
dpi : int
|
|
41
|
+
Dots Per Inch resolution.
|
|
42
|
+
style : str or dict
|
|
43
|
+
Name of style or corresponding dict.
|
|
44
|
+
lightmode : bool
|
|
45
|
+
True to use lightLP style.
|
|
46
|
+
darkmode : bool
|
|
47
|
+
True to use darkLP style.
|
|
48
|
+
kwargs : dict
|
|
49
|
+
Keyword arguments corresponding to attributes to change.
|
|
50
|
+
|
|
51
|
+
Attributes
|
|
52
|
+
----------
|
|
53
|
+
axis : property
|
|
54
|
+
set as an index, when gotten returns corresponding axis.
|
|
55
|
+
plot_axes : list
|
|
56
|
+
list of plotting axes.
|
|
57
|
+
naxes : int
|
|
58
|
+
Number of plotting axes.
|
|
59
|
+
figsize_default : tuple
|
|
60
|
+
Default figure size (x, y) in inch.
|
|
61
|
+
figsize_ratio : float
|
|
62
|
+
x/y figure size ratio, while keeping the same area as default figsize.
|
|
63
|
+
figsize_fact : tuple
|
|
64
|
+
(x, y) figure size growing factors.
|
|
65
|
+
title : property
|
|
66
|
+
suptitle applied and to apply when set.
|
|
67
|
+
tight : bool
|
|
68
|
+
True to apply tight layout when polishing.
|
|
69
|
+
|
|
70
|
+
Examples
|
|
71
|
+
--------
|
|
72
|
+
>>> from plotlp import figure, plt
|
|
73
|
+
...
|
|
74
|
+
>>> fig = figure() # Savefigure output
|
|
75
|
+
>>> plt.imshow(image, barname='My colorbar') # Apply barname to auto createe colorbar
|
|
76
|
+
>>> fig.polish() # Applies StyledAxes automatic polishing on each axis
|
|
77
|
+
>>> fig.arrayfig(close=False) # Saves figure into an numpy array (calls fig.savefig, close=False to not close figure)
|
|
78
|
+
>>> plt.savefig(png_path=png_path, close=False, **savefig_kwargs) # saving png only
|
|
79
|
+
>>> plt.savefig(pdf_path=pdf_path, close=False, **savefig_kwargs) # saving pdf only
|
|
80
|
+
>>> plt.savefig(path, **savefig_kwargs) # saving png and pdf automatically, close=True by default so no more figure after
|
|
81
|
+
'''
|
|
82
|
+
|
|
83
|
+
def __init__(self, figsize=None, dpi=None, *, style=None, darkmode=False, lightmode=False, **kwargs):
|
|
84
|
+
|
|
85
|
+
# Style
|
|
86
|
+
if style is not None :
|
|
87
|
+
self.style = style
|
|
88
|
+
elif lightmode : self.lightmode()
|
|
89
|
+
elif darkmode : self.darkmode()
|
|
90
|
+
else :
|
|
91
|
+
self.style
|
|
92
|
+
|
|
93
|
+
# Init
|
|
94
|
+
with plt.style.context(self.style) :
|
|
95
|
+
super().__init__(figsize, dpi)
|
|
96
|
+
selfkwargs(self, kwargs)
|
|
97
|
+
self.figresize()
|
|
98
|
+
|
|
99
|
+
|
|
100
|
+
|
|
101
|
+
#Style
|
|
102
|
+
style_name = 'lightLP'
|
|
103
|
+
_style = None #style dict
|
|
104
|
+
style_kwargs = {}
|
|
105
|
+
@property
|
|
106
|
+
def style(self) :
|
|
107
|
+
if self._style is None :
|
|
108
|
+
self.style = self.style_name
|
|
109
|
+
return self._style
|
|
110
|
+
@style.setter
|
|
111
|
+
def style(self,value) :
|
|
112
|
+
if isinstance(value,str) :
|
|
113
|
+
self.style_name = value
|
|
114
|
+
self._style = get_style(value)
|
|
115
|
+
else :
|
|
116
|
+
self.style_name = None
|
|
117
|
+
self._style = value
|
|
118
|
+
self._style.update(self.style_kwargs)
|
|
119
|
+
def lightmode(self) : #to auto call lightmode
|
|
120
|
+
self.style = 'lightLP'
|
|
121
|
+
def darkmode(self) : #to auto call darkmode
|
|
122
|
+
self.style = 'darkLP'
|
|
123
|
+
|
|
124
|
+
|
|
125
|
+
|
|
126
|
+
#Axe
|
|
127
|
+
axis_num = 0 #index of axes
|
|
128
|
+
|
|
129
|
+
@property
|
|
130
|
+
def axis(self) :
|
|
131
|
+
return self.plot_axes[self.axis_num]
|
|
132
|
+
@axis.setter
|
|
133
|
+
def axis(self,value) :
|
|
134
|
+
self.axis_num = value
|
|
135
|
+
plt.sca(self.plot_axes[self.axis_num])
|
|
136
|
+
|
|
137
|
+
@property
|
|
138
|
+
def naxes(self) :
|
|
139
|
+
return len(self.plot_axes)
|
|
140
|
+
|
|
141
|
+
@property
|
|
142
|
+
def plot_axes(self) :
|
|
143
|
+
return [ax for ax in self.axes if not getattr(ax, "is_cbar", False)]
|
|
144
|
+
|
|
145
|
+
def add_subplot(self, *args, **kwargs):
|
|
146
|
+
with plt.style.context(self.style) :
|
|
147
|
+
kwargs["projection"] = "styled" # force the Axes type
|
|
148
|
+
return super().add_subplot(*args, **kwargs)
|
|
149
|
+
def add_axes(self, *args, **kwargs):
|
|
150
|
+
with plt.style.context(self.style) :
|
|
151
|
+
return super().add_axes(*args, **kwargs)
|
|
152
|
+
|
|
153
|
+
|
|
154
|
+
|
|
155
|
+
# Paper index
|
|
156
|
+
paper_index_kwargs = {'size': 20, 'weight': 'bold'}
|
|
157
|
+
def paper_index(self, axes=None, **kwargs) :
|
|
158
|
+
with plt.style.context(self.style) :
|
|
159
|
+
if axes is None :
|
|
160
|
+
axes = self.plot_axes
|
|
161
|
+
kw = self.paper_index_kwargs.copy()
|
|
162
|
+
kw.update(kwargs)
|
|
163
|
+
for n, ax in enumerate(axes):
|
|
164
|
+
ax.text(-0.1, 1.1, string.ascii_lowercase[n], transform=ax.transAxes, **kw)
|
|
165
|
+
|
|
166
|
+
|
|
167
|
+
|
|
168
|
+
# Colorbar
|
|
169
|
+
barname = {'rotation':270,'labelpad':10}
|
|
170
|
+
cax = {'size':"5%", 'pad':0.05}
|
|
171
|
+
def colorbar(self, mappable, cax=None, ax=None, barname=None, **kwargs) :
|
|
172
|
+
with plt.style.context(self.style) :
|
|
173
|
+
if cax is None :
|
|
174
|
+
if ax is None :
|
|
175
|
+
ax = mappable.axes
|
|
176
|
+
divider = make_axes_locatable(ax)
|
|
177
|
+
cax = divider.append_axes("right", **self.cax)
|
|
178
|
+
cax.is_cbar = True
|
|
179
|
+
cbar = super().colorbar(mappable=mappable, cax=cax, ax=None, **kwargs)
|
|
180
|
+
if barname is not None :
|
|
181
|
+
cbar.ax.set_ylabel(barname, **self.barname)
|
|
182
|
+
return cbar
|
|
183
|
+
|
|
184
|
+
|
|
185
|
+
|
|
186
|
+
#figure size parameter
|
|
187
|
+
@prop()
|
|
188
|
+
def figsize_default(self) :
|
|
189
|
+
return self.get_size_inches()
|
|
190
|
+
|
|
191
|
+
@prop()
|
|
192
|
+
def figsize_ratio(self) :
|
|
193
|
+
x, y = self.figsize_default
|
|
194
|
+
return x / y
|
|
195
|
+
|
|
196
|
+
@prop()
|
|
197
|
+
def figsize_fact(self) :
|
|
198
|
+
return 1., 1.
|
|
199
|
+
|
|
200
|
+
def figresize(self) :
|
|
201
|
+
default = self.figsize_default
|
|
202
|
+
ratio = self.figsize_ratio
|
|
203
|
+
fact = self.figsize_fact
|
|
204
|
+
area = default[0] * default[1]
|
|
205
|
+
y = np.sqrt(area/ratio)
|
|
206
|
+
x = ratio * y
|
|
207
|
+
self.set_size_inches(x * fact[0], y * fact[1])
|
|
208
|
+
self._figsize_default = None
|
|
209
|
+
self._figsize_ratio = None
|
|
210
|
+
self._figsize_fact = None
|
|
211
|
+
|
|
212
|
+
|
|
213
|
+
|
|
214
|
+
# Title
|
|
215
|
+
@property
|
|
216
|
+
def title(self) :
|
|
217
|
+
if getattr(self, '_title', None) is None :
|
|
218
|
+
return None
|
|
219
|
+
return self._title.get_text()
|
|
220
|
+
@title.setter
|
|
221
|
+
def title(self, value) :
|
|
222
|
+
with plt.style.context(self.style) :
|
|
223
|
+
self._title = self.suptitle(value)
|
|
224
|
+
|
|
225
|
+
|
|
226
|
+
|
|
227
|
+
# Polish
|
|
228
|
+
tight = True
|
|
229
|
+
polish_figure = True
|
|
230
|
+
def polish(self) :
|
|
231
|
+
with plt.style.context(self.style) :
|
|
232
|
+
for axis_num in range(self.naxes) :
|
|
233
|
+
self.axis = axis_num
|
|
234
|
+
self.axis.polish()
|
|
235
|
+
if self.tight :
|
|
236
|
+
self.tight_layout()
|
|
237
|
+
|
|
238
|
+
|
|
239
|
+
|
|
240
|
+
# Savefig
|
|
241
|
+
def savefig(self, path=None, *, polish=None, path_png=None, path_pdf=None, close=True, **kwargs) :
|
|
242
|
+
if polish is True or polish is None and self.polish_figure :
|
|
243
|
+
self.polish()
|
|
244
|
+
|
|
245
|
+
with plt.style.context(self.style) :
|
|
246
|
+
|
|
247
|
+
# Saving in array
|
|
248
|
+
if isinstance(path, BytesIO) :
|
|
249
|
+
super().savefig(path, **kwargs)
|
|
250
|
+
|
|
251
|
+
# Saving in file
|
|
252
|
+
else :
|
|
253
|
+
path_png = Path(path_png) if path_png is not None else Path(path) if path is not None and path.suffix != '.pdf' else None
|
|
254
|
+
path_pdf = Path(path_pdf) if path_pdf is not None else Path(path) if path is not None and path.suffix != '.png' else None
|
|
255
|
+
|
|
256
|
+
if path_png is not None :
|
|
257
|
+
super().savefig(path_png.with_suffix('.png'), **kwargs)
|
|
258
|
+
if path_pdf is not None :
|
|
259
|
+
super().savefig(path_pdf.with_suffix('.pdf'), **kwargs)
|
|
260
|
+
|
|
261
|
+
# Close figure
|
|
262
|
+
if close :
|
|
263
|
+
plt.close(self)
|
|
264
|
+
gc.collect()
|
|
265
|
+
|
|
266
|
+
|
|
267
|
+
|
|
268
|
+
#Arrayfig
|
|
269
|
+
def arrayfig(self, *args, **kwargs) :
|
|
270
|
+
'''
|
|
271
|
+
Converts figure into a numpy array
|
|
272
|
+
'''
|
|
273
|
+
with plt.style.context(self.style) :
|
|
274
|
+
with BytesIO() as buf:
|
|
275
|
+
self.savefig(buf, *args, **kwargs)
|
|
276
|
+
buf.seek(0)
|
|
277
|
+
image = Image.open(buf)
|
|
278
|
+
image_np = np.array(image)
|
|
279
|
+
return image_np
|
|
280
|
+
|
|
281
|
+
|
|
282
|
+
|
|
283
|
+
#Show
|
|
284
|
+
def show(self, *args, **kwargs) :
|
|
285
|
+
with plt.style.context(self.style) :
|
|
286
|
+
super().show(*args,**kwargs)
|
|
287
|
+
|
|
288
|
+
|
|
289
|
+
|
|
290
|
+
# %% Test function run
|
|
291
|
+
if __name__ == "__main__":
|
|
292
|
+
from corelp import test
|
|
293
|
+
test(__file__)
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
# -*- coding: utf-8 -*-
|
|
3
|
+
# Date : 2025-12-11
|
|
4
|
+
# Author : Lancelot PINCET
|
|
5
|
+
# GitHub : https://github.com/LancelotPincet
|
|
6
|
+
# Library : plotLP
|
|
7
|
+
# Module : StyledFigure
|
|
8
|
+
|
|
9
|
+
"""
|
|
10
|
+
This file allows to test StyledFigure
|
|
11
|
+
|
|
12
|
+
StyledFigure : A class defining figures with custom styles included inside.
|
|
13
|
+
"""
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
# %% Libraries
|
|
18
|
+
from corelp import print, debug
|
|
19
|
+
from plotlp import StyledFigure
|
|
20
|
+
debug_folder = debug(__file__)
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
# %% Test function run
|
|
25
|
+
if __name__ == "__main__":
|
|
26
|
+
from corelp import test
|
|
27
|
+
test(__file__)
|