gsplot 0.0.1__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.
gsplot/style/legend.py ADDED
@@ -0,0 +1,469 @@
1
+ from typing import Any
2
+
3
+ import matplotlib.pyplot as plt
4
+ from matplotlib.artist import Artist
5
+ from matplotlib.axes import Axes
6
+ from matplotlib.legend import Legend as Lg
7
+ from matplotlib.legend_handler import HandlerBase
8
+
9
+ from ..base.base import CreateClassParams, ParamsGetter, bind_passed_params
10
+ from ..figure.axes_base import AxesResolver
11
+
12
+ __all__: list[str] = [
13
+ "legend",
14
+ "legend_axes",
15
+ "legend_handlers",
16
+ "legend_reverse",
17
+ "legend_get_handlers",
18
+ ]
19
+
20
+
21
+ class Legend:
22
+ """
23
+ A class to manage legends for a specific Matplotlib axis.
24
+
25
+ This class provides functionality for customizing, reversing, and managing
26
+ legends on a specific axis in a Matplotlib figure.
27
+
28
+ Parameters
29
+ --------------------
30
+ axis_target : int | Axes
31
+ The target axis for the legend. Can be an axis index or an `Axes` object.
32
+ handles : list[Any], optional
33
+ A list of handles for the legend.
34
+ labels : list[str], optional
35
+ A list of labels for the legend.
36
+ handlers : dict, optional
37
+ A dictionary of custom legend handlers.
38
+ *args : Any
39
+ Additional positional arguments for the legend.
40
+ **kwargs : Any
41
+ Additional keyword arguments for the legend.
42
+
43
+ Attributes
44
+ --------------------
45
+ axis_target : int | Axes
46
+ The target axis for the legend.
47
+ handles : list[Any] | None
48
+ The legend handles.
49
+ labels : list[str] | None
50
+ The legend labels.
51
+ handlers : dict | None
52
+ The custom legend handlers.
53
+ axis_index : int
54
+ The resolved index of the target axis.
55
+ axis : matplotlib.axes.Axes
56
+ The resolved `Axes` object for the target axis.
57
+
58
+ Methods
59
+ --------------------
60
+ get_legend_handlers() -> tuple[list[Artist], list[str], dict[Artist, HandlerBase]]
61
+ Retrieves the legend handles, labels, and associated handlers.
62
+ legend() -> matplotlib.legend.Legend
63
+ Adds a legend to the axis.
64
+ legend_handlers() -> matplotlib.legend.Legend
65
+ Adds a legend with custom handles, labels, and handlers.
66
+ reverse_legend() -> matplotlib.legend.Legend
67
+ Adds a legend to the axis with reversed order of handles and labels.
68
+ """
69
+
70
+ def __init__(
71
+ self,
72
+ axis_target: int | Axes,
73
+ handles: list[Any] | None = None,
74
+ labels: list[str] | None = None,
75
+ handlers: dict | None = None,
76
+ *args: Any,
77
+ **kwargs: Any
78
+ ):
79
+ self.axis_target: int | Axes = axis_target
80
+ self.handles: list[Any] | None = handles
81
+ self.labels: list[str] | None = labels
82
+ self.handlers: dict | None = handlers
83
+ self.args: Any = args
84
+ self.kwargs: Any = kwargs
85
+
86
+ _axes_resolver = AxesResolver(axis_target)
87
+ self.axis_index: int = _axes_resolver.axis_index
88
+ self.axis: Axes = _axes_resolver.axis
89
+
90
+ def get_legend_handlers(
91
+ self,
92
+ ) -> tuple[list[Artist], list[str], dict[Artist, HandlerBase]]:
93
+ """
94
+ Retrieves the legend handles, labels, and associated handlers for the target axis.
95
+
96
+ Returns
97
+ --------------------
98
+ tuple[list[Artist], list[str], dict[Artist, HandlerBase]]
99
+ - handles: The list of legend handles.
100
+ - labels: The list of legend labels.
101
+ - handlers: A dictionary mapping handles to their legend handlers.
102
+ """
103
+
104
+ handles, labels = self.axis.get_legend_handles_labels()
105
+
106
+ # handler_map = Lg(
107
+ # parent=self.axis, handles=[], labels=[]
108
+ # ).get_legend_handler_map()
109
+ # handlers = dict(zip(handles, [handler_map[type(handle)] for handle in handles]))
110
+
111
+ handler_map = Lg(
112
+ parent=self.axis, handles=[], labels=[]
113
+ ).get_legend_handler_map()
114
+
115
+ handlers = {}
116
+ for handle in handles:
117
+ if type(handle) in handler_map:
118
+ print(handle)
119
+ handlers[handle] = handler_map[type(handle)]
120
+ else:
121
+ # if handle is not in handler_map, pass
122
+ pass
123
+
124
+ return handles, labels, handlers
125
+
126
+ def legend(self) -> Lg:
127
+ """
128
+ Adds a legend to the target axis.
129
+
130
+ Returns
131
+ --------------------
132
+ matplotlib.legend.Legend
133
+ The created legend object.
134
+ """
135
+ _lg = self.axis.legend(*self.args, **self.kwargs)
136
+
137
+ return _lg
138
+
139
+ def legend_handlers(self) -> Lg:
140
+ """
141
+ Adds a legend with custom handles, labels, and handlers to the target axis.
142
+
143
+ Returns
144
+ --------------------
145
+ matplotlib.legend.Legend
146
+ The created legend object with the provided custom handlers.
147
+ """
148
+ _lg = self.axis.legend(
149
+ handles=self.handles,
150
+ labels=self.labels,
151
+ handler_map=self.handlers,
152
+ *self.args,
153
+ **self.kwargs,
154
+ )
155
+
156
+ return _lg
157
+
158
+ def reverse_legend(self) -> Lg:
159
+ """
160
+ Adds a legend to the target axis with reversed order of handles and labels.
161
+
162
+ Returns
163
+ --------------------
164
+ matplotlib.legend.Legend
165
+ The created legend object with reversed order.
166
+ """
167
+
168
+ handles, labels, handlers = self.get_legend_handlers()
169
+ _lg = self.axis.legend(
170
+ handles=handles[::-1],
171
+ labels=labels[::-1],
172
+ handler_map=handlers,
173
+ *self.args,
174
+ **self.kwargs,
175
+ )
176
+ return _lg
177
+
178
+
179
+ class LegendAxes:
180
+ """
181
+ A class to manage legends for all axes in the current Matplotlib figure.
182
+
183
+ Parameters
184
+ --------------------
185
+ *args : Any
186
+ Additional positional arguments for legends.
187
+ **kwargs : Any
188
+ Additional keyword arguments for legends.
189
+
190
+ Attributes
191
+ --------------------
192
+ args : Any
193
+ Positional arguments for legends.
194
+ kwargs : Any
195
+ Keyword arguments for legends.
196
+
197
+ Methods
198
+ --------------------
199
+ legend_axes() -> list[matplotlib.legend.Legend]
200
+ Adds legends to all axes in the current figure.
201
+ """
202
+
203
+ def __init__(self, *args: Any, **kwargs: Any):
204
+ self.args: Any = args
205
+ self.kwargs: Any = kwargs
206
+
207
+ def legend_axes(self) -> list[Lg]:
208
+ """
209
+ Adds legends to all axes in the current Matplotlib figure.
210
+
211
+ Returns
212
+ --------------------
213
+ list[matplotlib.legend.Legend]
214
+ A list of legend objects created for each axis.
215
+ """
216
+ _lg_list = []
217
+ for ax in plt.gcf().axes:
218
+ _lg = ax.legend(*self.args, **self.kwargs)
219
+ _lg_list.append(_lg)
220
+ return _lg_list
221
+
222
+
223
+ @bind_passed_params()
224
+ def legend(axis_target: int | Axes, *args: Any, **kwargs: Any) -> Lg:
225
+ """
226
+ Adds a legend to the specified axis.
227
+
228
+ Parameters
229
+ --------------------
230
+ axis_target : int | Axes
231
+ The target axis for the legend. Can be an axis index or an `Axes` object.
232
+ *args : Any
233
+ Additional positional arguments for the legend.
234
+ **kwargs : Any
235
+ Additional keyword arguments for the legend.
236
+
237
+ Notes
238
+ --------------------
239
+ This function utilizes the `ParamsGetter` to retrieve bound parameters and
240
+ the `CreateClassParams` class to handle the merging of default, configuration,
241
+ and passed parameters.
242
+
243
+ Returns
244
+ --------------------
245
+ matplotlib.legend.Legend
246
+ The created legend object.
247
+
248
+ Examples
249
+ --------------------
250
+ >>> import matplotlib.pyplot as plt
251
+ >>> import numpy as np
252
+ >>> import gsplot as gs
253
+ >>> x = np.linspace(0, 10, 100)
254
+ >>> plt.plot(x, np.sin(x), label="Sine")
255
+ >>> plt.plot(x, np.cos(x), label="Cosine")
256
+ >>> gs.legend(0) # Adds legend to the first axis
257
+ >>> plt.show()
258
+ """
259
+ passed_params: dict[str, Any] = ParamsGetter("passed_params").get_bound_params()
260
+ class_params = CreateClassParams(passed_params).get_class_params()
261
+
262
+ _legend = Legend(
263
+ class_params["axis_target"],
264
+ *class_params["args"],
265
+ **class_params["kwargs"],
266
+ )
267
+ return _legend.legend()
268
+
269
+
270
+ @bind_passed_params()
271
+ def legend_axes(*args: Any, **kwargs: Any) -> list[Lg]:
272
+ """
273
+ Adds legends to all axes in the current Matplotlib figure.
274
+
275
+ Parameters
276
+ --------------------
277
+ *args : Any
278
+ Additional positional arguments for legends.
279
+ **kwargs : Any
280
+ Additional keyword arguments for legends.
281
+
282
+ Notes
283
+ --------------------
284
+ This function utilizes the `ParamsGetter` to retrieve bound parameters and
285
+ the `CreateClassParams` class to handle the merging of default, configuration,
286
+ and passed parameters.
287
+
288
+ Returns
289
+ --------------------
290
+ list[matplotlib.legend.Legend]
291
+ A list of legend objects created for each axis.
292
+
293
+ Examples
294
+ --------------------
295
+ >>> import matplotlib.pyplot as plt
296
+ >>> fig, axes = plt.subplots(2, 1)
297
+ >>> import gsplot as gs
298
+ >>> axes[0].plot([1, 2, 3], [4, 5, 6], label="Line 1")
299
+ >>> axes[1].plot([1, 2, 3], [6, 5, 4], label="Line 2")
300
+ >>> gs.legend_axes() # Adds legends to all axes
301
+ >>> plt.show()
302
+ """
303
+ passed_params: dict[str, Any] = ParamsGetter("passed_params").get_bound_params()
304
+ class_params = CreateClassParams(passed_params).get_class_params()
305
+
306
+ _legend_axes = LegendAxes(
307
+ *class_params["args"],
308
+ **class_params["kwargs"],
309
+ )
310
+ return _legend_axes.legend_axes()
311
+
312
+
313
+ @bind_passed_params()
314
+ def legend_handlers(
315
+ axis_target: int | Axes,
316
+ handles: list[Any] | None = None,
317
+ labels: list[str] | None = None,
318
+ handlers: dict | None = None,
319
+ *args: Any,
320
+ **kwargs: Any
321
+ ) -> Lg:
322
+ """
323
+ Adds a legend with custom handles, labels, and handlers to the specified axis.
324
+
325
+ Parameters
326
+ --------------------
327
+ axis_target : int | Axes
328
+ The target axis for the legend. Can be an axis index or an `Axes` object.
329
+ handles : list[Any], optional
330
+ A list of custom handles for the legend.
331
+ labels : list[str], optional
332
+ A list of custom labels for the legend.
333
+ handlers : dict, optional
334
+ A dictionary of custom legend handlers.
335
+ *args : Any
336
+ Additional positional arguments for the legend.
337
+ **kwargs : Any
338
+ Additional keyword arguments for the legend.
339
+
340
+ Notes
341
+ --------------------
342
+ This function utilizes the `ParamsGetter` to retrieve bound parameters and
343
+ the `CreateClassParams` class to handle the merging of default, configuration,
344
+ and passed parameters.
345
+
346
+ Returns
347
+ --------------------
348
+ matplotlib.legend.Legend
349
+ The created legend object with the provided custom handlers.
350
+
351
+ Examples
352
+ --------------------
353
+ >>> import matplotlib.pyplot as plt
354
+ >>> from matplotlib.lines import Line2D
355
+ >>> import gsplot as gs
356
+ >>> fig, ax = plt.subplots()
357
+ >>> ax.plot([0, 1], [0, 1], label="Line A")
358
+ >>> custom_handle = [Line2D([0], [0], color="r", lw=2)]
359
+ >>> gs.legend_handlers(0, handles=custom_handle, labels=["Custom Line"])
360
+ >>> plt.show()
361
+ """
362
+ passed_params: dict[str, Any] = ParamsGetter("passed_params").get_bound_params()
363
+ class_params = CreateClassParams(passed_params).get_class_params()
364
+
365
+ _legend = Legend(
366
+ class_params["axis_target"],
367
+ class_params["handles"],
368
+ class_params["labels"],
369
+ class_params["handlers"],
370
+ *class_params["args"],
371
+ **class_params["kwargs"],
372
+ )
373
+ return _legend.legend_handlers()
374
+
375
+
376
+ @bind_passed_params()
377
+ def legend_reverse(
378
+ axis_target: int | Axes,
379
+ handles: list[Any] | None = None,
380
+ labels: list[str] | None = None,
381
+ handlers: dict | None = None,
382
+ *args: Any,
383
+ **kwargs: Any
384
+ ) -> Lg:
385
+ """
386
+ Adds a legend to the specified axis with reversed order of handles and labels.
387
+
388
+ Parameters
389
+ --------------------
390
+ axis_target : int | Axes
391
+ The target axis for the legend. Can be an axis index or an `Axes` object.
392
+ handles : list[Any], optional
393
+ A list of custom handles for the legend.
394
+ labels : list[str], optional
395
+ A list of custom labels for the legend.
396
+ handlers : dict, optional
397
+ A dictionary of custom legend handlers.
398
+ *args : Any
399
+ Additional positional arguments for the legend.
400
+ **kwargs : Any
401
+ Additional keyword arguments for the legend.
402
+
403
+ Notes
404
+ --------------------
405
+ This function utilizes the `ParamsGetter` to retrieve bound parameters and
406
+ the `CreateClassParams` class to handle the merging of default, configuration,
407
+ and passed parameters.
408
+
409
+ Returns
410
+ --------------------
411
+ matplotlib.legend.Legend
412
+ The created legend object with reversed order.
413
+
414
+ Examples
415
+ --------------------
416
+ >>> import matplotlib.pyplot as plt
417
+ >>> x = [1, 2, 3]
418
+ >>> y1 = [4, 5, 6]
419
+ >>> y2 = [6, 5, 4]
420
+ >>> plt.plot(x, y1, label="Line 1")
421
+ >>> plt.plot(x, y2, label="Line 2")
422
+ >>> legend_reverse(0) # Reverses the legend order
423
+ >>> plt.show()
424
+ """
425
+ passed_params: dict[str, Any] = ParamsGetter("passed_params").get_bound_params()
426
+ class_params = CreateClassParams(passed_params).get_class_params()
427
+
428
+ _legend = Legend(
429
+ class_params["axis_target"],
430
+ class_params["handles"],
431
+ class_params["labels"],
432
+ class_params["handlers"],
433
+ *class_params["args"],
434
+ **class_params["kwargs"],
435
+ )
436
+ return _legend.reverse_legend()
437
+
438
+
439
+ def legend_get_handlers(
440
+ axis_target: int | Axes,
441
+ ) -> tuple:
442
+ """
443
+ Retrieves the legend handles, labels, and associated handlers for the specified axis.
444
+
445
+ Parameters
446
+ --------------------
447
+ axis_target : int | Axes
448
+ The target axis for retrieving the legend handlers. Can be an axis index or an `Axes` object.
449
+
450
+ Returns
451
+ --------------------
452
+ tuple
453
+ - handles: The list of legend handles.
454
+ - labels: The list of legend labels.
455
+ - handlers: A dictionary mapping handles to their legend handlers.
456
+
457
+ Examples
458
+ --------------------
459
+ >>> import matplotlib.pyplot as plt
460
+ >>> import gsplot as gs
461
+ >>> fig, ax = plt.subplots()
462
+ >>> ax.plot([0, 1], [0, 1], label="Line A")
463
+ >>> ax.plot([1, 0], [0, 1], label="Line B")
464
+ >>> handles, labels, handlers = gs.legend_get_handlers(0)
465
+ >>> print("Handles:", handles)
466
+ >>> print("Labels:", labels)
467
+ >>> print("Handlers:", handlers)
468
+ """
469
+ return Legend(axis_target).get_legend_handlers()