Repository: rasterio/rasterio

Issue:
rasterio.plot.show: rasters with RGBA bands are not displayed as expected
<!--

WELCOME ABOARD!

Hi and welcome to the Rasterio project. We appreciate bug reports, questions
about documentation, and suggestions for new features. This issue template
isn't intended to ward you off; only to intercept and redirect some particular
categories of reports, and to collect a few important facts that issue reporters
often omit.

The primary forum for questions about installation and usage of Rasterio is 
https://rasterio.groups.io/g/main. The authors and other users will answer 
questions when they have expertise to share and time to explain. Please take the
time to craft a clear question and be patient about responses. Please do not
bring these questions to Rasterio's issue tracker, which we want to reserve for
bug reports and other actionable issues.

Questions about development of Rasterio, brainstorming, requests for comment,
and not-yet-actionable proposals are welcome in the project's developers 
discussion group https://rasterio.groups.io/g/dev. Issues opened in Rasterio's
GitHub repo which haven't been socialized there may be perfunctorily closed.

Please note: Rasterio contains extension modules and is thus susceptible to
C library compatibility issues. If you are reporting an installation or module
import issue, please note that this project only accepts reports about problems
with packages downloaded from the Python Package Index. Conda users should take
issues to one of the following trackers:

- https://github.com/ContinuumIO/anaconda-issues/issues
- https://github.com/conda-forge/rasterio-feedstock

Also please note: we are currently working on 1.0 and pre-releases. Bugs found
in version 0.36 will not be fixed except in a 1.0 alpha or beta release. In 
some cases, 0.36 bugs have already been fixed in recent pre-releases.

You think you've found a bug? We believe you!
-->

## Expected behavior and actual behavior.

By providing a raster dataset with RGBA bands, `rasterio.plot.show` should successfully display the RGB figure. However, in the current code, it only displays data from "R" band.

