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

[Bug]: Padding at the edges ofGridSpecFromSubplotSpec is double counted withlayout="constrained" #28894

Open
@jakelevi1996

Description

@jakelevi1996

Bug summary

Padding at the edges ofGridSpecFromSubplotSpec is double counted withlayout="constrained" - IE, for an inner grid G1 in element E of an outer grid G2, the padding is counted once between E and the other elements of G2, and once between the edges of E and the first/last elements within G1, forcing the elements within G1 to be much smaller than they need to be (see below).

Code for reproduction

importnumpyasnpimportmatplotlib.pyplotaspltimportmatplotlib.axesimportmatplotlib._layoutgridrng=np.random.default_rng(0)defmake_demo(plot_name,pad=0.1,show_box=True):file_name="%s.png"%plot_nameprint(file_name)figure=plt.figure(figsize=[10,6],layout="constrained")figure.get_layout_engine().set(w_pad=pad,h_pad=pad)axes=figure.subplots(1,2,width_ratios=[1,2])show_random_image(axes[0])axes=add_subplots(axes[1],2,2,show_box)axes=add_subplots(axes[1],2,2,show_box)figure.suptitle(plot_name,fontsize=25)figure.savefig(file_name)defadd_subplots(axis:matplotlib.axes.Axes,nx,ny,show_box,    )->list[matplotlib.axes.Axes]:axis.clear()ifshow_box:axis.get_xaxis().set_visible(False)axis.get_yaxis().set_visible(False)else:axis.set_axis_off()subplot_spec=axis.get_subplotspec()subgrid_spec=subplot_spec.subgridspec(nx,ny)axis_list=subgrid_spec.subplots().flatten().tolist()forainaxis_list:show_random_image(a)returnaxis_listdefshow_random_image(axis:matplotlib.axes.Axes):axis.pcolormesh(rng.uniform(0,1, [10,10]))axis.set_axis_off()defmain():fix_parent_space()make_demo("1_original")make_demo("2_original_no_box",show_box=False)make_demo("3_more_padding",0.2)make_demo("4_more_padding_no_box",0.2,False)fix_double_edge_padding()make_demo("5_fixed",0.2)make_demo("6_fixed_no_box",0.2,False)deffix_parent_space():importmatplotlib._constrained_layoutimportmatplotlib._layoutgridasmlayoutgriddefmake_layoutgrids_gs(layoutgrids,gs):"""        Make the layoutgrid for a gridspec (and anything nested in the gridspec)        """ifgsinlayoutgridsorgs.figureisNone:returnlayoutgrids# in order to do constrained_layout there has to be at least *one*# gridspec in the tree:layoutgrids['hasgrids']=Trueifnothasattr(gs,'_subplot_spec'):# normal gridspecparent=layoutgrids[gs.figure]layoutgrids[gs]=mlayoutgrid.LayoutGrid(parent=parent,parent_inner=True,name='gridspec',ncols=gs._ncols,nrows=gs._nrows,width_ratios=gs.get_width_ratios(),height_ratios=gs.get_height_ratios())else:# this is a gridspecfromsubplotspec:subplot_spec=gs._subplot_specparentgs=subplot_spec.get_gridspec()# if a nested gridspec it is possible the parent is not in there yet:ifparentgsnotinlayoutgrids:layoutgrids=make_layoutgrids_gs(layoutgrids,parentgs)subspeclb=layoutgrids[parentgs]# gridspecfromsubplotspec need an outer container:# get a unique representation:rep= (gs,'top')ifrepnotinlayoutgrids:layoutgrids[rep]=mlayoutgrid.LayoutGrid(parent=subspeclb,parent_inner=True,name='top',nrows=1,ncols=1,parent_pos=(subplot_spec.rowspan,subplot_spec.colspan))layoutgrids[gs]=mlayoutgrid.LayoutGrid(parent=layoutgrids[rep],name='gridspec',nrows=gs._nrows,ncols=gs._ncols,width_ratios=gs.get_width_ratios(),height_ratios=gs.get_height_ratios())returnlayoutgridsmatplotlib._constrained_layout.make_layoutgrids_gs=make_layoutgrids_gsdeffix_double_edge_padding():importmatplotlib._constrained_layoutimportmatplotlib.gridspecdefget_margin_from_padding(obj,*,w_pad=0,h_pad=0,hspace=0,wspace=0):ss=obj._subplotspecgs=ss.get_gridspec()ifhasattr(gs,'hspace'):_hspace= (gs.hspaceifgs.hspaceisnotNoneelsehspace)_wspace= (gs.wspaceifgs.wspaceisnotNoneelsewspace)else:_hspace= (gs._hspaceifgs._hspaceisnotNoneelsehspace)_wspace= (gs._wspaceifgs._wspaceisnotNoneelsewspace)_wspace=_wspace/2_hspace=_hspace/2nrows,ncols=gs.get_geometry()# there are two margins for each direction.  The "cb"# margins are for pads and colorbars, the non-"cb" are# for the Axes decorations (labels etc).margin= {'leftcb':w_pad,'rightcb':w_pad,'bottomcb':h_pad,'topcb':h_pad,'left':0,'right':0,'top':0,'bottom':0}ifisinstance(gs,matplotlib.gridspec.GridSpecFromSubplotSpec):ifss.is_first_col():margin['leftcb']=0ifss.is_last_col():margin['rightcb']=0ifss.is_first_row():margin['topcb']=0ifss.is_last_row():margin['bottomcb']=0if_wspace/ncols>w_pad:ifss.colspan.start>0:margin['leftcb']=_wspace/ncolsifss.colspan.stop<ncols:margin['rightcb']=_wspace/ncolsif_hspace/nrows>h_pad:ifss.rowspan.stop<nrows:margin['bottomcb']=_hspace/nrowsifss.rowspan.start>0:margin['topcb']=_hspace/nrowsreturnmarginmatplotlib._constrained_layout.get_margin_from_padding=get_margin_from_paddingif__name__=="__main__":main()# filenames = [#     "1_original.png",#     "2_original_no_box.png",#     "3_more_padding.png",#     "4_more_padding_no_box.png",#     "5_fixed.png",#     "6_fixed_no_box.png",# ]# from jutility import util, plotting# mp = plotting.MultiPlot(#     *[plotting.ImShow(util.load_image(s)) for s in filenames],#     num_cols=2,#     colour="grey",# )# mp.save()

Actual outcome

When padding is increased (row 1 to row 2), the elements in the inner grids become way too small (this assumes the functionfix_parent_space which fixes#28891 has been called at the start):

image

Expected outcome

After my fix (functionfix_double_edge_padding) is applied, the subplots return to a normal size, shown in row 3 above.

Additional information

My fix is shown in the functionfix_double_edge_padding above, specifically the branch that starts withif isinstance(gs, matplotlib.gridspec.GridSpecFromSubplotSpec):, which applies to the functionget_margin_from_padding in_constrained_layout.py (https://github.com/matplotlib/matplotlib/blob/v3.9.2/lib/matplotlib/_constrained_layout.py#L297 ).

Operating system

Ubuntu

Matplotlib Version

3.9.2

Matplotlib Backend

qtagg

Python version

Python 3.10.12

Jupyter version

No response

Installation

pip

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions


      [8]ページ先頭

      ©2009-2025 Movatter.jp