We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
Add a function to easily display a matotlib histogram in rio-insp
See #455 for background 

Might be useful to surface this both in `rio insp` and as `rasterio.show_histogram()`.


--- 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/tool.py`
Content:
```
1 
2 import code
3 import collections
4 import logging
5 
6 try:
7     import matplotlib.pyplot as plt
8 except ImportError:
9     plt = None
10 
11 import numpy
12 
13 import rasterio
14 
15 
16 logger = logging.getLogger('rasterio')
17 
18 Stats = collections.namedtuple('Stats', ['min', 'max', 'mean'])
19 
20 # Collect dictionary of functions for use in the interpreter in main()
21 funcs = locals()
22 
23 
24 def show(source, cmap='gray'):
25     """Show a raster using matplotlib.
26 
27     The raster may be either an ndarray or a (dataset, bidx)
28     tuple.
29     """
30     if isinstance(source, tuple):
31         arr = source[0].read(source[1])
32     else:
33         arr = source
34     if plt is not None:
35         plt.imshow(arr, cmap=cmap)
36         plt.show()
37     else:
38         raise ImportError("matplotlib could not be imported")
39 
40 
41 def stats(source):
42     """Return a tuple with raster min, max, and mean.
43     """
44     if isinstance(source, tuple):
45         arr = source[0].read(source[1])
46     else:
47         arr = source
48     return Stats(numpy.min(arr), numpy.max(arr), numpy.mean(arr))
49 
50 
51 def main(banner, dataset, alt_interpreter=None):
52     """ Main entry point for use with python interpreter """
53     local = dict(funcs, src=dataset, np=numpy, rio=rasterio, plt=plt)
54     if not alt_interpreter:
55         code.interact(banner, local=local)
56     elif alt_interpreter == 'ipython':
57         import IPython
58         IPython.InteractiveShell.banner1 = banner
59         IPython.start_ipython(argv=[], user_ns=local)
60     else:
61         raise ValueError("Unsupported interpreter '%s'" % alt_interpreter)
62 
63     return 0
64
```
--- 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/tool.py b/rasterio/tool.py
--- a/rasterio/tool.py
+++ b/rasterio/tool.py
@@ -11,6 +11,7 @@
 import numpy
 
 import rasterio
+from rasterio.five import zip_longest
 
 
 logger = logging.getLogger('rasterio')
@@ -48,6 +49,76 @@
     return Stats(numpy.min(arr), numpy.max(arr), numpy.mean(arr))
 
 
+def show_hist(source, bins=10, masked=True, title='Histogram'):
+
+    """
+    Easily display a histogram with matplotlib.
+
+    Parameters
+    ----------
+    bins : int, optional
+        Compute histogram across N bins.
+    data : np.array or rasterio.Band or tuple(dataset, bidx)
+        Input data to display.  The first three arrays in multi-dimensional
+        arrays are plotted as red, green, and blue.
+    masked : bool, optional
+        When working with a `rasterio.Band()` object, specifies if the data
+        should be masked on read.
+    title : str, optional
+        Title for the figure.
+    """
+
+    if plt is None:
+        raise ImportError("Could not import matplotlib")
+
+    if isinstance(source, (tuple, rasterio.Band)):
+        arr = source[0].read(source[1], masked=masked)
+    else:
+        arr = source
+
+    # 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()
+
+    if len(arr.shape) is 2:
+        arr = [arr]
+        colors = ['gold']
+    else:
+        colors = ('red', 'green', 'blue', 'violet', 'gold', 'saddlebrown')
+
+    # If a rasterio.Band() is given make sure the proper index is displayed
+    # in the legend.
+    if isinstance(source, (tuple, rasterio.Band)):
+        labels = [str(source[1])]
+    else:
+        labels = (str(i + 1) for i in range(len(arr)))
+
+    # This loop should add a single plot each band in the input array,
+    # regardless of if the number of bands exceeds the number of colors.
+    # The colors slicing ensures that the number of iterations always
+    # matches the number of bands.
+    # The goal is to provide a curated set of colors for working with
+    # smaller datasets and let matplotlib define additional colors when
+    # working with larger datasets.
+    for bnd, color, label in zip_longest(arr, colors[:len(arr)], labels):
+
+        plt.hist(
+            bnd.flatten(),
+            bins=bins,
+            alpha=0.5,
+            color=color,
+            label=label,
+            range=rng
+        )
+
+    plt.legend(loc="upper right")
+    plt.title(title, fontweight='bold')
+    plt.grid(True)
+    plt.xlabel('DN')
+    plt.ylabel('Frequency')
+    plt.show()
+
+
 def main(banner, dataset, alt_interpreter=None):
     """ Main entry point for use with python interpreter """
     local = dict(funcs, src=dataset, np=numpy, rio=rasterio, plt=plt)

{"golden_diff": "diff --git a/rasterio/tool.py b/rasterio/tool.py\n--- a/rasterio/tool.py\n+++ b/rasterio/tool.py\n@@ -11,6 +11,7 @@\n import numpy\n \n import rasterio\n+from rasterio.five import zip_longest\n \n \n logger = logging.getLogger('rasterio')\n@@ -48,6 +49,76 @@\n     return Stats(numpy.min(arr), numpy.max(arr), numpy.mean(arr))\n \n \n+def show_hist(source, bins=10, masked=True, title='Histogram'):\n+\n+    \"\"\"\n+    Easily display a histogram with matplotlib.\n+\n+    Parameters\n+    ----------\n+    bins : int, optional\n+        Compute histogram across N bins.\n+    data : np.array or 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+    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+    \"\"\"\n+\n+    if plt is None:\n+        raise ImportError(\"Could not import matplotlib\")\n+\n+    if 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 = [arr]\n+        colors = ['gold']\n+    else:\n+        colors = ('red', 'green', 'blue', 'violet', 'gold', 'saddlebrown')\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+    # This loop should add a single plot each band in the input array,\n+    # regardless of if the number of bands exceeds the number of colors.\n+    # The colors slicing ensures that the number of iterations always\n+    # matches the number of bands.\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+    for bnd, color, label in zip_longest(arr, colors[:len(arr)], labels):\n+\n+        plt.hist(\n+            bnd.flatten(),\n+            bins=bins,\n+            alpha=0.5,\n+            color=color,\n+            label=label,\n+            range=rng\n+        )\n+\n+    plt.legend(loc=\"upper right\")\n+    plt.title(title, fontweight='bold')\n+    plt.grid(True)\n+    plt.xlabel('DN')\n+    plt.ylabel('Frequency')\n+    plt.show()\n+\n+\n def main(banner, dataset, alt_interpreter=None):\n     \"\"\" Main entry point for use with python interpreter \"\"\"\n     local = dict(funcs, src=dataset, np=numpy, rio=rasterio, plt=plt)\n", "issue": "Add a function to easily display a matotlib histogram in rio-insp\nSee #455 for background \n\nMight be useful to surface this both in `rio insp` and as `rasterio.show_histogram()`.\n\n", "before_files": [{"content": "\nimport code\nimport collections\nimport logging\n\ntry:\n    import matplotlib.pyplot as plt\nexcept ImportError:\n    plt = None\n\nimport numpy\n\nimport rasterio\n\n\nlogger = logging.getLogger('rasterio')\n\nStats = collections.namedtuple('Stats', ['min', 'max', 'mean'])\n\n# Collect dictionary of functions for use in the interpreter in main()\nfuncs = locals()\n\n\ndef show(source, cmap='gray'):\n    \"\"\"Show a raster using matplotlib.\n\n    The raster may be either an ndarray or a (dataset, bidx)\n    tuple.\n    \"\"\"\n    if isinstance(source, tuple):\n        arr = source[0].read(source[1])\n    else:\n        arr = source\n    if plt is not None:\n        plt.imshow(arr, cmap=cmap)\n        plt.show()\n    else:\n        raise ImportError(\"matplotlib could not be imported\")\n\n\ndef stats(source):\n    \"\"\"Return a tuple with raster min, max, and mean.\n    \"\"\"\n    if isinstance(source, tuple):\n        arr = source[0].read(source[1])\n    else:\n        arr = source\n    return Stats(numpy.min(arr), numpy.max(arr), numpy.mean(arr))\n\n\ndef main(banner, dataset, alt_interpreter=None):\n    \"\"\" Main entry point for use with python interpreter \"\"\"\n    local = dict(funcs, src=dataset, np=numpy, rio=rasterio, plt=plt)\n    if not alt_interpreter:\n        code.interact(banner, local=local)\n    elif alt_interpreter == 'ipython':\n        import IPython\n        IPython.InteractiveShell.banner1 = banner\n        IPython.start_ipython(argv=[], user_ns=local)\n    else:\n        raise ValueError(\"Unsupported interpreter '%s'\" % alt_interpreter)\n\n    return 0\n", "path": "rasterio/tool.py"}], "after_files": [{"content": "\nimport code\nimport collections\nimport logging\n\ntry:\n    import matplotlib.pyplot as plt\nexcept ImportError:\n    plt = None\n\nimport numpy\n\nimport rasterio\nfrom rasterio.five import zip_longest\n\n\nlogger = logging.getLogger('rasterio')\n\nStats = collections.namedtuple('Stats', ['min', 'max', 'mean'])\n\n# Collect dictionary of functions for use in the interpreter in main()\nfuncs = locals()\n\n\ndef show(source, cmap='gray'):\n    \"\"\"Show a raster using matplotlib.\n\n    The raster may be either an ndarray or a (dataset, bidx)\n    tuple.\n    \"\"\"\n    if isinstance(source, tuple):\n        arr = source[0].read(source[1])\n    else:\n        arr = source\n    if plt is not None:\n        plt.imshow(arr, cmap=cmap)\n        plt.show()\n    else:\n        raise ImportError(\"matplotlib could not be imported\")\n\n\ndef stats(source):\n    \"\"\"Return a tuple with raster min, max, and mean.\n    \"\"\"\n    if isinstance(source, tuple):\n        arr = source[0].read(source[1])\n    else:\n        arr = source\n    return Stats(numpy.min(arr), numpy.max(arr), numpy.mean(arr))\n\n\ndef show_hist(source, bins=10, masked=True, title='Histogram'):\n\n    \"\"\"\n    Easily display a histogram with matplotlib.\n\n    Parameters\n    ----------\n    bins : int, optional\n        Compute histogram across N bins.\n    data : np.array or 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    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    \"\"\"\n\n    if plt is None:\n        raise ImportError(\"Could not import matplotlib\")\n\n    if 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 = [arr]\n        colors = ['gold']\n    else:\n        colors = ('red', 'green', 'blue', 'violet', 'gold', 'saddlebrown')\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    # This loop should add a single plot each band in the input array,\n    # regardless of if the number of bands exceeds the number of colors.\n    # The colors slicing ensures that the number of iterations always\n    # matches the number of bands.\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    for bnd, color, label in zip_longest(arr, colors[:len(arr)], labels):\n\n        plt.hist(\n            bnd.flatten(),\n            bins=bins,\n            alpha=0.5,\n            color=color,\n            label=label,\n            range=rng\n        )\n\n    plt.legend(loc=\"upper right\")\n    plt.title(title, fontweight='bold')\n    plt.grid(True)\n    plt.xlabel('DN')\n    plt.ylabel('Frequency')\n    plt.show()\n\n\ndef main(banner, dataset, alt_interpreter=None):\n    \"\"\" Main entry point for use with python interpreter \"\"\"\n    local = dict(funcs, src=dataset, np=numpy, rio=rasterio, plt=plt)\n    if not alt_interpreter:\n        code.interact(banner, local=local)\n    elif alt_interpreter == 'ipython':\n        import IPython\n        IPython.InteractiveShell.banner1 = banner\n        IPython.start_ipython(argv=[], user_ns=local)\n    else:\n        raise ValueError(\"Unsupported interpreter '%s'\" % alt_interpreter)\n\n    return 0\n", "path": "rasterio/tool.py"}]}