Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commitce9c860

Browse files
authored
Merge pull request#16618 from anntzer/subplotspans
Use SubplotSpec row/colspans more, and deprecate get_rows_columns.
2 parentsdefce2e +3e4c299 commitce9c860

File tree

4 files changed

+156
-212
lines changed

4 files changed

+156
-212
lines changed

‎doc/api/next_api_changes/deprecations.rst

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -386,3 +386,8 @@ instead.
386386
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
387387
The unused ``animation.html_args`` rcParam and ``animation.HTMLWriter.args_key``
388388
attribute are deprecated.
389+
390+
``SubplotSpec.get_rows_columns``
391+
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
392+
This method is deprecated. Use the ``GridSpec.nrows``, ``GridSpec.ncols``,
393+
``SubplotSpec.rowspan``, and ``SubplotSpec.colspan`` properties instead.

‎lib/matplotlib/_constrained_layout.py

Lines changed: 128 additions & 174 deletions
Original file line numberDiff line numberDiff line change
@@ -55,14 +55,8 @@
5555
_log=logging.getLogger(__name__)
5656

5757

58-
def_in_same_column(colnum0min,colnum0max,colnumCmin,colnumCmax):
59-
return (colnumCmin<=colnum0min<=colnumCmax
60-
orcolnumCmin<=colnum0max<=colnumCmax)
61-
62-
63-
def_in_same_row(rownum0min,rownum0max,rownumCmin,rownumCmax):
64-
return (rownumCmin<=rownum0min<=rownumCmax
65-
orrownumCmin<=rownum0max<=rownumCmax)
58+
def_spans_overlap(span0,span1):
59+
returnspan0.startinspan1orspan1.startinspan0
6660

6761

