We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
show_hist() fails with nans
I am getting an `UnboundLocalError: local variable 'ymin' referenced before assignment` when I am trying to use the show_hist() function in the plotting module.  

```
import rasterio
from rasterio.plot import show_hist
from rasterio.plot import show
import matplotlib.pyplot as plt

fname = r"C:\workspace\GLCM\output\glcm_rasters\2014_05\10\R02028_10_asm.tif"
src = rasterio.open(fname)

fig, (axrgb, axhist) = plt.subplots(1, 2, figsize=(14,7))
show(src, ax=axrgb)
show_hist(src, bins=50, histtype='bar', lw=0.0, stacked=False, alpha=0.3, ax=axhist)
 plt.show()
```

[here](https://drive.google.com/file/d/0B17WT3pXaqrYcUVQbXRVYkxqeXc/view?usp=sharing) is the offending file.

conda info:

```
             platform : win-64
        conda version : 4.1.11
    conda-env version : 2.5.2
  conda-build version : 1.20.0
       python version : 2.7.11.final.0
     requests version : 2.9.1
     root environment : c:\Anaconda2  (writable)
  default environment : c:\Anaconda2
     envs directories : c:\Anaconda2\envs
        package cache : c:\Anaconda2\pkgs
         channel URLs : https://repo.continuum.io/pkgs/free/win-64/
                        https://repo.continuum.io/pkgs/free/noarch/
                        https://repo.continuum.io/pkgs/pro/win-64/
                        https://repo.continuum.io/pkgs/pro/noarch/
                        https://repo.continuum.io/pkgs/msys2/win-64/
                        https://repo.continuum.io/pkgs/msys2/noarch/
          config file : None
         offline mode : False
    is foreign system : False
```

Package info:

```
rasterio                  0.36.0                    <pip>
matplotlib                1.5.1               np110py27_0
```


--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `rasterio/plot.py`
Content:
```
1 """Implementations of various common operations.
2 
3 Including `show()` for displaying an array or with matplotlib.
4 Most can handle a numpy array or `rasterio.Band()`.
5 Primarily supports `$ rio insp`.
6 """
7 
8 from __future__ import absolute_import
9 
10 import logging
11 import warnings
12 
13 import numpy as np
14 
15 import rasterio
16 from rasterio.io import DatasetReader
17 from rasterio.transform import guard_transform
18 from rasterio.compat import zip_longest
19 
20 logger = logging.getLogger(__name__)
21 
22 
23 def get_plt():
24     """import matplotlib.pyplot
25     raise import error if matplotlib is not installed
26     """
27     try:
28         import matplotlib.pyplot as plt
29         return plt
30     except (ImportError, RuntimeError):  # pragma: no cover
31         msg = "Could not import matplotlib\n"
32         msg += "matplotlib required for plotting functions"
33         raise ImportError(msg)
34 
35 
36 def show(source, with_bounds=True, contour=False, contour_label_kws=None,
37          ax=None, title=None, transform=None, **kwargs):
38     """Display a raster or raster band using matplotlib.
39 
40     Parameters
41     ----------
42     source : array-like in raster axis order,
43         or (raster dataset, bidx) tuple,
44         or raster dataset,
45         If the tuple (raster dataset, bidx),
46         selects band `bidx` from raster.  If raster dataset display the rgb image
47         as defined in the colorinterp metadata, or default to first band.
48     with_bounds : bool (opt)
49         Whether to change the image extent to the spatial bounds of the image,
50         rather than pixel coordinates. Only works when source is
51         (raster dataset, bidx) or raster dataset.
52     contour : bool (opt)
53         Whether to plot the raster data as contours
54     contour_label_kws : dictionary (opt)
55         Keyword arguments for labeling the contours,
56         empty dictionary for no labels.
57     ax : matplotlib axis (opt)
58         Axis to plot on, otherwise uses current axis.
59     title : str, optional
60         Title for the figure.
61     transform : Affine, optional
62         Defines the affine transform if source is an array
63     **kwargs : key, value pairings optional
64         These will be passed to the matplotlib imshow or contour method
65         depending on contour argument.
66         See full lists at:
67         http://matplotlib.org/api/axes_api.html?highlight=imshow#matplotlib.axes.Axes.imshow
68         or
69         http://matplotlib.org/api/axes_api.html?highlight=imshow#matplotlib.axes.Axes.contour
70 
71     Returns
72     -------
73     ax : matplotlib Axes
74         Axes with plot.
75     """
76     plt = get_plt()
77 
78     if isinstance(source, tuple):
79         arr = source[0].read(source[1])
80         if with_bounds:
81             kwargs['extent'] = plotting_extent(source[0])
82     elif isinstance(source, DatasetReader):
83         if source.count == 1:
84             arr = source.read(1, masked=True)
85         else:
86             try:
87                 source_colorinterp = {source.colorinterp(n): n for n in source.indexes}
88                 colorinterp = rasterio.enums.ColorInterp
89                 rgb_indexes = [source_colorinterp[ci] for ci in
90                                (colorinterp.red, colorinterp.green, colorinterp.blue)]
91                 arr = source.read(rgb_indexes, masked=True)
92                 arr = reshape_as_image(arr)
93 
94                 if with_bounds:
95                     kwargs['extent'] = plotting_extent(source)
96             except KeyError:
97                 arr = source.read(1, masked=True)
98     else:
99         # The source is a numpy array reshape it to image if it has 3+ bands
100         source = np.ma.squeeze(source)
101         if len(source.shape) >= 3:
102             arr = reshape_as_image(source)
103         else:
104             arr = source
105         if transform and with_bounds:
106             kwargs['extent'] = plotting_extent(arr, transform)
107 
108     show = False
109     if not ax:
110         show = True
111         ax = plt.gca()
112 
113     if contour:
114         if 'cmap' not in kwargs:
115             kwargs['colors'] = kwargs.get('colors', 'red')
116         kwargs['linewidths'] = kwargs.get('linewidths', 1.5)
117         kwargs['alpha'] = kwargs.get('alpha', 0.8)
118 
119         C = ax.contour(arr, origin='upper', **kwargs)
120         if contour_label_kws is None:
121             # no explicit label kws passed use defaults
122             contour_label_kws = dict(fontsize=8,
123                                      inline=True)
124         if contour_label_kws:
125             ax.clabel(C, **contour_label_kws)
126     else:
127         ax.imshow(arr, **kwargs)
128     if title:
129         ax.set_title(title, fontweight='bold')
130 
131     if show:
132         plt.show()
133 
134     return ax
135 
136 
137 def plotting_extent(source, transform=None):
138     """Returns an extent in the format needed
139      for matplotlib's imshow (left, right, bottom, top)
140      instead of rasterio's bounds (left, bottom, top, right)
141 
142     Parameters
143     ----------
144     source : raster dataset or array in image order (see reshape_as_image)
145     transform: Affine, required if source is array
146     """
147     if hasattr(source, 'bounds'):
148         extent = (source.bounds.left, source.bounds.right,
149                   source.bounds.bottom, source.bounds.top)
150     elif not transform:
151         raise ValueError(
152             "transform is required if source is an array")
153     else:
154         transform = guard_transform(transform)
155         rows, cols = source.shape[0:2]
156         left, top = transform * (0, 0)
157         right, bottom = transform * (cols, rows)
158         extent = (left, right, bottom, top)
159 
160     return extent
161 
162 
163 def reshape_as_image(arr):
164     """Returns the source array reshaped into the order
165     expected by image processing and visualization software
166     (matplotlib, scikit-image, etc)
167     by swapping the axes order from (bands, rows, columns)
168     to (rows, columns, bands)
169 
170     Parameters
171     ----------
172     source : array-like in a of format (bands, rows, columns)
173     """
174     # swap the axes order from (bands, rows, columns) to (rows, columns, bands)
175     im = np.ma.transpose(arr, [1,2,0])
176     return im
177 
178 
179 
180 def reshape_as_raster(arr):
181     """Returns the array in a raster order
182     by swapping the axes order from (rows, columns, bands)
183     to (bands, rows, columns)
184 
185     Parameters
186     ----------
187     arr : array-like in the image form of (rows, columns, bands)
188     """
189     # swap the axes order from (rows, columns, bands) to (bands, rows, columns)
190     im = np.transpose(arr, [2,0,1])
191     return im
192 
193 
194 def show_hist(source, bins=10, masked=True, title='Histogram', ax=None, **kwargs):
195     """Easily display a histogram with matplotlib.
196 
197     Parameters
198     ----------
199     source : np.array or DatasetReader, rasterio.Band or tuple(dataset, bidx)
200         Input data to display.  The first three arrays in multi-dimensional
201         arrays are plotted as red, green, and blue.
202     bins : int, optional
203         Compute histogram across N bins.
204     masked : bool, optional
205         When working with a `rasterio.Band()` object, specifies if the data
206         should be masked on read.
207     title : str, optional
208         Title for the figure.
209     ax : matplotlib axes (opt)
210         The raster will be added to this axes if passed.
211     **kwargs : optional keyword arguments
212         These will be passed to the matplotlib hist method. See full list at:
213         http://matplotlib.org/api/axes_api.html?highlight=imshow#matplotlib.axes.Axes.hist
214     """
215     plt = get_plt()
216 
217     if isinstance(source, DatasetReader):
218         arr = source.read(masked=masked)
219     elif isinstance(source, (tuple, rasterio.Band)):
220         arr = source[0].read(source[1], masked=masked)
221     else:
222         arr = source
223 
224     # The histogram is computed individually for each 'band' in the array
225     # so we need the overall min/max to constrain the plot
226     rng = arr.min(), arr.max()
227 
228     if len(arr.shape) is 2:
229         arr = np.expand_dims(arr.flatten(), 0).T
230         colors = ['gold']
231     else:
232         arr = arr.reshape(arr.shape[0], -1).T
233         colors = ['red', 'green', 'blue', 'violet', 'gold', 'saddlebrown']
234 
235     # The goal is to provide a curated set of colors for working with
236     # smaller datasets and let matplotlib define additional colors when
237     # working with larger datasets.
238     if arr.shape[-1] > len(colors):
239         n = arr.shape[-1] - len(colors)
240         colors.extend(np.ndarray.tolist(plt.get_cmap('Accent')(np.linspace(0, 1, n))))
241     else:
242         colors = colors[:arr.shape[-1]]
243 
244     # If a rasterio.Band() is given make sure the proper index is displayed
245     # in the legend.
246     if isinstance(source, (tuple, rasterio.Band)):
247         labels = [str(source[1])]
248     else:
249         labels = (str(i + 1) for i in range(len(arr)))
250 
251     if ax:
252         show = False
253     else:
254         show = True
255         ax = plt.gca()
256 
257     fig = ax.get_figure()
258 
259     ax.hist(arr,
260             bins=bins,
261             color=colors,
262             label=labels,
263             range=rng,
264             **kwargs)
265 
266     ax.legend(loc="upper right")
267     ax.set_title(title, fontweight='bold')
268     ax.grid(True)
269     ax.set_xlabel('DN')
270     ax.set_ylabel('Frequency')
271     if show:
272         plt.show()
273
```
--- END FILES ---

Please first localize the bug based on the issue statement, and then generate a patch according to the `git diff` format fenced by three backticks.

Here is an example:

```diff
diff --git a/examples/server_async.py b/examples/server_async.py
--- a/examples/server_async.py
+++ b/examples/server_async.py
@@ -313,4 +313,4 @@
 
 
 if __name__ == "__main__":
-    asyncio.run(run_async_server("."), debug=True)
+    asyncio.run(run_async_server(), debug=True)
diff --git a/examples/server_sync.py b/examples/server_sync.py
--- a/examples/server_sync.py
+++ b/examples/server_sync.py
@@ -313,5 +313,5 @@
 
 
 if __name__ == "__main__":
-    server = run_sync_server(".")
+    server = run_sync_server()
     server.shutdown()

```

diff --git a/rasterio/plot.py b/rasterio/plot.py
--- a/rasterio/plot.py
+++ b/rasterio/plot.py
@@ -223,7 +223,7 @@
 
     # The histogram is computed individually for each 'band' in the array
     # so we need the overall min/max to constrain the plot
-    rng = arr.min(), arr.max()
+    rng = np.nanmin(arr), np.nanmax(arr)
 
     if len(arr.shape) is 2:
         arr = np.expand_dims(arr.flatten(), 0).T

{"golden_diff": "diff --git a/rasterio/plot.py b/rasterio/plot.py\n--- a/rasterio/plot.py\n+++ b/rasterio/plot.py\n@@ -223,7 +223,7 @@\n \n     # The histogram is computed individually for each 'band' in the array\n     # so we need the overall min/max to constrain the plot\n-    rng = arr.min(), arr.max()\n+    rng = np.nanmin(arr), np.nanmax(arr)\n \n     if len(arr.shape) is 2:\n         arr = np.expand_dims(arr.flatten(), 0).T\n", "issue": "show_hist() fails with nans\nI am getting an `UnboundLocalError: local variable 'ymin' referenced before assignment` when I am trying to use the show_hist() function in the plotting module.  \n\n```\nimport rasterio\nfrom rasterio.plot import show_hist\nfrom rasterio.plot import show\nimport matplotlib.pyplot as plt\n\nfname = r\"C:\\workspace\\GLCM\\output\\glcm_rasters\\2014_05\\10\\R02028_10_asm.tif\"\nsrc = rasterio.open(fname)\n\nfig, (axrgb, axhist) = plt.subplots(1, 2, figsize=(14,7))\nshow(src, ax=axrgb)\nshow_hist(src, bins=50, histtype='bar', lw=0.0, stacked=False, alpha=0.3, ax=axhist)\n plt.show()\n```\n\n[here](https://drive.google.com/file/d/0B17WT3pXaqrYcUVQbXRVYkxqeXc/view?usp=sharing) is the offending file.\n\nconda info:\n\n```\n             platform : win-64\n        conda version : 4.1.11\n    conda-env version : 2.5.2\n  conda-build version : 1.20.0\n       python version : 2.7.11.final.0\n     requests version : 2.9.1\n     root environment : c:\\Anaconda2  (writable)\n  default environment : c:\\Anaconda2\n     envs directories : c:\\Anaconda2\\envs\n        package cache : c:\\Anaconda2\\pkgs\n         channel URLs : https://repo.continuum.io/pkgs/free/win-64/\n                        https://repo.continuum.io/pkgs/free/noarch/\n                        https://repo.continuum.io/pkgs/pro/win-64/\n                        https://repo.continuum.io/pkgs/pro/noarch/\n                        https://repo.continuum.io/pkgs/msys2/win-64/\n                        https://repo.continuum.io/pkgs/msys2/noarch/\n          config file : None\n         offline mode : False\n    is foreign system : False\n```\n\nPackage info:\n\n```\nrasterio                  0.36.0                    <pip>\nmatplotlib                1.5.1               np110py27_0\n```\n\n", "before_files": [{"content": "\"\"\"Implementations of various common operations.\n\nIncluding `show()` for displaying an array or with matplotlib.\nMost can handle a numpy array or `rasterio.Band()`.\nPrimarily supports `$ rio insp`.\n\"\"\"\n\nfrom __future__ import absolute_import\n\nimport logging\nimport warnings\n\nimport numpy as np\n\nimport rasterio\nfrom rasterio.io import DatasetReader\nfrom rasterio.transform import guard_transform\nfrom rasterio.compat import zip_longest\n\nlogger = logging.getLogger(__name__)\n\n\ndef get_plt():\n    \"\"\"import matplotlib.pyplot\n    raise import error if matplotlib is not installed\n    \"\"\"\n    try:\n        import matplotlib.pyplot as plt\n        return plt\n    except (ImportError, RuntimeError):  # pragma: no cover\n        msg = \"Could not import matplotlib\\n\"\n        msg += \"matplotlib required for plotting functions\"\n        raise ImportError(msg)\n\n\ndef show(source, with_bounds=True, contour=False, contour_label_kws=None,\n         ax=None, title=None, transform=None, **kwargs):\n    \"\"\"Display a raster or raster band using matplotlib.\n\n    Parameters\n    ----------\n    source : array-like in raster axis order,\n        or (raster dataset, bidx) tuple,\n        or raster dataset,\n        If the tuple (raster dataset, bidx),\n        selects band `bidx` from raster.  If raster dataset display the rgb image\n        as defined in the colorinterp metadata, or default to first band.\n    with_bounds : bool (opt)\n        Whether to change the image extent to the spatial bounds of the image,\n        rather than pixel coordinates. Only works when source is\n        (raster dataset, bidx) or raster dataset.\n    contour : bool (opt)\n        Whether to plot the raster data as contours\n    contour_label_kws : dictionary (opt)\n        Keyword arguments for labeling the contours,\n        empty dictionary for no labels.\n    ax : matplotlib axis (opt)\n        Axis to plot on, otherwise uses current axis.\n    title : str, optional\n        Title for the figure.\n    transform : Affine, optional\n        Defines the affine transform if source is an array\n    **kwargs : key, value pairings optional\n        These will be passed to the matplotlib imshow or contour method\n        depending on contour argument.\n        See full lists at:\n        http://matplotlib.org/api/axes_api.html?highlight=imshow#matplotlib.axes.Axes.imshow\n        or\n        http://matplotlib.org/api/axes_api.html?highlight=imshow#matplotlib.axes.Axes.contour\n\n    Returns\n    -------\n    ax : matplotlib Axes\n        Axes with plot.\n    \"\"\"\n    plt = get_plt()\n\n    if isinstance(source, tuple):\n        arr = source[0].read(source[1])\n        if with_bounds:\n            kwargs['extent'] = plotting_extent(source[0])\n    elif isinstance(source, DatasetReader):\n        if source.count == 1:\n            arr = source.read(1, masked=True)\n        else:\n            try:\n                source_colorinterp = {source.colorinterp(n): n for n in source.indexes}\n                colorinterp = rasterio.enums.ColorInterp\n                rgb_indexes = [source_colorinterp[ci] for ci in\n                               (colorinterp.red, colorinterp.green, colorinterp.blue)]\n                arr = source.read(rgb_indexes, masked=True)\n                arr = reshape_as_image(arr)\n\n                if with_bounds:\n                    kwargs['extent'] = plotting_extent(source)\n            except KeyError:\n                arr = source.read(1, masked=True)\n    else:\n        # The source is a numpy array reshape it to image if it has 3+ bands\n        source = np.ma.squeeze(source)\n        if len(source.shape) >= 3:\n            arr = reshape_as_image(source)\n        else:\n            arr = source\n        if transform and with_bounds:\n            kwargs['extent'] = plotting_extent(arr, transform)\n\n    show = False\n    if not ax:\n        show = True\n        ax = plt.gca()\n\n    if contour:\n        if 'cmap' not in kwargs:\n            kwargs['colors'] = kwargs.get('colors', 'red')\n        kwargs['linewidths'] = kwargs.get('linewidths', 1.5)\n        kwargs['alpha'] = kwargs.get('alpha', 0.8)\n\n        C = ax.contour(arr, origin='upper', **kwargs)\n        if contour_label_kws is None:\n            # no explicit label kws passed use defaults\n            contour_label_kws = dict(fontsize=8,\n                                     inline=True)\n        if contour_label_kws:\n            ax.clabel(C, **contour_label_kws)\n    else:\n        ax.imshow(arr, **kwargs)\n    if title:\n        ax.set_title(title, fontweight='bold')\n\n    if show:\n        plt.show()\n\n    return ax\n\n\ndef plotting_extent(source, transform=None):\n    \"\"\"Returns an extent in the format needed\n     for matplotlib's imshow (left, right, bottom, top)\n     instead of rasterio's bounds (left, bottom, top, right)\n\n    Parameters\n    ----------\n    source : raster dataset or array in image order (see reshape_as_image)\n    transform: Affine, required if source is array\n    \"\"\"\n    if hasattr(source, 'bounds'):\n        extent = (source.bounds.left, source.bounds.right,\n                  source.bounds.bottom, source.bounds.top)\n    elif not transform:\n        raise ValueError(\n            \"transform is required if source is an array\")\n    else:\n        transform = guard_transform(transform)\n        rows, cols = source.shape[0:2]\n        left, top = transform * (0, 0)\n        right, bottom = transform * (cols, rows)\n        extent = (left, right, bottom, top)\n\n    return extent\n\n\ndef reshape_as_image(arr):\n    \"\"\"Returns the source array reshaped into the order\n    expected by image processing and visualization software\n    (matplotlib, scikit-image, etc)\n    by swapping the axes order from (bands, rows, columns)\n    to (rows, columns, bands)\n\n    Parameters\n    ----------\n    source : array-like in a of format (bands, rows, columns)\n    \"\"\"\n    # swap the axes order from (bands, rows, columns) to (rows, columns, bands)\n    im = np.ma.transpose(arr, [1,2,0])\n    return im\n\n\n\ndef reshape_as_raster(arr):\n    \"\"\"Returns the array in a raster order\n    by swapping the axes order from (rows, columns, bands)\n    to (bands, rows, columns)\n\n    Parameters\n    ----------\n    arr : array-like in the image form of (rows, columns, bands)\n    \"\"\"\n    # swap the axes order from (rows, columns, bands) to (bands, rows, columns)\n    im = np.transpose(arr, [2,0,1])\n    return im\n\n\ndef show_hist(source, bins=10, masked=True, title='Histogram', ax=None, **kwargs):\n    \"\"\"Easily display a histogram with matplotlib.\n\n    Parameters\n    ----------\n    source : np.array or DatasetReader, rasterio.Band or tuple(dataset, bidx)\n        Input data to display.  The first three arrays in multi-dimensional\n        arrays are plotted as red, green, and blue.\n    bins : int, optional\n        Compute histogram across N bins.\n    masked : bool, optional\n        When working with a `rasterio.Band()` object, specifies if the data\n        should be masked on read.\n    title : str, optional\n        Title for the figure.\n    ax : matplotlib axes (opt)\n        The raster will be added to this axes if passed.\n    **kwargs : optional keyword arguments\n        These will be passed to the matplotlib hist method. See full list at:\n        http://matplotlib.org/api/axes_api.html?highlight=imshow#matplotlib.axes.Axes.hist\n    \"\"\"\n    plt = get_plt()\n\n    if isinstance(source, DatasetReader):\n        arr = source.read(masked=masked)\n    elif isinstance(source, (tuple, rasterio.Band)):\n        arr = source[0].read(source[1], masked=masked)\n    else:\n        arr = source\n\n    # The histogram is computed individually for each 'band' in the array\n    # so we need the overall min/max to constrain the plot\n    rng = arr.min(), arr.max()\n\n    if len(arr.shape) is 2:\n        arr = np.expand_dims(arr.flatten(), 0).T\n        colors = ['gold']\n    else:\n        arr = arr.reshape(arr.shape[0], -1).T\n        colors = ['red', 'green', 'blue', 'violet', 'gold', 'saddlebrown']\n\n    # The goal is to provide a curated set of colors for working with\n    # smaller datasets and let matplotlib define additional colors when\n    # working with larger datasets.\n    if arr.shape[-1] > len(colors):\n        n = arr.shape[-1] - len(colors)\n        colors.extend(np.ndarray.tolist(plt.get_cmap('Accent')(np.linspace(0, 1, n))))\n    else:\n        colors = colors[:arr.shape[-1]]\n\n    # If a rasterio.Band() is given make sure the proper index is displayed\n    # in the legend.\n    if isinstance(source, (tuple, rasterio.Band)):\n        labels = [str(source[1])]\n    else:\n        labels = (str(i + 1) for i in range(len(arr)))\n\n    if ax:\n        show = False\n    else:\n        show = True\n        ax = plt.gca()\n\n    fig = ax.get_figure()\n\n    ax.hist(arr,\n            bins=bins,\n            color=colors,\n            label=labels,\n            range=rng,\n            **kwargs)\n\n    ax.legend(loc=\"upper right\")\n    ax.set_title(title, fontweight='bold')\n    ax.grid(True)\n    ax.set_xlabel('DN')\n    ax.set_ylabel('Frequency')\n    if show:\n        plt.show()\n", "path": "rasterio/plot.py"}], "after_files": [{"content": "\"\"\"Implementations of various common operations.\n\nIncluding `show()` for displaying an array or with matplotlib.\nMost can handle a numpy array or `rasterio.Band()`.\nPrimarily supports `$ rio insp`.\n\"\"\"\n\nfrom __future__ import absolute_import\n\nimport logging\nimport warnings\n\nimport numpy as np\n\nimport rasterio\nfrom rasterio.io import DatasetReader\nfrom rasterio.transform import guard_transform\nfrom rasterio.compat import zip_longest\n\nlogger = logging.getLogger(__name__)\n\n\ndef get_plt():\n    \"\"\"import matplotlib.pyplot\n    raise import error if matplotlib is not installed\n    \"\"\"\n    try:\n        import matplotlib.pyplot as plt\n        return plt\n    except (ImportError, RuntimeError):  # pragma: no cover\n        msg = \"Could not import matplotlib\\n\"\n        msg += \"matplotlib required for plotting functions\"\n        raise ImportError(msg)\n\n\ndef show(source, with_bounds=True, contour=False, contour_label_kws=None,\n         ax=None, title=None, transform=None, **kwargs):\n    \"\"\"Display a raster or raster band using matplotlib.\n\n    Parameters\n    ----------\n    source : array-like in raster axis order,\n        or (raster dataset, bidx) tuple,\n        or raster dataset,\n        If the tuple (raster dataset, bidx),\n        selects band `bidx` from raster.  If raster dataset display the rgb image\n        as defined in the colorinterp metadata, or default to first band.\n    with_bounds : bool (opt)\n        Whether to change the image extent to the spatial bounds of the image,\n        rather than pixel coordinates. Only works when source is\n        (raster dataset, bidx) or raster dataset.\n    contour : bool (opt)\n        Whether to plot the raster data as contours\n    contour_label_kws : dictionary (opt)\n        Keyword arguments for labeling the contours,\n        empty dictionary for no labels.\n    ax : matplotlib axis (opt)\n        Axis to plot on, otherwise uses current axis.\n    title : str, optional\n        Title for the figure.\n    transform : Affine, optional\n        Defines the affine transform if source is an array\n    **kwargs : key, value pairings optional\n        These will be passed to the matplotlib imshow or contour method\n        depending on contour argument.\n        See full lists at:\n        http://matplotlib.org/api/axes_api.html?highlight=imshow#matplotlib.axes.Axes.imshow\n        or\n        http://matplotlib.org/api/axes_api.html?highlight=imshow#matplotlib.axes.Axes.contour\n\n    Returns\n    -------\n    ax : matplotlib Axes\n        Axes with plot.\n    \"\"\"\n    plt = get_plt()\n\n    if isinstance(source, tuple):\n        arr = source[0].read(source[1])\n        if with_bounds:\n            kwargs['extent'] = plotting_extent(source[0])\n    elif isinstance(source, DatasetReader):\n        if source.count == 1:\n            arr = source.read(1, masked=True)\n        else:\n            try:\n                source_colorinterp = {source.colorinterp(n): n for n in source.indexes}\n                colorinterp = rasterio.enums.ColorInterp\n                rgb_indexes = [source_colorinterp[ci] for ci in\n                               (colorinterp.red, colorinterp.green, colorinterp.blue)]\n                arr = source.read(rgb_indexes, masked=True)\n                arr = reshape_as_image(arr)\n\n                if with_bounds:\n                    kwargs['extent'] = plotting_extent(source)\n            except KeyError:\n                arr = source.read(1, masked=True)\n    else:\n        # The source is a numpy array reshape it to image if it has 3+ bands\n        source = np.ma.squeeze(source)\n        if len(source.shape) >= 3:\n            arr = reshape_as_image(source)\n        else:\n            arr = source\n        if transform and with_bounds:\n            kwargs['extent'] = plotting_extent(arr, transform)\n\n    show = False\n    if not ax:\n        show = True\n        ax = plt.gca()\n\n    if contour:\n        if 'cmap' not in kwargs:\n            kwargs['colors'] = kwargs.get('colors', 'red')\n        kwargs['linewidths'] = kwargs.get('linewidths', 1.5)\n        kwargs['alpha'] = kwargs.get('alpha', 0.8)\n\n        C = ax.contour(arr, origin='upper', **kwargs)\n        if contour_label_kws is None:\n            # no explicit label kws passed use defaults\n            contour_label_kws = dict(fontsize=8,\n                                     inline=True)\n        if contour_label_kws:\n            ax.clabel(C, **contour_label_kws)\n    else:\n        ax.imshow(arr, **kwargs)\n    if title:\n        ax.set_title(title, fontweight='bold')\n\n    if show:\n        plt.show()\n\n    return ax\n\n\ndef plotting_extent(source, transform=None):\n    \"\"\"Returns an extent in the format needed\n     for matplotlib's imshow (left, right, bottom, top)\n     instead of rasterio's bounds (left, bottom, top, right)\n\n    Parameters\n    ----------\n    source : raster dataset or array in image order (see reshape_as_image)\n    transform: Affine, required if source is array\n    \"\"\"\n    if hasattr(source, 'bounds'):\n        extent = (source.bounds.left, source.bounds.right,\n                  source.bounds.bottom, source.bounds.top)\n    elif not transform:\n        raise ValueError(\n            \"transform is required if source is an array\")\n    else:\n        transform = guard_transform(transform)\n        rows, cols = source.shape[0:2]\n        left, top = transform * (0, 0)\n        right, bottom = transform * (cols, rows)\n        extent = (left, right, bottom, top)\n\n    return extent\n\n\ndef reshape_as_image(arr):\n    \"\"\"Returns the source array reshaped into the order\n    expected by image processing and visualization software\n    (matplotlib, scikit-image, etc)\n    by swapping the axes order from (bands, rows, columns)\n    to (rows, columns, bands)\n\n    Parameters\n    ----------\n    source : array-like in a of format (bands, rows, columns)\n    \"\"\"\n    # swap the axes order from (bands, rows, columns) to (rows, columns, bands)\n    im = np.ma.transpose(arr, [1,2,0])\n    return im\n\n\n\ndef reshape_as_raster(arr):\n    \"\"\"Returns the array in a raster order\n    by swapping the axes order from (rows, columns, bands)\n    to (bands, rows, columns)\n\n    Parameters\n    ----------\n    arr : array-like in the image form of (rows, columns, bands)\n    \"\"\"\n    # swap the axes order from (rows, columns, bands) to (bands, rows, columns)\n    im = np.transpose(arr, [2,0,1])\n    return im\n\n\ndef show_hist(source, bins=10, masked=True, title='Histogram', ax=None, **kwargs):\n    \"\"\"Easily display a histogram with matplotlib.\n\n    Parameters\n    ----------\n    source : np.array or DatasetReader, rasterio.Band or tuple(dataset, bidx)\n        Input data to display.  The first three arrays in multi-dimensional\n        arrays are plotted as red, green, and blue.\n    bins : int, optional\n        Compute histogram across N bins.\n    masked : bool, optional\n        When working with a `rasterio.Band()` object, specifies if the data\n        should be masked on read.\n    title : str, optional\n        Title for the figure.\n    ax : matplotlib axes (opt)\n        The raster will be added to this axes if passed.\n    **kwargs : optional keyword arguments\n        These will be passed to the matplotlib hist method. See full list at:\n        http://matplotlib.org/api/axes_api.html?highlight=imshow#matplotlib.axes.Axes.hist\n    \"\"\"\n    plt = get_plt()\n\n    if isinstance(source, DatasetReader):\n        arr = source.read(masked=masked)\n    elif isinstance(source, (tuple, rasterio.Band)):\n        arr = source[0].read(source[1], masked=masked)\n    else:\n        arr = source\n\n    # The histogram is computed individually for each 'band' in the array\n    # so we need the overall min/max to constrain the plot\n    rng = np.nanmin(arr), np.nanmax(arr)\n\n    if len(arr.shape) is 2:\n        arr = np.expand_dims(arr.flatten(), 0).T\n        colors = ['gold']\n    else:\n        arr = arr.reshape(arr.shape[0], -1).T\n        colors = ['red', 'green', 'blue', 'violet', 'gold', 'saddlebrown']\n\n    # The goal is to provide a curated set of colors for working with\n    # smaller datasets and let matplotlib define additional colors when\n    # working with larger datasets.\n    if arr.shape[-1] > len(colors):\n        n = arr.shape[-1] - len(colors)\n        colors.extend(np.ndarray.tolist(plt.get_cmap('Accent')(np.linspace(0, 1, n))))\n    else:\n        colors = colors[:arr.shape[-1]]\n\n    # If a rasterio.Band() is given make sure the proper index is displayed\n    # in the legend.\n    if isinstance(source, (tuple, rasterio.Band)):\n        labels = [str(source[1])]\n    else:\n        labels = (str(i + 1) for i in range(len(arr)))\n\n    if ax:\n        show = False\n    else:\n        show = True\n        ax = plt.gca()\n\n    fig = ax.get_figure()\n\n    ax.hist(arr,\n            bins=bins,\n            color=colors,\n            label=labels,\n            range=rng,\n            **kwargs)\n\n    ax.legend(loc=\"upper right\")\n    ax.set_title(title, fontweight='bold')\n    ax.grid(True)\n    ax.set_xlabel('DN')\n    ax.set_ylabel('Frequency')\n    if show:\n        plt.show()\n", "path": "rasterio/plot.py"}]}