Repository: SciTools/cartopy

Issue:
Default ‘origin’ for imshow
So, the default value for the `origin` argument to `imshow` for base matplotlib is as documented:
```
origin : {'upper', 'lower'}, optional
Place the [0,0] index of the array in the upper left or lower left corner of the axes.
The convention 'upper' is typically used for matrices and images. If not given, 
rcParams["image.origin"] is used, defaulting to 'upper'.

Note that the vertical axes points upward for 'lower' but downward for 'upper'.
```

Why on earth do we default to ‘lower’??? 
https://github.com/SciTools/cartopy/blob/f918d97924339887d301c0a8bb7cd34d0590b6ed/lib/cartopy/mpl/geoaxes.py#L1092


Discussion:
I’d like to change the default, or at least start moving in that direction, by matching matplotlib. If we need to do a deprecation cycle, I’d like to start warning about it then.
👍 on this - it's a strange quirk and certainly makes teaching `imshow` then `imshow` on geoaxes a bit difficult.
> Why on earth do we default to ‘lower’???

I am unsure if your question is rhetorical, but I always assumed it was because that is the typical orientation of scientific grids.
I guess the better question is: why on earth does CartoPy have a different default than matplotlib itself? It seems like a confusing break from matplotlib for little benefit.
Ping @pelson since you wrote the original code 6 years ago.
> I am unsure if your question is rhetorical, but I always assumed it was because that is the typical orientation of scientific grids.

Precisely. *It is* inconsistent though, and I would support changing it to be consistent with matplotlib.

There is an assumption in the image re-projection code that the image is lower, and hence the comment further down that states:

```
                # It is implicitly assumed by the regridding operation that the
                # origin of the image is 'lower', so simply adjust for that
                # here.
```

This doesn't preclude fixing the default though. 
  
Bigger question: anybody know why upper is the default in matplotlib. Is it a historical quirk? PNGs are lower, scientific data is lower, JPEGs are upper (normally)...
Advise: don't try to fix this in v0.17 - it is a breaking change that we don't *need* to make in the next few days. v0.17 is already pretty big... 😉 
I'm sure matplotlib does it because MATLAB does--probably because metrices and rows-based data. Blaming MATLAB is what I usually do when I encounter *ahem* unconventional behavior in matplotlib.

No to changing the default in 0.17 seems sensible...but how about a `DeprecationWarning` or a `FutureWarning` so that people know the change is coming?
PNGs are lower? That seems opposite to most graphics applications.
See #1194 for a PR to warn when using the default value for origin.

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
@@ -1212,7 +1212,7 @@ def imshow(self, img, *args, **kwargs):
         origin: {'lower', 'upper'}
             The origin of the vertical pixels. See
             :func:`matplotlib.pyplot.imshow` for further details.
-            Default is ``'lower'``.
+            Default is ``'upper'``. Prior to 0.18, it was ``'lower'``.
 
         """
         if 'update_datalim' in kwargs:
@@ -1222,7 +1222,7 @@ def imshow(self, img, *args, **kwargs):
 
         transform = kwargs.pop('transform')
         extent = kwargs.get('extent', None)
-        kwargs.setdefault('origin', 'lower')
+        kwargs.setdefault('origin', 'upper')
 
         same_projection = (isinstance(transform, ccrs.Projection) and
                            self.projection == transform)


Test patch:
diff --git a/lib/cartopy/tests/mpl/test_images.py b/lib/cartopy/tests/mpl/test_images.py
--- a/lib/cartopy/tests/mpl/test_images.py
+++ b/lib/cartopy/tests/mpl/test_images.py
@@ -133,7 +133,7 @@ def test_imshow():
     # form that JPG images would be loaded with imread.
     img = (img * 255).astype('uint8')
     ax = plt.axes(projection=ccrs.Orthographic())
-    ax.imshow(img, origin='upper', transform=source_proj,
+    ax.imshow(img, transform=source_proj,
               extent=[-180, 180, -90, 90])
 
 
@@ -148,7 +148,7 @@ def test_imshow_projected():
     ax = plt.axes(projection=ccrs.LambertConformal())
     ax.set_extent(img_extent, crs=source_proj)
     ax.coastlines(resolution='50m')
-    ax.imshow(img, extent=img_extent, origin='upper', transform=source_proj)
+    ax.imshow(img, extent=img_extent, transform=source_proj)
 
 
 def test_imshow_wrapping():
@@ -180,7 +180,7 @@ def test_pil_Image():
     img = Image.open(NATURAL_EARTH_IMG)
     source_proj = ccrs.PlateCarree()
     ax = plt.axes(projection=ccrs.Orthographic())
-    ax.imshow(img, origin='upper', transform=source_proj,
+    ax.imshow(img, transform=source_proj,
               extent=[-180, 180, -90, 90])