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
+ # update all the variables in the layout.
135
+ fig ._layoutgrid .update_variables ()
136
+ if _check_no_collapsed_axes (fig ):
137
+ _reposition_axes (fig , renderer , h_pad = h_pad , w_pad = w_pad ,
138
+ hspace = hspace , wspace = wspace )
139
+ else :
140
+ _api .warn_external (warn_collapsed )
124
141
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.' )
142
+ _api .warn_external (warn_collapsed )
128
143
_reset_margins (fig )
129
144
130
145
146
+ def _compress_fixed_aspect (fig ):
147
+ extraw = dict ()
148
+ extrah = dict ()
149
+ for ax in fig .axes :
150
+ if hasattr (ax , 'get_subplotspec' ):
151
+ actual = ax .get_position (original = False )
152
+ ax .apply_aspect ()
153
+ sub = ax .get_subplotspec ()
154
+ gs = sub .get_gridspec ()
155
+ if gs not in extraw .keys ():
156
+ extraw [gs ] = np .zeros (gs .ncols )
157
+ extrah [gs ] = np .zeros (gs .nrows )
158
+ orig = ax .get_position (original = True )
159
+ actual = ax .get_position (original = False )
160
+ dw = orig .width - actual .width
161
+ if dw > 0 :
162
+ for i in sub .colspan :
163
+ extraw [gs ][i ] = max (extraw [gs ][i ], dw )
164
+ dh = orig .height - actual .height
165
+ if dh > 0 :
166
+ for i in sub .rowspan :
167
+ extrah [gs ][i ] = max (extrah [gs ][i ], dh )
168
+
169
+ fig ._layoutgrid .edit_margin_min ('left' , np .sum (extraw [gs ]) / 2 )
170
+ fig ._layoutgrid .edit_margin_min ('right' , np .sum (extraw [gs ]) / 2 )
171
+
172
+ fig ._layoutgrid .edit_margin_min ('top' , np .sum (extrah [gs ]) / 2 )
173
+ fig ._layoutgrid .edit_margin_min ('bottom' , np .sum (extrah [gs ]) / 2 )
174
+
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