I think the problem comes from [line 96 in plot.py](https://github.com/mapbox/rasterio/blob/73a7c84131eb9e38da70000e2da28869a2f555d2/rasterio/plot.py#L96). In line 96: `source_colorinterp = OrderedDict(zip(source.indexes, source.colorinterp))`, the order of `source.indexes` and `source.colorinterp` should be changed. In other words, `source.colorinterp` should be the key and `source.indexes` should be the value.
(BTW, an unrelated question: why using `OrderedDict`? Can a regular dict do it?)

## Steps to reproduce the problem.

Save the following code to a script and run the script.

```python
import numpy
import rasterio
import rasterio.plot
from matplotlib import pyplot

r = numpy.array([[ 255, 0, 0]], dtype=numpy.uint8)
g = numpy.array([[0, 255, 0]], dtype=numpy.uint8)
b = numpy.array([[0,  0, 255]], dtype=numpy.uint8)
alpha = numpy.array([[255, 255, 255]], dtype=numpy.uint8)

dst = rasterio.open(
    "test.tif", mode="w", driver="GTiff", width=3, height=1, count=4,
    crs=rasterio.crs.CRS.from_epsg(3857),
    transform=rasterio.transform.from_origin(0., 3., 1., 1.),
    dtype=rasterio.uint8)
dst.write_band(1, r)
dst.write_band(2, g)
dst.write_band(3, b)
dst.write_band(4, alpha)
dst.close()

test = rasterio.open("test.tif")
pyplot.figure(figsize=(3, 1))
ax = pyplot.gca()
rasterio.plot.show(test, ax=ax)
pyplot.show()
test.close()
```
The output figure is like this:
<img src="https://dl.dropboxusercontent.com/s/zoe4dmkp8z8brdx/wrong.png?dl=0">

However, the expected figure should be like this:
<img src="https://dl.dropboxusercontent.com/s/uyv0s5mc44t3cba/correct.png?dl=0">

After I changed the [line 96 in plot.py](https://github.com/mapbox/rasterio/blob/73a7c84131eb9e38da70000e2da28869a2f555d2/rasterio/plot.py#L96) to `source_colorinterp = OrderedDict(zip(source.colorinterp, source.indexes))`, I can get the expected figure.

## Operating system

Arch Linux + conda 4.6.2 + python 3.6.8

## Rasterio version and provenance

rasterio v1.0.18 installed using pip 19.0.1.

rasterio.plot.show: rasters with RGBA bands are not displayed as expected
<!--

WELCOME ABOARD!

Hi and welcome to the Rasterio project. We appreciate bug reports, questions
about documentation, and suggestions for new features. This issue template
isn't intended to ward you off; only to intercept and redirect some particular
categories of reports, and to collect a few important facts that issue reporters
often omit.

The primary forum for questions about installation and usage of Rasterio is 
https://rasterio.groups.io/g/main. The authors and other users will answer 
questions when they have expertise to share and time to explain. Please take the
time to craft a clear question and be patient about responses. Please do not
bring these questions to Rasterio's issue tracker, which we want to reserve for
bug reports and other actionable issues.

Questions about development of Rasterio, brainstorming, requests for comment,
and not-yet-actionable proposals are welcome in the project's developers 
discussion group https://rasterio.groups.io/g/dev. Issues opened in Rasterio's
GitHub repo which haven't been socialized there may be perfunctorily closed.

Please note: Rasterio contains extension modules and is thus susceptible to
C library compatibility issues. If you are reporting an installation or module
import issue, please note that this project only accepts reports about problems
with packages downloaded from the Python Package Index. Conda users should take
issues to one of the following trackers:

- https://github.com/ContinuumIO/anaconda-issues/issues
- https://github.com/conda-forge/rasterio-feedstock

Also please note: we are currently working on 1.0 and pre-releases. Bugs found
in version 0.36 will not be fixed except in a 1.0 alpha or beta release. In 
some cases, 0.36 bugs have already been fixed in recent pre-releases.

You think you've found a bug? We believe you!
-->

## Expected behavior and actual behavior.

By providing a raster dataset with RGBA bands, `rasterio.plot.show` should successfully display the RGB figure. However, in the current code, it only displays data from "R" band.

I think the problem comes from [line 96 in plot.py](https://github.com/mapbox/rasterio/blob/73a7c84131eb9e38da70000e2da28869a2f555d2/rasterio/plot.py#L96). In line 96: `source_colorinterp = OrderedDict(zip(source.indexes, source.colorinterp))`, the order of `source.indexes` and `source.colorinterp` should be changed. In other words, `source.colorinterp` should be the key and `source.indexes` should be the value.
(BTW, an unrelated question: why using `OrderedDict`? Can a regular dict do it?)

## Steps to reproduce the problem.

Save the following code to a script and run the script.

```python
import numpy
import rasterio
import rasterio.plot
from matplotlib import pyplot

r = numpy.array([[ 255, 0, 0]], dtype=numpy.uint8)
g = numpy.array([[0, 255, 0]], dtype=numpy.uint8)
b = numpy.array([[0,  0, 255]], dtype=numpy.uint8)
alpha = numpy.array([[255, 255, 255]], dtype=numpy.uint8)

dst = rasterio.open(
    "test.tif", mode="w", driver="GTiff", width=3, height=1, count=4,
    crs=rasterio.crs.CRS.from_epsg(3857),
    transform=rasterio.transform.from_origin(0., 3., 1., 1.),
    dtype=rasterio.uint8)
dst.write_band(1, r)
dst.write_band(2, g)
dst.write_band(3, b)
dst.write_band(4, alpha)
dst.close()

test = rasterio.open("test.tif")
pyplot.figure(figsize=(3, 1))
ax = pyplot.gca()
rasterio.plot.show(test, ax=ax)
pyplot.show()
test.close()
```
The output figure is like this:
<img src="https://dl.dropboxusercontent.com/s/zoe4dmkp8z8brdx/wrong.png?dl=0">

However, the expected figure should be like this:
<img src="https://dl.dropboxusercontent.com/s/uyv0s5mc44t3cba/correct.png?dl=0">

After I changed the [line 96 in plot.py](https://github.com/mapbox/rasterio/blob/73a7c84131eb9e38da70000e2da28869a2f555d2/rasterio/plot.py#L96) to `source_colorinterp = OrderedDict(zip(source.colorinterp, source.indexes))`, I can get the expected figure.

## Operating system

Arch Linux + conda 4.6.2 + python 3.6.8

## Rasterio version and provenance

rasterio v1.0.18 installed using pip 19.0.1.



Discussion:
Any news on this? It seems like a pretty big bug, and the fix seems easy...
@giacomov rasterio isn't a visualization library, so issues like this one are relatively low priority. I need to focus on core bugs. Of course, I'm happy to review PRs!
@sgillies makes sense. PR is coming then! Thanks,
Any news on this? It seems like a pretty big bug, and the fix seems easy...
@giacomov rasterio isn't a visualization library, so issues like this one are relatively low priority. I need to focus on core bugs. Of course, I'm happy to review PRs!
@sgillies makes sense. PR is coming then! Thanks,

Resolving patch:
diff --git a/rasterio/plot.py b/rasterio/plot.py
--- a/rasterio/plot.py
+++ b/rasterio/plot.py
@@ -93,10 +93,19 @@ def show(source, with_bounds=True, contour=False, contour_label_kws=None,
             arr = source.read(1, masked=True)
         else:
             try:
-                source_colorinterp = OrderedDict(zip(source.indexes, source.colorinterp))
+
+                # Lookup table for the color space in the source file. This will allow us to re-order it
+                # to RGB if needed
+                source_colorinterp = OrderedDict(zip(source.colorinterp, source.indexes))
+
                 colorinterp = rasterio.enums.ColorInterp
+
+                # Gather the indexes of the RGB channels in that order
                 rgb_indexes = [source_colorinterp[ci] for ci in
                                (colorinterp.red, colorinterp.green, colorinterp.blue)]
+
+                # Read the image in the proper order so the numpy array will have the colors in the
+                # order expected by matplotlib (RGB)
                 arr = source.read(rgb_indexes, masked=True)
                 arr = reshape_as_image(arr)
 


Test patch: