Repository: SciTools/cartopy

Issue:
matplotlib pcolormesh bounding box breaks 'tight' bbox calculation
When plotting a colormesh using cartopy the matplotlib code for determining the tight bounding box breaks because it seems to return a tuple of coordinates rather than the expected matplotlib bounding box type. This can easily be reproduced with the simple `pcolormesh` example in the documentation:

``` python
import iris
import matplotlib.pyplot as plt

import cartopy.crs as ccrs

# load some sample iris data
fname = iris.sample_data_path('rotated_pole.nc')
temperature = iris.load_cube(fname)

# iris comes complete with a method to put bounds on a simple point
# coordinate. This is very useful...
temperature.coord('grid_latitude').guess_bounds()
temperature.coord('grid_longitude').guess_bounds()

# turn the iris Cube data structure into numpy arrays
gridlons = temperature.coord('grid_longitude').contiguous_bounds()
gridlats = temperature.coord('grid_latitude').contiguous_bounds()
temperature = temperature.data

# set up a map
ax = plt.axes(projection=ccrs.PlateCarree())

# define the coordinate system that the grid lons and grid lats are on
rotated_pole = ccrs.RotatedPole(pole_longitude=177.5, pole_latitude=37.5)
plt.pcolormesh(gridlons, gridlats, temperature, transform=rotated_pole)

ax.coastlines()

plt.show()
```

Will return:

``` python
AttributeError: 'tuple' object has no attribute 'xmax'
```

On OSX with matplotlib 1.5. This happens when matplotlib attempts to iterate over all the artists to determine their extents but unlike most other types the `matplotlib.collections.QuadMesh` seems to return a tuple when calling `quadmesh.get_window_extent(renderer)`.



Discussion:
After a little bit more investigation the QuadMesh `get_datalim` method is getting patched on the QuadMesh instance and this is used by the `get_window_extent` method to get the bounding box. I think the correct fix is to have the `get_datalim` method return the bounds as a bounding box like most other artists seem to. But one of you will probably be better at determining the correct fix. I still haven't been able to figure out why this issue appeared as it works with the last release of cartopy.

Seems to have been caused by https://github.com/SciTools/cartopy/commit/998ba54070c7dd140f373e04c5a093fc32b37727, which changed how `get_datalim` is computed.

This issue completely breaks plotting in jupyter notebooks using inline--at least for `pcolormesh`.

Yes this will break plotting of pcolormesh anywhere `bbox_inches=tight` is used, which includes the `%matplotlib inline` backend in the notebook.

thank you for highlighting this, I think this needs fixing.

how small a test case can we put together?
It would be great to propose a failing test on a PR which mimics this problem as simply as is sensible

Does this sound like it could be done without too much hassle?

Sounds reasonable, I'll try to come up with a basic example today.

i'd suggest a test in here:
https://github.com/SciTools/cartopy/tree/master/lib/cartopy/tests/mpl
perhaps in 
https://github.com/SciTools/cartopy/blob/master/lib/cartopy/tests/mpl/test_axes.py


Resolving patch:
diff --git a/lib/cartopy/mpl/geoaxes.py b/lib/cartopy/mpl/geoaxes.py
--- a/lib/cartopy/mpl/geoaxes.py
+++ b/lib/cartopy/mpl/geoaxes.py
@@ -1297,8 +1297,13 @@ def _pcolormesh_patched(self, *args, **kwargs):
         maxy = np.amax(Y)
 
         corners = (minx, miny), (maxx, maxy)
-        collection._corners = corners
+        ########################
+        # PATCH
+        # XXX Non-standard matplotlib thing.
+        collection._corners = mtransforms.Bbox(corners)
         collection.get_datalim = lambda transData: collection._corners
+        # END OF PATCH
+        ##############
 
         self.update_datalim(corners)
         self.add_collection(collection)


Test patch: