@@ -5149,3 +5149,93 @@ def test_twinx_knows_limits():
5149
5149
ax2 .plot ([0 , 0.5 ], [1 , 2 ])
5150
5150
5151
5151
assert ((xtwin .viewLim .intervalx == ax2 .viewLim .intervalx ).all ())
5152
+
5153
+
5154
+ def test_adjustable_limits ():
5155
+
5156
+ # Test the 'datalim', 'xlim', and 'ylim' options
5157
+
5158
+ image = np .ones ((5 , 5 ))
5159
+
5160
+ # First, we test adjustable='datalim'. Here, whether xlim or ylim are
5161
+ # changed is up to Matplotlib.
5162
+
5163
+ fig = plt .figure (figsize = (6 , 4 ))
5164
+ ax = fig .add_axes ([0 , 0 , 1 , 1 ], aspect = 'equal' )
5165
+ ax .imshow (image , origin = 'lower' )
5166
+
5167
+ # Since the axes has a landscape aspect ratio, the image should fit
5168
+ # vertically and have white padding horizontally:
5169
+ ax .set_adjustable ('datalim' )
5170
+ ax .apply_aspect ()
5171
+ assert_allclose (ax .get_xlim (), [- 1.75 , 5.75 ])
5172
+ assert_allclose (ax .get_ylim (), [- 0.5 , 4.5 ])
5173
+
5174
+ # Because of the way Matplotlib computes the aspect internally, it turns out
5175
+ # that in this scenario ylim is the adjustable, so even if we change ylim,
5176
+ # xlim will stay the same and ylim will get adjusted. This could be improved
5177
+ # in future by checking in set_xlim and set_ylim whether adjustable='datalim'
5178
+ # and try and make sure this value is respected.
5179
+ ax .set_ylim (4 , 5 )
5180
+ ax .apply_aspect ()
5181
+ assert_allclose (ax .get_xlim (), [- 1.75 , 5.75 ])
5182
+ assert_allclose (ax .get_ylim (), [2 , 7 ])
5183
+
5184
+ # Similarly, if xlim is changed, the values are not necessarily respected
5185
+ # and in fact ylim is the one that stays constant. This behavior is the
5186
+ # reason for adding explicit adjustable='xlim' and adjustable='ylim' options.
5187
+ ax .set_xlim (1 , 4 )
5188
+ ax .apply_aspect ()
5189
+ assert_allclose (ax .get_xlim (), [- 1.25 , 6.25 ])
5190
+ assert_allclose (ax .get_ylim (), [2 , 7 ])
5191
+
5192
+ # We now test adjustable='xlim', which should behave in a much more
5193
+ # predictable way.
5194
+
5195
+ fig = plt .figure (figsize = (6 , 4 ))
5196
+ ax = fig .add_axes ([0 , 0 , 1 , 1 ], aspect = 'equal' )
5197
+ ax .imshow (image , origin = 'lower' )
5198
+
5199
+ ax .set_adjustable ('xlim' )
5200
+ ax .apply_aspect ()
5201
+ assert_allclose (ax .get_xlim (), [- 1.75 , 5.75 ])
5202
+ assert_allclose (ax .get_ylim (), [- 0.5 , 4.5 ])
5203
+
5204
+ # Changing ylim results in ylim changing predictably and xlim getting
5205
+ # adjusted
5206
+ ax .set_ylim (4 , 6 )
5207
+ ax .apply_aspect ()
5208
+ assert_allclose (ax .get_xlim (), [0.5 , 3.5 ])
5209
+ assert_allclose (ax .get_ylim (), [4 , 6 ])
5210
+
5211
+ # Changing xlim results in xlim adjusting itself and ylim staying the same
5212
+ ax .set_xlim (2 , 4 )
5213
+ ax .apply_aspect ()
5214
+ assert_allclose (ax .get_xlim (), [1.5 , 4.5 ])
5215
+ assert_allclose (ax .get_ylim (), [4 , 6 ])
5216
+
5217
+ # Finally we test adjustable='ylim', which should behave similarly to 'xlim'
5218
+
5219
+ fig = plt .figure (figsize = (6 , 4 ))
5220
+ ax = fig .add_axes ([0 , 0 , 1 , 1 ], aspect = 'equal' )
5221
+ ax .imshow (image , origin = 'lower' )
5222
+
5223
+ # In the case where ylim is the adjustable, the image will fill the axes
5224
+ # horizontally.
5225
+ ax .set_adjustable ('ylim' )
5226
+ ax .apply_aspect ()
5227
+ assert_allclose (ax .get_xlim (), [- 0.5 , 4.5 ])
5228
+ assert_allclose (ax .get_ylim (), [1 / 3. , 11 / 3. ])
5229
+
5230
+ # Changing xlim results in xlim changing predictably and ylim getting
5231
+ # adjusted
5232
+ ax .set_xlim (4 , 6 )
5233
+ ax .apply_aspect ()
5234
+ assert_allclose (ax .get_xlim (), [4 , 6 ])
5235
+ assert_allclose (ax .get_ylim (), [4 / 3. , 8 / 3. ])
5236
+
5237
+ # Changing ylim results in ylim adjusting itself and xlim staying the same
5238
+ ax .set_ylim (2 , 4 )
5239
+ ax .apply_aspect ()
5240
+ assert_allclose (ax .get_xlim (), [4 , 6 ])
5241
+ assert_allclose (ax .get_ylim (), [7 / 3. , 11 / 3. ])
0 commit comments