61
61
62
62
######################################################
63
63
def do_constrained_layout (fig , renderer , h_pad , w_pad ,
64
- hspace = None , wspace = None ):
64
+ hspace = None , wspace = None , compress = False ):
65
65
"""
66
66
Do the constrained_layout. Called at draw time in
67
67
``figure.constrained_layout()``
@@ -83,6 +83,11 @@ def do_constrained_layout(fig, renderer, h_pad, w_pad,
83
83
A value of 0.2 for a three-column layout would have a space
84
84
of 0.1 of the figure width between each column.
85
85
If h/wspace < h/w_pad, then the pads are used instead.
86
+
87
+ compress : boolean, False
88
+ Whether to try and push axes together if their aspect ratios
89
+ make it so that the they will have lots of extra white space
90
+ between them. Useful for grids of images or maps.
86
91
"""
87
92
88
93
# list of unique gridspecs that contain child axes:
@@ -98,7 +103,7 @@ def do_constrained_layout(fig, renderer, h_pad, w_pad,
98
103
'Possibly did not call parent GridSpec with the'
99
104
' "figure" keyword' )
100
105
101
- for _ in range (2 ):
106
+ for nn in range (2 ):
102
107
# do the algorithm twice. This has to be done because decorations
103
108
# change size after the first re-position (i.e. x/yticklabels get
104
109
# larger/smaller). This second reposition tends to be much milder,
@@ -118,16 +123,56 @@ def do_constrained_layout(fig, renderer, h_pad, w_pad,
118
123
# update all the variables in the layout.
119
124
fig ._layoutgrid .update_variables ()
120
125
126
+ warn_collapsed = ('constrained_layout not applied because '
127
+ 'axes sizes collapsed to zero. Try making '
128
+ 'figure larger or axes decorations smaller.' )
121
129
if _check_no_collapsed_axes (fig ):
122
130
_reposition_axes (fig , renderer , h_pad = h_pad , w_pad = w_pad ,
123
131
hspace = hspace , wspace = wspace )
132
+ if compress :
133
+ _compress_fixed_aspect (fig )
134
+
135
+ # update all the variables in the layout.
136
+ fig ._layoutgrid .update_variables ()
137
+ if _check_no_collapsed_axes (fig ):
138
+ _reposition_axes (fig , renderer , h_pad = h_pad , w_pad = w_pad ,
139
+ hspace = hspace , wspace = wspace )
140
+ else :
141
+ _api .warn_external (warn_collapsed )
124
142
else :
125
- _api .warn_external ('constrained_layout not applied because '
126
- 'axes sizes collapsed to zero. Try making '
127
- 'figure larger or axes decorations smaller.' )
143
+ _api .warn_external (warn_collapsed )
128
144
_reset_margins (fig )
129
145
130
146
147
+ def _compress_fixed_aspect (fig ):
148
+ extraw = dict ()
149
+ extrah = dict ()
150
+ for ax in fig .axes :
151
+ if hasattr (ax , 'get_subplotspec' ):
152
+ actual = ax .get_position (original = False )
153
+ ax .apply_aspect ()
154
+ sub = ax .get_subplotspec ()
155
+ gs = sub .get_gridspec ()
156
+ if gs not in extraw .keys ():
157
+ extraw [gs ] = np .zeros (gs .ncols )
158
+ extrah [gs ] = np .zeros (gs .nrows )
159
+ orig = ax .get_position (original = True )
160
+ actual = ax .get_position (original = False )
161
+ dw = orig .width - actual .width
162
+ if dw > 0 :
163
+ for i in sub .colspan :
164
+ extraw [gs ][i ] = max (extraw [gs ][i ], dw )
165
+ dh = orig .height - actual .height
166
+ if dh > 0 :
167
+ for i in sub .rowspan :
168
+ extrah [gs ][i ] = max (extrah [gs ][i ], dh )
169
+
170
+ fig ._layoutgrid .edit_margin_min ('left' , np .sum (extraw [gs ]) / 2 )
171
+ fig ._layoutgrid .edit_margin_min ('right' , np .sum (extraw [gs ]) / 2 )
172
+
173
+ fig ._layoutgrid .edit_margin_min ('top' , np .sum (extrah [gs ]) / 2 )
174
+ fig ._layoutgrid .edit_margin_min ('bottom' , np .sum (extrah [gs ]) / 2 )
175
+
131
176
def _check_no_collapsed_axes (fig ):
132
177
"""
133
178
Check that no axes have collapsed to zero size.
0 commit comments