FazBrowse GitHub Viewer
|
Trending
|
URL:
|
Home
Tools:
[Download Repo ZIP]
[View Raw Code]
[Original HTTPS Page]
matplotlib/lib/matplotlib/gridspec.py at v3.11.2 · matplotlib/matplotlib · GitHub
matplotlib
/
matplotlib
Public
Uh oh!
There was an error while loading.
Please reload this page
.
Notifications
You must be signed in to change notification settings
Fork
8.5k
Star
23.3k
Code
Issues
1.1k
Pull requests
430
Actions
Projects
Wiki
Security and quality
0
Insights
Additional navigation options
Code
Issues
Pull requests
Actions
Projects
Wiki
Security and quality
Insights
Expand file tree
Breadcrumbs
matplotlib
/
lib
/
matplotlib
/
gridspec.py
Copy path
More file actions
More file actions
Latest commit
History
History
History
807 lines (688 loc) · 29.8 KB
Breadcrumbs
matplotlib
/
lib
/
matplotlib
/
gridspec.py
Copy path
File metadata and controls
807 lines (688 loc) · 29.8 KB
Raw
Copy raw file
Download raw file
Open symbols panel
Edit and raw actions
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
r"""
:mod:`~matplotlib.gridspec` contains classes that help to layout multiple
`~.axes.Axes` in a grid-like pattern within a figure.
The `GridSpec` specifies the overall grid structure. Individual cells within
the grid are referenced by `SubplotSpec`\s.
Often, users need not access this module directly, and can use higher-level
methods like `~.pyplot.subplots`, `~.pyplot.subplot_mosaic` and
`~.Figure.subfigures`. See the tutorial :ref:`arranging_axes` for a guide.
"""
import
copy
import
logging
from
numbers
import
Integral
import
numpy
as
np
import
matplotlib
as
mpl
from
matplotlib
import
_api
,
_pylab_helpers
,
_tight_layout
from
matplotlib
.
_api
import
UNSET
as
_UNSET
from
matplotlib
.
transforms
import
Bbox
_log
=
logging
.
getLogger
(
__name__
)
class
GridSpecBase
:
"""
A base class of GridSpec that specifies the geometry of the grid
that a subplot will be placed.
"""
def
__init__
(
self
,
nrows
,
ncols
,
height_ratios
=
None
,
width_ratios
=
None
):
"""
Parameters
----------
nrows, ncols : int
The number of rows and columns of the grid.
width_ratios : array-like of length *ncols*, optional
Defines the relative widths of the columns. Each column gets a
relative width of ``width_ratios[i] / sum(width_ratios)``.
If not given, all columns will have the same width.
height_ratios : array-like of length *nrows*, optional
Defines the relative heights of the rows. Each row gets a
relative height of ``height_ratios[i] / sum(height_ratios)``.
If not given, all rows will have the same height.
"""
if
not
isinstance
(
nrows
,
Integral
)
or
nrows
<=
0
:
raise
ValueError
(
f"Number of rows must be a positive integer, not
{
nrows
!r
}
"
)
if
not
isinstance
(
ncols
,
Integral
)
or
ncols
<=
0
:
raise
ValueError
(
f"Number of columns must be a positive integer, not
{
ncols
!r
}
"
)
self
.
_nrows
,
self
.
_ncols
=
nrows
,
ncols
self
.
set_height_ratios
(
height_ratios
)
self
.
set_width_ratios
(
width_ratios
)
def
__repr__
(
self
):
height_arg
=
(
f', height_ratios=
{
self
.
_row_height_ratios
!r
}
'
if
len
(
set
(
self
.
_row_height_ratios
))
!=
1
else
''
)
width_arg
=
(
f', width_ratios=
{
self
.
_col_width_ratios
!r
}
'
if
len
(
set
(
self
.
_col_width_ratios
))
!=
1
else
''
)
return
'{clsname}({nrows}, {ncols}{optionals})'
.
format
(
clsname
=
self
.
__class__
.
__name__
,
nrows
=
self
.
_nrows
,
ncols
=
self
.
_ncols
,
optionals
=
height_arg
+
width_arg
,
)
nrows
=
property
(
lambda
self
:
self
.
_nrows
,
doc
=
"The number of rows in the grid."
)
ncols
=
property
(
lambda
self
:
self
.
_ncols
,
doc
=
"The number of columns in the grid."
)
def
get_geometry
(
self
):
"""
Return a tuple containing the number of rows and columns in the grid.
"""
return
self
.
_nrows
,
self
.
_ncols
def
get_subplot_params
(
self
,
figure
=
None
):
# Must be implemented in subclasses
pass
def
new_subplotspec
(
self
,
loc
,
rowspan
=
1
,
colspan
=
1
):
"""
Create and return a `.SubplotSpec` instance.
Parameters
----------
loc : (int, int)
The position of the subplot in the grid as
``(row_index, column_index)``.
rowspan, colspan : int, default: 1
The number of rows and columns the subplot should span in the grid.
"""
loc1
,
loc2
=
loc
subplotspec
=
self
[
loc1
:
loc1
+
rowspan
,
loc2
:
loc2
+
colspan
]
return
subplotspec
def
set_width_ratios
(
self
,
width_ratios
):
"""
Set the relative widths of the columns.
*width_ratios* must be of length *ncols*. Each column gets a relative
width of ``width_ratios[i] / sum(width_ratios)``.
"""
if
width_ratios
is
None
:
width_ratios
=
[
1
]
*
self
.
_ncols
elif
len
(
width_ratios
)
!=
self
.
_ncols
:
raise
ValueError
(
'Expected the given number of width ratios to '
'match the number of columns of the grid'
)
self
.
_col_width_ratios
=
width_ratios
def
get_width_ratios
(
self
):
"""
Return the width ratios.
This is *None* if no width ratios have been set explicitly.
"""
return
self
.
_col_width_ratios
def
set_height_ratios
(
self
,
height_ratios
):
"""
Set the relative heights of the rows.
*height_ratios* must be of length *nrows*. Each row gets a relative
height of ``height_ratios[i] / sum(height_ratios)``.
"""
if
height_ratios
is
None
:
height_ratios
=
[
1
]
*
self
.
_nrows
elif
len
(
height_ratios
)
!=
self
.
_nrows
:
raise
ValueError
(
'Expected the given number of height ratios to '
'match the number of rows of the grid'
)
self
.
_row_height_ratios
=
height_ratios
def
get_height_ratios
(
self
):
"""
Return the height ratios.
This is *None* if no height ratios have been set explicitly.
"""
return
self
.
_row_height_ratios
def
get_grid_positions
(
self
,
fig
):
"""
Return the positions of the grid cells in figure coordinates.
Parameters
----------
fig : `~matplotlib.figure.Figure`
The figure the grid should be applied to. The subplot parameters
(margins and spacing between subplots) are taken from *fig*.
Returns
-------
bottoms, tops, lefts, rights : array
The bottom, top, left, right positions of the grid cells in
figure coordinates.
"""
nrows
,
ncols
=
self
.
get_geometry
()
subplot_params
=
self
.
get_subplot_params
(
fig
)
left
=
subplot_params
.
left
right
=
subplot_params
.
right
bottom
=
subplot_params
.
bottom
top
=
subplot_params
.
top
wspace
=
subplot_params
.
wspace
hspace
=
subplot_params
.
hspace
tot_width
=
right
-
left
tot_height
=
top
-
bottom
# calculate accumulated heights of columns
cell_h
=
tot_height
/
(
nrows
+
hspace
*
(
nrows
-
1
))
sep_h
=
hspace
*
cell_h
norm
=
cell_h
*
nrows
/
sum
(
self
.
_row_height_ratios
)
cell_heights
=
[
r
*
norm
for
r
in
self
.
_row_height_ratios
]
sep_heights
=
[
0
]
+
([
sep_h
]
*
(
nrows
-
1
))
cell_hs
=
np
.
cumsum
(
np
.
column_stack
([
sep_heights
,
cell_heights
]).
flat
)
# calculate accumulated widths of rows
cell_w
=
tot_width
/
(
ncols
+
wspace
*
(
ncols
-
1
))
sep_w
=
wspace
*
cell_w
norm
=
cell_w
*
ncols
/
sum
(
self
.
_col_width_ratios
)
cell_widths
=
[
r
*
norm
for
r
in
self
.
_col_width_ratios
]
sep_widths
=
[
0
]
+
([
sep_w
]
*
(
ncols
-
1
))
cell_ws
=
np
.
cumsum
(
np
.
column_stack
([
sep_widths
,
cell_widths
]).
flat
)
fig_tops
,
fig_bottoms
=
(
top
-
cell_hs
).
reshape
((
-
1
,
2
)).
T
fig_lefts
,
fig_rights
=
(
left
+
cell_ws
).
reshape
((
-
1
,
2
)).
T
return
fig_bottoms
,
fig_tops
,
fig_lefts
,
fig_rights
@
staticmethod
def
_check_gridspec_exists
(
figure
,
nrows
,
ncols
):
"""
Check if the figure already has a gridspec with these dimensions,
or create a new one
"""
for
ax
in
figure
.
get_axes
():
gs
=
ax
.
get_gridspec
()
if
gs
is
not
None
:
if
hasattr
(
gs
,
'get_topmost_subplotspec'
):
# This is needed for colorbar gridspec layouts.
# This is probably OK because this whole logic tree
# is for when the user is doing simple things with the
# add_subplot command. For complicated layouts
# like subgridspecs the proper gridspec is passed in...
gs
=
gs
.
get_topmost_subplotspec
().
get_gridspec
()
if
gs
.
get_geometry
()
==
(
nrows
,
ncols
):
return
gs
# else gridspec not found:
return
GridSpec
(
nrows
,
ncols
,
figure
=
figure
)
def
__getitem__
(
self
,
key
):
"""Create and return a `.SubplotSpec` instance."""
nrows
,
ncols
=
self
.
get_geometry
()
def
_normalize
(
key
,
size
,
axis
):
# Includes last index.
orig_key
=
key
if
isinstance
(
key
,
slice
):
start
,
stop
,
_
=
key
.
indices
(
size
)
if
stop
>
start
:
return
start
,
stop
-
1
raise
IndexError
(
"GridSpec slice would result in no space "
"allocated for subplot"
)
else
:
if
key
<
0
:
key
=
key
+
size
if
0
<=
key
<
size
:
return
key
,
key
elif
axis
is
not
None
:
raise
IndexError
(
f"index
{
orig_key
}
is out of bounds for "
f"axis
{
axis
}
with size
{
size
}
"
)
else
:
# flat index
raise
IndexError
(
f"index
{
orig_key
}
is out of bounds for "
f"GridSpec with size
{
size
}
"
)
if
isinstance
(
key
,
tuple
):
try
:
k1
,
k2
=
key
except
ValueError
as
err
:
raise
ValueError
(
"Unrecognized subplot spec"
)
from
err
num1
,
num2
=
np
.
ravel_multi_index
(
[
_normalize
(
k1
,
nrows
,
0
),
_normalize
(
k2
,
ncols
,
1
)],
(
nrows
,
ncols
))
else
:
# Single key
num1
,
num2
=
_normalize
(
key
,
nrows
*
ncols
,
None
)
return
SubplotSpec
(
self
,
num1
,
num2
)
def
subplots
(
self
,
*
,
sharex
=
False
,
sharey
=
False
,
squeeze
=
True
,
subplot_kw
=
None
):
"""
Add all subplots specified by this `GridSpec` to its parent figure.
See `.Figure.subplots` for detailed documentation.
"""
figure
=
self
.
figure
if
figure
is
None
:
raise
ValueError
(
"GridSpec.subplots() only works for GridSpecs "
"created with a parent figure"
)
if
not
isinstance
(
sharex
,
str
):
sharex
=
"all"
if
sharex
else
"none"
if
not
isinstance
(
sharey
,
str
):
sharey
=
"all"
if
sharey
else
"none"
_api
.
check_in_list
([
"all"
,
"row"
,
"col"
,
"none"
,
False
,
True
],
sharex
=
sharex
,
sharey
=
sharey
)
if
subplot_kw
is
None
:
subplot_kw
=
{}
# don't mutate kwargs passed by user...
subplot_kw
=
subplot_kw
.
copy
()
# Create array to hold all Axes.
axarr
=
np
.
empty
((
self
.
_nrows
,
self
.
_ncols
),
dtype
=
object
)
for
row
in
range
(
self
.
_nrows
):
for
col
in
range
(
self
.
_ncols
):
shared_with
=
{
"none"
:
None
,
"all"
:
axarr
[
0
,
0
],
"row"
:
axarr
[
row
,
0
],
"col"
:
axarr
[
0
,
col
]}
subplot_kw
[
"sharex"
]
=
shared_with
[
sharex
]
subplot_kw
[
"sharey"
]
=
shared_with
[
sharey
]
axarr
[
row
,
col
]
=
figure
.
add_subplot
(
self
[
row
,
col
],
**
subplot_kw
)
# turn off redundant tick labeling
if
sharex
in
[
"col"
,
"all"
]:
for
ax
in
axarr
.
flat
:
ax
.
_label_outer_xaxis
(
skip_non_rectangular_axes
=
True
)
if
sharey
in
[
"row"
,
"all"
]:
for
ax
in
axarr
.
flat
:
ax
.
_label_outer_yaxis
(
skip_non_rectangular_axes
=
True
)
if
squeeze
:
# Discarding unneeded dimensions that equal 1. If we only have one
# subplot, just return it instead of a 1-element array.
return
axarr
.
item
()
if
axarr
.
size
==
1
else
axarr
.
squeeze
()
else
:
# Returned axis array will be always 2-d, even if nrows=ncols=1.
return
axarr
class
GridSpec
(
GridSpecBase
):
"""
A grid layout to place subplots within a figure.
The location of the grid cells is determined in a similar way to
`.SubplotParams` using *left*, *right*, *top*, *bottom*, *wspace*
and *hspace*.
Indexing a GridSpec instance returns a `.SubplotSpec`.
"""
def
__init__
(
self
,
nrows
,
ncols
,
figure
=
None
,
left
=
None
,
bottom
=
None
,
right
=
None
,
top
=
None
,
wspace
=
None
,
hspace
=
None
,
width_ratios
=
None
,
height_ratios
=
None
):
"""
Parameters
----------
nrows, ncols : int
The number of rows and columns of the grid.
figure : `.Figure`, optional
Only used for constrained layout to create a proper layoutgrid.
left, right, top, bottom : float, optional
Extent of the subplots as a fraction of figure width or height.
Left cannot be larger than right, and bottom cannot be larger than
top. If not given, the values will be inferred from a figure or
rcParams at draw time. See also `GridSpec.get_subplot_params`.
wspace : float, optional
The amount of width reserved for space between subplots,
expressed as a fraction of the average axis width.
If not given, the values will be inferred from a figure or
rcParams when necessary. See also `GridSpec.get_subplot_params`.
hspace : float, optional
The amount of height reserved for space between subplots,
expressed as a fraction of the average axis height.
If not given, the values will be inferred from a figure or
rcParams when necessary. See also `GridSpec.get_subplot_params`.
width_ratios : array-like of length *ncols*, optional
Defines the relative widths of the columns. Each column gets a
relative width of ``width_ratios[i] / sum(width_ratios)``.
If not given, all columns will have the same width.
height_ratios : array-like of length *nrows*, optional
Defines the relative heights of the rows. Each row gets a
relative height of ``height_ratios[i] / sum(height_ratios)``.
If not given, all rows will have the same height.
"""
self
.
left
=
left
self
.
bottom
=
bottom
self
.
right
=
right
self
.
top
=
top
self
.
wspace
=
wspace
self
.
hspace
=
hspace
self
.
figure
=
figure
super
().
__init__
(
nrows
,
ncols
,
width_ratios
=
width_ratios
,
height_ratios
=
height_ratios
)
_AllowedKeys
=
[
"left"
,
"bottom"
,
"right"
,
"top"
,
"wspace"
,
"hspace"
]
def
update
(
self
,
*
,
left
=
_UNSET
,
bottom
=
_UNSET
,
right
=
_UNSET
,
top
=
_UNSET
,
wspace
=
_UNSET
,
hspace
=
_UNSET
):
"""
Update the subplot parameters of the grid.
Parameters that are not explicitly given are not changed. Setting a
parameter to *None* resets it to :rc:`figure.subplot.*`.
Parameters
----------
left, right, top, bottom : float or None, optional
Extent of the subplots as a fraction of figure width or height.
wspace, hspace : float or None, optional
Spacing between the subplots as a fraction of the average subplot
width / height.
"""
if
left
is
not
_UNSET
:
self
.
left
=
left
if
bottom
is
not
_UNSET
:
self
.
bottom
=
bottom
if
right
is
not
_UNSET
:
self
.
right
=
right
if
top
is
not
_UNSET
:
self
.
top
=
top
if
wspace
is
not
_UNSET
:
self
.
wspace
=
wspace
if
hspace
is
not
_UNSET
:
self
.
hspace
=
hspace
for
figmanager
in
_pylab_helpers
.
Gcf
.
figs
.
values
():
for
ax
in
figmanager
.
canvas
.
figure
.
axes
:
if
ax
.
get_subplotspec
()
is
not
None
:
ss
=
ax
.
get_subplotspec
().
get_topmost_subplotspec
()
if
ss
.
get_gridspec
()
==
self
:
fig
=
ax
.
get_figure
(
root
=
False
)
ax
.
_set_position
(
ax
.
get_subplotspec
().
get_position
(
fig
))
def
get_subplot_params
(
self
,
figure
=
None
):
"""
Return the `.SubplotParams` for the GridSpec.
In order of precedence the values are taken from
- non-*None* attributes of the GridSpec
- the provided *figure*
- :rc:`figure.subplot.*`
Note that the ``figure`` attribute of the GridSpec is always ignored.
"""
if
figure
is
None
:
kw
=
{
k
:
mpl
.
rcParams
[
"figure.subplot."
+
k
]
for
k
in
self
.
_AllowedKeys
}
subplotpars
=
SubplotParams
(
**
kw
)
else
:
subplotpars
=
copy
.
copy
(
figure
.
subplotpars
)
subplotpars
.
update
(
**
{
k
:
getattr
(
self
,
k
)
for
k
in
self
.
_AllowedKeys
})
return
subplotpars
def
locally_modified_subplot_params
(
self
):
"""
Return a list of the names of the subplot parameters explicitly set
in the GridSpec.
This is a subset of the attributes of `.SubplotParams`.
"""
return
[
k
for
k
in
self
.
_AllowedKeys
if
getattr
(
self
,
k
)]
def
tight_layout
(
self
,
figure
,
renderer
=
None
,
pad
=
1.08
,
h_pad
=
None
,
w_pad
=
None
,
rect
=
None
):
"""
Adjust subplot parameters to give specified padding.
Parameters
----------
figure : `.Figure`
The figure.
renderer : `.RendererBase` subclass, optional
The renderer to be used.
pad : float
Padding between the figure edge and the edges of subplots, as a
fraction of the font-size.
h_pad, w_pad : float, optional
Padding (height/width) between edges of adjacent subplots.
Defaults to *pad*.
rect : tuple (left, bottom, right, top), default: None
(left, bottom, right, top) rectangle in normalized figure
coordinates that the whole subplots area (including labels) will
fit into. Default (None) is the whole figure.
"""
if
renderer
is
None
:
renderer
=
figure
.
_get_renderer
()
kwargs
=
_tight_layout
.
get_tight_layout_figure
(
figure
,
figure
.
axes
,
_tight_layout
.
get_subplotspec_list
(
figure
.
axes
,
grid_spec
=
self
),
renderer
,
pad
=
pad
,
h_pad
=
h_pad
,
w_pad
=
w_pad
,
rect
=
rect
)
if
kwargs
:
self
.
update
(
**
kwargs
)
class
GridSpecFromSubplotSpec
(
GridSpecBase
):
"""
GridSpec whose subplot layout parameters are inherited from the
location specified by a given SubplotSpec.
"""
def
__init__
(
self
,
nrows
,
ncols
,
subplot_spec
,
wspace
=
None
,
hspace
=
None
,
height_ratios
=
None
,
width_ratios
=
None
):
"""
Parameters
----------
nrows, ncols : int
Number of rows and number of columns of the grid.
subplot_spec : SubplotSpec
Spec from which the layout parameters are inherited.
wspace, hspace : float, optional
See `GridSpec` for more details. If not specified default values
(from the figure or rcParams) are used.
height_ratios : array-like of length *nrows*, optional
See `GridSpecBase` for details.
width_ratios : array-like of length *ncols*, optional
See `GridSpecBase` for details.
"""
self
.
_wspace
=
wspace
self
.
_hspace
=
hspace
if
isinstance
(
subplot_spec
,
SubplotSpec
):
self
.
_subplot_spec
=
subplot_spec
else
:
raise
TypeError
(
"subplot_spec must be type SubplotSpec, "
"usually from GridSpec, or axes.get_subplotspec."
)
self
.
figure
=
self
.
_subplot_spec
.
get_gridspec
().
figure
super
().
__init__
(
nrows
,
ncols
,
width_ratios
=
width_ratios
,
height_ratios
=
height_ratios
)
def
get_subplot_params
(
self
,
figure
=
None
):
"""Return a dictionary of subplot layout parameters."""
hspace
=
(
self
.
_hspace
if
self
.
_hspace
is
not
None
else
figure
.
subplotpars
.
hspace
if
figure
is
not
None
else
mpl
.
rcParams
[
"figure.subplot.hspace"
])
wspace
=
(
self
.
_wspace
if
self
.
_wspace
is
not
None
else
figure
.
subplotpars
.
wspace
if
figure
is
not
None
else
mpl
.
rcParams
[
"figure.subplot.wspace"
])
figbox
=
self
.
_subplot_spec
.
get_position
(
figure
)
left
,
bottom
,
right
,
top
=
figbox
.
extents
return
SubplotParams
(
left
=
left
,
right
=
right
,
bottom
=
bottom
,
top
=
top
,
wspace
=
wspace
,
hspace
=
hspace
)
def
get_topmost_subplotspec
(
self
):
"""
Return the topmost `.SubplotSpec` instance associated with the subplot.
"""
return
self
.
_subplot_spec
.
get_topmost_subplotspec
()
class
SubplotSpec
:
"""
The location of a subplot in a `GridSpec`.
.. note::
Likely, you will never instantiate a `SubplotSpec` yourself. Instead,
you will typically obtain one from a `GridSpec` using item-access.
Parameters
----------
gridspec : `~matplotlib.gridspec.GridSpec`
The GridSpec, which the subplot is referencing.
num1, num2 : int
The subplot will occupy the *num1*-th cell of the given
*gridspec*. If *num2* is provided, the subplot will span between
*num1*-th cell and *num2*-th cell **inclusive**.
The index starts from 0.
"""
def
__init__
(
self
,
gridspec
,
num1
,
num2
=
None
):
self
.
_gridspec
=
gridspec
self
.
num1
=
num1
self
.
num2
=
num2
def
__repr__
(
self
):
return
(
f"
{
self
.
get_gridspec
()
}
["
f"
{
self
.
rowspan
.
start
}
:
{
self
.
rowspan
.
stop
}
, "
f"
{
self
.
colspan
.
start
}
:
{
self
.
colspan
.
stop
}
]"
)
@
staticmethod
def
_from_subplot_args
(
figure
,
args
):
"""
Construct a `.SubplotSpec` from a parent `.Figure` and either
- a `.SubplotSpec` -- returned as is;
- one or three numbers -- a MATLAB-style subplot specifier.
"""
if
len
(
args
)
==
1
:
arg
,
=
args
if
isinstance
(
arg
,
SubplotSpec
):
return
arg
elif
not
isinstance
(
arg
,
Integral
):
raise
ValueError
(
f"Single argument to subplot must be a three-digit "
f"integer, not
{
arg
!r
}
"
)
try
:
rows
,
cols
,
num
=
map
(
int
,
str
(
arg
))
except
ValueError
:
raise
ValueError
(
f"Single argument to subplot must be a three-digit "
f"integer, not
{
arg
!r
}
"
)
from
None
elif
len
(
args
)
==
3
:
rows
,
cols
,
num
=
args
else
:
raise
_api
.
nargs_error
(
"subplot"
,
takes
=
"1 or 3"
,
given
=
len
(
args
))
gs
=
GridSpec
.
_check_gridspec_exists
(
figure
,
rows
,
cols
)
if
gs
is
None
:
gs
=
GridSpec
(
rows
,
cols
,
figure
=
figure
)
if
isinstance
(
num
,
tuple
)
and
len
(
num
)
==
2
:
if
not
all
(
isinstance
(
n
,
Integral
)
for
n
in
num
):
raise
ValueError
(
f"Subplot specifier tuple must contain integers, not
{
num
}
"
)
i
,
j
=
num
else
:
if
not
isinstance
(
num
,
Integral
)
or
num
<
1
or
num
>
rows
*
cols
:
raise
ValueError
(
f"num must be an integer with 1 <= num <=
{
rows
*
cols
}
, "
f"not
{
num
!r
}
"
)
i
=
j
=
num
return
gs
[
i
-
1
:
j
]
# num2 is a property only to handle the case where it is None and someone
# mutates num1.
@
property
def
num2
(
self
):
return
self
.
num1
if
self
.
_num2
is
None
else
self
.
_num2
@
num2
.
setter
def
num2
(
self
,
value
):
self
.
_num2
=
value
def
get_gridspec
(
self
):
return
self
.
_gridspec
def
get_geometry
(
self
):
"""
Return the subplot geometry as tuple ``(n_rows, n_cols, start, stop)``.
The indices *start* and *stop* define the range of the subplot within
the `GridSpec`. *stop* is inclusive (i.e. for a single cell
``start == stop``).
"""
rows
,
cols
=
self
.
get_gridspec
().
get_geometry
()
return
rows
,
cols
,
self
.
num1
,
self
.
num2
@
property
def
rowspan
(
self
):
"""The rows spanned by this subplot, as a `range` object."""
ncols
=
self
.
get_gridspec
().
ncols
return
range
(
self
.
num1
//
ncols
,
self
.
num2
//
ncols
+
1
)
@
property
def
colspan
(
self
):
"""The columns spanned by this subplot, as a `range` object."""
ncols
=
self
.
get_gridspec
().
ncols
# We explicitly support num2 referring to a column on num1's *left*, so
# we must sort the column indices here so that the range makes sense.
c1
,
c2
=
sorted
([
self
.
num1
%
ncols
,
self
.
num2
%
ncols
])
return
range
(
c1
,
c2
+
1
)
def
is_first_row
(
self
):
return
self
.
rowspan
.
start
==
0
def
is_last_row
(
self
):
return
self
.
rowspan
.
stop
==
self
.
get_gridspec
().
nrows
def
is_first_col
(
self
):
return
self
.
colspan
.
start
==
0
def
is_last_col
(
self
):
return
self
.
colspan
.
stop
==
self
.
get_gridspec
().
ncols
def
get_position
(
self
,
figure
):
"""
Update the subplot position from ``figure.subplotpars``.
"""
gridspec
=
self
.
get_gridspec
()
nrows
,
ncols
=
gridspec
.
get_geometry
()
rows
,
cols
=
np
.
unravel_index
([
self
.
num1
,
self
.
num2
], (
nrows
,
ncols
))
fig_bottoms
,
fig_tops
,
fig_lefts
,
fig_rights
=
\
gridspec
.
get_grid_positions
(
figure
)
fig_bottom
=
fig_bottoms
[
rows
].
min
()
fig_top
=
fig_tops
[
rows
].
max
()
fig_left
=
fig_lefts
[
cols
].
min
()
fig_right
=
fig_rights
[
cols
].
max
()
return
Bbox
.
from_extents
(
fig_left
,
fig_bottom
,
fig_right
,
fig_top
)
def
get_topmost_subplotspec
(
self
):
"""
Return the topmost `SubplotSpec` instance associated with the subplot.
"""
gridspec
=
self
.
get_gridspec
()
if
hasattr
(
gridspec
,
"get_topmost_subplotspec"
):
return
gridspec
.
get_topmost_subplotspec
()
else
:
return
self
def
__eq__
(
self
,
other
):
"""
Two SubplotSpecs are considered equal if they refer to the same
position(s) in the same `GridSpec`.
"""
# other may not even have the attributes we are checking.
return
((
self
.
_gridspec
,
self
.
num1
,
self
.
num2
)
==
(
getattr
(
other
,
"_gridspec"
,
object
()),
getattr
(
other
,
"num1"
,
object
()),
getattr
(
other
,
"num2"
,
object
())))
def
__hash__
(
self
):
return
hash
((
self
.
_gridspec
,
self
.
num1
,
self
.
num2
))
def
subgridspec
(
self
,
nrows
,
ncols
,
**
kwargs
):
"""
Create a GridSpec within this subplot.
The created `.GridSpecFromSubplotSpec` will have this `SubplotSpec` as
a parent.
Parameters
----------
nrows : int
Number of rows in grid.
ncols : int
Number of columns in grid.
Returns
-------
`.GridSpecFromSubplotSpec`
Other Parameters
----------------
**kwargs
All other parameters are passed to `.GridSpecFromSubplotSpec`.
See Also
--------
matplotlib.pyplot.subplots
Examples
--------
Adding three subplots in the space occupied by a single subplot::
fig = plt.figure()
gs0 = fig.add_gridspec(3, 1)
ax1 = fig.add_subplot(gs0[0])
ax2 = fig.add_subplot(gs0[1])
gssub = gs0[2].subgridspec(1, 3)
for i in range(3):
fig.add_subplot(gssub[0, i])
"""
return
GridSpecFromSubplotSpec
(
nrows
,
ncols
,
self
,
**
kwargs
)
class
SubplotParams
:
"""
Parameters defining the positioning of a subplots grid in a figure.
"""
def
__init__
(
self
,
left
=
None
,
bottom
=
None
,
right
=
None
,
top
=
None
,
wspace
=
None
,
hspace
=
None
):
"""
Defaults are given by :rc:`figure.subplot.[name]`.
Parameters
----------
left : float, optional
The position of the left edge of the subplots,
as a fraction of the figure width.
right : float, optional
The position of the right edge of the subplots,
as a fraction of the figure width.
bottom : float, optional
The position of the bottom edge of the subplots,
as a fraction of the figure height.
top : float, optional
The position of the top edge of the subplots,
as a fraction of the figure height.
wspace : float, optional
The width of the padding between subplots,
as a fraction of the average Axes width.
hspace : float, optional
The height of the padding between subplots,
as a fraction of the average Axes height.
"""
for
key
in
[
"left"
,
"bottom"
,
"right"
,
"top"
,
"wspace"
,
"hspace"
]:
setattr
(
self
,
key
,
mpl
.
rcParams
[
f"figure.subplot.
{
key
}
"
])
self
.
update
(
left
,
bottom
,
right
,
top
,
wspace
,
hspace
)
def
update
(
self
,
left
=
None
,
bottom
=
None
,
right
=
None
,
top
=
None
,
wspace
=
None
,
hspace
=
None
):
"""
Update the dimensions of the passed parameters. *None* means unchanged.
"""
if
((
left
if
left
is
not
None
else
self
.
left
)
>=
(
right
if
right
is
not
None
else
self
.
right
)):
raise
ValueError
(
'left cannot be >= right'
)
if
((
bottom
if
bottom
is
not
None
else
self
.
bottom
)
>=
(
top
if
top
is
not
None
else
self
.
top
)):
raise
ValueError
(
'bottom cannot be >= top'
)
if
left
is
not
None
:
self
.
left
=
left
if
right
is
not
None
:
self
.
right
=
right
if
bottom
is
not
None
:
self
.
bottom
=
bottom
if
top
is
not
None
:
self
.
top
=
top
if
wspace
is
not
None
:
self
.
wspace
=
wspace
if
hspace
is
not
None
:
self
.
hspace
=
hspace
def
reset
(
self
):
"""Restore the subplot positioning parameters to the default rcParams values"""
for
key
in
self
.
to_dict
():
setattr
(
self
,
key
,
mpl
.
rcParams
[
f'figure.subplot.
{
key
}
'
])
def
to_dict
(
self
):
"""Return a copy of the subplot parameters as a dict."""
return
self
.
__dict__
.
copy
()
Back
|
FazBrowse Home
|
New Git URL