6862
def_axes_all_finite_sized(fig):
@@ -155,7 +149,7 @@ def do_constrained_layout(fig, renderer, h_pad, w_pad,
155149
# fill in any empty gridspec slots w/ ghost axes...
156150
_make_ghost_gridspec_slots(fig,gs)
157151

158-
fornnninrange(2):
152+
for_inrange(2):
159153
# do the algorithm twice. This has to be done because decorators
160154
# change size after the first re-position (i.e. x/yticklabels get
161155
# larger/smaller). This second reposition tends to be much milder,
@@ -329,131 +323,109 @@ def _align_spines(fig, gs):
329323
if (hasattr(ax,'get_subplotspec')
330324
andax._layoutboxisnotNone
331325
andax.get_subplotspec().get_gridspec()==gs)]
332-
rownummin=np.zeros(len(axs),dtype=np.int8)
333-
rownummax=np.zeros(len(axs),dtype=np.int8)
334-
colnummin=np.zeros(len(axs),dtype=np.int8)
335-
colnummax=np.zeros(len(axs),dtype=np.int8)
336-
width=np.zeros(len(axs))
337-
height=np.zeros(len(axs))
338-
339-
forn,axinenumerate(axs):
326+
rowspans= []
327+
colspans= []
328+
heights= []
329+
widths= []
330+
331+
foraxinaxs:
340332
ss0=ax.get_subplotspec()
341-
rownummin[n],colnummin[n]=divmod(ss0.num1,ncols)
342-
rownummax[n],colnummax[n]=divmod(ss0.num2,ncols)
343-
width[n]=np.sum(
344-
width_ratios[colnummin[n]:(colnummax[n]+1)])
345-
height[n]=np.sum(
346-
height_ratios[rownummin[n]:(rownummax[n]+1)])
347-
348-
fornn,axinenumerate(axs[:-1]):
349-
# now compare ax to all the axs:
350-
#
351-
# If the subplotspecs have the same colnumXmax, then line
352-
# up their right sides. If they have the same min, then
353-
# line up their left sides (and vertical equivalents).
354-
rownum0min,colnum0min=rownummin[nn],colnummin[nn]
355-
rownum0max,colnum0max=rownummax[nn],colnummax[nn]
356-
width0,height0=width[nn],height[nn]
333+
rowspan=ss0.rowspan
334+
colspan=ss0.colspan
335+
rowspans.append(rowspan)
336+
colspans.append(colspan)
337+
heights.append(sum(height_ratios[rowspan.start:rowspan.stop]))
338+
widths.append(sum(width_ratios[colspan.start:colspan.stop]))
339+
340+
foridx0,ax0inenumerate(axs):
341+
# Compare ax to all other axs: If the subplotspecs start (/stop) at
342+
# the same column, then line up their left (/right) sides; likewise
343+
# for rows/top/bottom.
344+
rowspan0=rowspans[idx0]
345+
colspan0=colspans[idx0]
346+
height0=heights[idx0]
347+
width0=widths[idx0]
357348
alignleft=False
358349
alignright=False
359350
alignbot=False
360351
aligntop=False
361352
alignheight=False
362353
alignwidth=False
363-
formminrange(nn+1,len(axs)):
364-
axc=axs[mm]
365-
rownumCmin,colnumCmin=rownummin[mm],colnummin[mm]
366-
rownumCmax,colnumCmax=rownummax[mm],colnummax[mm]
367-
widthC,heightC=width[mm],height[mm]
368-
# Horizontally align axes spines if they have the
369-
# same min or max:
370-
ifnotalignleftandcolnum0min==colnumCmin:
371-
# we want the _poslayoutboxes to line up on left
372-
# side of the axes spines...
373-
layoutbox.align([ax._poslayoutbox,axc._poslayoutbox],
354+
foridx1inrange(idx0+1,len(axs)):
355+
ax1=axs[idx1]
356+
rowspan1=rowspans[idx1]
357+
colspan1=colspans[idx1]
358+
width1=widths[idx1]
359+
height1=heights[idx1]
360+
# Horizontally align axes spines if they have the same min or max:
361+
ifnotalignleftandcolspan0.start==colspan1.start:
362+
_log.debug('same start columns; line up layoutbox lefts')
363+
layoutbox.align([ax0._poslayoutbox,ax1._poslayoutbox],
374364
'left')
375365
alignleft=True
376-
ifnotalignrightandcolnum0max==colnumCmax:
377-
#line upright sides of _poslayoutbox
378-
layoutbox.align([ax._poslayoutbox,axc._poslayoutbox],
366+
ifnotalignrightandcolspan0.stop==colspan1.stop:
367+
_log.debug('same stop columns;line uplayoutbox rights')
368+
layoutbox.align([ax0._poslayoutbox,ax1._poslayoutbox],
379369
'right')
380370
alignright=True
381-
# Vertically align axes spines if they have the
382-
# same min or max:
383-
ifnotaligntopandrownum0min==rownumCmin:
384-
# line up top of _poslayoutbox
385-
_log.debug('rownum0min == rownumCmin')
386-
layoutbox.align([ax._poslayoutbox,axc._poslayoutbox],
371+
# Vertically align axes spines if they have the same min or max:
372+
ifnotaligntopandrowspan0.start==rowspan1.start:
373+
_log.debug('same start rows; line up layoutbox tops')
374+
layoutbox.align([ax0._poslayoutbox,ax1._poslayoutbox],
387375
'top')
388376
aligntop=True
389-
ifnotalignbotandrownum0max==rownumCmax:
390-
# line up bottom of _poslayoutbox
391-
_log.debug('rownum0max == rownumCmax')
392-
layoutbox.align([ax._poslayoutbox,axc._poslayoutbox],
377+
ifnotalignbotandrowspan0.stop==rowspan1.stop:
378+
_log.debug('same stop rows; line up layoutbox bottoms')
379+
layoutbox.align([ax0._poslayoutbox,ax1._poslayoutbox],
393380
'bottom')
394381
alignbot=True
395-
###########
382+
396383
# Now we make the widths and heights of position boxes
397384
# similar. (i.e the spine locations)
398-
# This allows vertically stacked subplots to have
399-
# different sizes if they occupy different amounts
400-
# of the gridspec: i.e.
401-
# gs = gridspec.GridSpec(3, 1)
402-
# ax1 = gs[0, :]
403-
# ax2 = gs[1:, :]
404-
# then drows0 = 1, and drowsC = 2, and ax2
405-
# should be at least twice as large as ax1.
385+
# This allows vertically stacked subplots to have different sizes
386+
# if they occupy different amounts of the gridspec, e.g. if
387+
# gs = gridspec.GridSpec(3, 1)
388+
# ax0 = gs[0, :]
389+
# ax1 = gs[1:, :]
390+
# then len(rowspan0) = 1, and len(rowspan1) = 2,
391+
# and ax1 should be at least twice as large as ax0.
406392
# But it can be more than twice as large because
407393
# it needs less room for the labeling.
408-
#
409-
# For height, this only needs to be done if the
410-
# subplots share a column. For width if they
411-
# share a row.
412-
413-
drowsC= (rownumCmax-rownumCmin+1)
414-
drows0= (rownum0max-rownum0min+1)
415-
dcolsC= (colnumCmax-colnumCmin+1)
416-
dcols0= (colnum0max-colnum0min+1)
417-
418-
ifnotalignheightanddrows0==drowsC:
419-
ax._poslayoutbox.constrain_height(
420-
axc._poslayoutbox.height*height0/heightC)
394+
395+
# For heights, do it if the subplots share a column.
396+
ifnotalignheightandlen(rowspan0)==len(rowspan1):
397+
ax0._poslayoutbox.constrain_height(
398+
ax1._poslayoutbox.height*height0/height1)
421399
alignheight=True
422-
elif_in_same_column(colnum0min,colnum0max,
423-
colnumCmin,colnumCmax):
424-
ifheight0>heightC:
425-
ax._poslayoutbox.constrain_height_min(
426-
axc._poslayoutbox.height*height0/heightC)
400+
elif_spans_overlap(colspan0,colspan1):
401+
ifheight0>height1:
402+
ax0._poslayoutbox.constrain_height_min(
403+
ax1._poslayoutbox.height*height0/height1)
427404
# these constraints stop the smaller axes from
428405
# being allowed to go to zero height...
429-
axc._poslayoutbox.constrain_height_min(
430-
ax._poslayoutbox.height*heightC/
431-
(height0*1.8))
432-
elifheight0<heightC:
433-
axc._poslayoutbox.constrain_height_min(
434-
ax._poslayoutbox.height*heightC/height0)
435-
ax._poslayoutbox.constrain_height_min(
436-
ax._poslayoutbox.height*height0/
437-
(heightC*1.8))
438-
# widths...
439-
ifnotalignwidthanddcols0==dcolsC:
440-
ax._poslayoutbox.constrain_width(
441-
axc._poslayoutbox.width*width0/widthC)
406+
ax1._poslayoutbox.constrain_height_min(
407+
ax0._poslayoutbox.height*height1/ (height0*1.8))
408+
elifheight0<height1:
409+
ax1._poslayoutbox.constrain_height_min(
410+
ax0._poslayoutbox.height*height1/height0)
411+
ax0._poslayoutbox.constrain_height_min(
412+
ax0._poslayoutbox.height*height0/ (height1*1.8))
413+
# For widths, do it if the subplots share a row.
414+
ifnotalignwidthandlen(colspan0)==len(colspan1):
415+
ax0._poslayoutbox.constrain_width(
416+
ax1._poslayoutbox.width*width0/width1)
442417
alignwidth=True
443-
elif_in_same_row(rownum0min,rownum0max,
444-
rownumCmin,rownumCmax):
445-
ifwidth0>widthC:
446-
ax._poslayoutbox.constrain_width_min(
447-
axc._poslayoutbox.width*width0/widthC)
448-
axc._poslayoutbox.constrain_width_min(
449-
ax._poslayoutbox.width*widthC/
450-
(width0*1.8))
451-
elifwidth0<widthC:
452-
axc._poslayoutbox.constrain_width_min(
453-
ax._poslayoutbox.width*widthC/width0)
454-
ax._poslayoutbox.constrain_width_min(
455-
axc._poslayoutbox.width*width0/
456-
(widthC*1.8))
418+
elif_spans_overlap(rowspan0,rowspan1):
419+
ifwidth0>width1:
420+
ax0._poslayoutbox.constrain_width_min(
421+
ax1._poslayoutbox.width*width0/width1)
422+
ax1._poslayoutbox.constrain_width_min(
423+
ax0._poslayoutbox.width*width1/ (width0*1.8))
424+
elifwidth0<width1:
425+
ax1._poslayoutbox.constrain_width_min(
426+
ax0._poslayoutbox.width*width1/width0)
427+
ax0._poslayoutbox.constrain_width_min(
428+
ax1._poslayoutbox.width*width0/ (width1*1.8))
457429

458430

459431
def_arrange_subplotspecs(gs,hspace=0,wspace=0):
@@ -470,34 +442,25 @@ def _arrange_subplotspecs(gs, hspace=0, wspace=0):
470442
forchild0insschildren:
471443
ss0=child0.artist
472444
nrows,ncols=ss0.get_gridspec().get_geometry()
473-
rowNum0min,colNum0min=divmod(ss0.num1,ncols)
474-
rowNum0max,colNum0max=divmod(ss0.num2,ncols)
445+
rowspan0=ss0.rowspan
446+
colspan0=ss0.colspan
475447
sschildren=sschildren[1:]
476-
forchildcinsschildren:
477-
ssc=childc.artist
478-
rowNumCmin,colNumCmin=divmod(ssc.num1,ncols)
479-
rowNumCmax,colNumCmax=divmod(ssc.num2,ncols)
480-
# OK, this tells us the relative layout of ax
481-
# with axc
482-
thepad=wspace/ncols
483-
ifcolNum0max<colNumCmin:
484-
layoutbox.hstack([ss0._layoutbox,ssc._layoutbox],
485-
padding=thepad)
486-
ifcolNumCmax<colNum0min:
487-
layoutbox.hstack([ssc._layoutbox,ss0._layoutbox],
488-
padding=thepad)
489-
490-
####
448+
forchild1insschildren:
449+
ss1=child1.artist
450+
rowspan1=ss1.rowspan
451+
colspan1=ss1.colspan
452+
# OK, this tells us the relative layout of child0 with child1.
453+
pad=wspace/ncols
454+
ifcolspan0.stop<=colspan1.start:
455+
layoutbox.hstack([ss0._layoutbox,ss1._layoutbox],padding=pad)
456+
ifcolspan1.stop<=colspan0.start:
457+
layoutbox.hstack([ss1._layoutbox,ss0._layoutbox],padding=pad)
491458
# vertical alignment
492-
thepad=hspace/nrows
493-
ifrowNum0max<rowNumCmin:
494-
layoutbox.vstack([ss0._layoutbox,
495-
ssc._layoutbox],
496-
padding=thepad)
497-
ifrowNumCmax<rowNum0min:
498-
layoutbox.vstack([ssc._layoutbox,
499-
ss0._layoutbox],
500-
padding=thepad)
459+
pad=hspace/nrows
460+
ifrowspan0.stop<=rowspan1.start:
461+
layoutbox.vstack([ss0._layoutbox,ss1._layoutbox],padding=pad)
462+
ifrowspan1.stop<=rowspan0.start:
463+
layoutbox.vstack([ss1._layoutbox,ss0._layoutbox],padding=pad)
501464

502465

503466
deflayoutcolorbarsingle(ax,cax,shrink,aspect,location,pad=0.05):
@@ -560,33 +523,28 @@ def layoutcolorbarsingle(ax, cax, shrink, aspect, location, pad=0.05):
560523

561524

562525
def_getmaxminrowcolumn(axs):
563-
# helper to get the min/max rows and columns of a list of axes.
564-
maxrow=-100000
565-
minrow=1000000
566-
maxax=None
567-
minax=None
568-
maxcol=-100000
569-
mincol=1000000
570-
maxax_col=None
571-
minax_col=None
572-
526+
"""
527+
Find axes covering the first and last rows and columns of a list of axes.
528+
"""
529+
startrow=startcol=np.inf
530+
stoprow=stopcol=-np.inf
531+
startax_row=startax_col=stopax_row=stopax_col=None
573532
foraxinaxs:
574533
subspec=ax.get_subplotspec()
575-
nrows,ncols,row_start,row_stop,col_start,col_stop= \
576-
subspec.get_rows_columns()
577-
ifrow_stop>maxrow:
578-
maxrow=row_stop
579-
maxax=ax
580-
ifrow_start<minrow:
581-
minrow=row_start
582-
minax=ax
583-
ifcol_stop>maxcol:
584-
maxcol=col_stop
585-
maxax_col=ax
586-
ifcol_start<mincol:
587-
mincol=col_start
588-
minax_col=ax
589-
return (minrow,maxrow,minax,maxax,mincol,maxcol,minax_col,maxax_col)
534+
ifsubspec.rowspan.start<startrow:
535+
startrow=subspec.rowspan.start
536+
startax_row=ax
537+
ifsubspec.rowspan.stop>stoprow:
538+
stoprow=subspec.rowspan.stop
539+
stopax_row=ax
540+
ifsubspec.colspan.start<startcol:
541+
startcol=subspec.colspan.start
542+
startax_col=ax
543+
ifsubspec.colspan.stop>stopcol:
544+
stopcol=subspec.colspan.stop
545+
stopax_col=ax
546+
return (startrow,stoprow-1,startax_row,stopax_row,
547+
startcol,stopcol-1,startax_col,stopax_col)
590548

591549

592550
deflayoutcolorbargridspec(parents,cax,shrink,aspect,location,pad=0.05):
@@ -630,18 +588,16 @@ def layoutcolorbargridspec(parents, cax, shrink, aspect, location, pad=0.05):
630588
# Horizontal Layout: need to check all the axes in this gridspec
631589
forchingslb.children:
632590
subspec=ch.artist
633-
nrows,ncols,row_start,row_stop,col_start,col_stop= \
634-
subspec.get_rows_columns()
635591
iflocation=='right':
636-
ifcol_stop<=maxcol:
592+
ifsubspec.colspan.stop-1<=maxcol:
637593
order= [subspec._layoutbox,lb]
638594
# arrange to right of the parents
639-
ifcol_start>maxcol:
595+
elifsubspec.colspan.start>maxcol:
640596
order= [lb,subspec._layoutbox]
641597
eliflocation=='left':
642-
ifcol_start>=mincol:
598+
ifsubspec.colspan.start>=mincol:
643599
order= [lb,subspec._layoutbox]
644-
ifcol_stop<mincol:
600+
elifsubspec.colspan.stop-1<mincol:
645601
order= [subspec._layoutbox,lb]
646602
layoutbox.hstack(order,padding=pad*gslb.width,
647603
strength='strong')
@@ -686,17 +642,15 @@ def layoutcolorbargridspec(parents, cax, shrink, aspect, location, pad=0.05):
686642
# Vertical Layout: need to check all the axes in this gridspec
687643
forchingslb.children:
688644
subspec=ch.artist
689-
nrows,ncols,row_start,row_stop,col_start,col_stop= \
690-
subspec.get_rows_columns()
691645
iflocation=='bottom':
692-
ifrow_stop<=minrow:
646+
ifsubspec.rowspan.stop-1<=minrow:
693647
order= [subspec._layoutbox,lb]
694-
ifrow_start>maxrow:
648+
elifsubspec.rowspan.start>maxrow:
695649
order= [lb,subspec._layoutbox]
696650
eliflocation=='top':
697-
ifrow_stop<minrow:
651+
ifsubspec.rowspan.stop-1<minrow:
698652
order= [subspec._layoutbox,lb]
699-
ifrow_start>=maxrow:
653+
elifsubspec.rowspan.start>=maxrow:
700654
order= [lb,subspec._layoutbox]
701655
layoutbox.vstack(order,padding=pad*gslb.width,
702656
strength='strong')

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp