We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
Extract data bounds (excluding NODATA) from raster
I have a need for auto-cropping rasters that have large amounts of `NODATA` around the periphery.  To support that, it seems like we could use a general function similar to `bounds`, e.g., `data_bounds` which would return the minimum bounding rectangle of non `NODATA` pixels.

I looked for prior works here and in scipy and didn't see anything obvious.

@sgillies any issues with adding this here?


--- 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/__init__.py`
Content:
```
1 # rasterio
2 
3 from collections import namedtuple
4 import logging
5 import os
6 import warnings
7 
8 from rasterio._base import eval_window, window_shape, window_index
9 from rasterio._drivers import driver_count, GDALEnv
10 import rasterio.dtypes
11 from rasterio.dtypes import (
12     bool_, ubyte, uint8, uint16, int16, uint32, int32, float32, float64,
13     complex_)
14 from rasterio.five import string_types
15 from rasterio.profiles import default_gtiff_profile
16 from rasterio.transform import Affine, guard_transform
17 
18 # These modules are imported from the Cython extensions, but are also import
19 # here to help tools like cx_Freeze find them automatically
20 from rasterio import _err, coords, enums
21 
22 # Classes in rasterio._io are imported below just before we need them.
23 
24 __all__ = [
25     'band', 'open', 'drivers', 'copy', 'pad']
26 __version__ = "0.29.0"
27 
28 log = logging.getLogger('rasterio')
29 class NullHandler(logging.Handler):
30     def emit(self, record):
31         pass
32 log.addHandler(NullHandler())
33 
34 
35 def open(
36         path, mode='r', 
37         driver=None,
38         width=None, height=None,
39         count=None,
40         crs=None, transform=None,
41         dtype=None,
42         nodata=None,
43         **kwargs):
44     """Open file at ``path`` in ``mode`` "r" (read), "r+" (read/write),
45     or "w" (write) and return a ``Reader`` or ``Updater`` object.
46     
47     In write mode, a driver name such as "GTiff" or "JPEG" (see GDAL
48     docs or ``gdal_translate --help`` on the command line), ``width``
49     (number of pixels per line) and ``height`` (number of lines), the
50     ``count`` number of bands in the new file must be specified.
51     Additionally, the data type for bands such as ``rasterio.ubyte`` for
52     8-bit bands or ``rasterio.uint16`` for 16-bit bands must be
53     specified using the ``dtype`` argument.
54 
55     A coordinate reference system for raster datasets in write mode can
56     be defined by the ``crs`` argument. It takes Proj4 style mappings
57     like
58     
59       {'proj': 'longlat', 'ellps': 'WGS84', 'datum': 'WGS84',
60        'no_defs': True}
61 
62     An affine transformation that maps ``col,row`` pixel coordinates to
63     ``x,y`` coordinates in the coordinate reference system can be
64     specified using the ``transform`` argument. The value may be either
65     an instance of ``affine.Affine`` or a 6-element sequence of the
66     affine transformation matrix coefficients ``a, b, c, d, e, f``.
67     These coefficients are shown in the figure below.
68 
69       | x |   | a  b  c | | c |
70       | y | = | d  e  f | | r |
71       | 1 |   | 0  0  1 | | 1 |
72 
73     a: rate of change of X with respect to increasing column, i.e.
74             pixel width
75     b: rotation, 0 if the raster is oriented "north up" 
76     c: X coordinate of the top left corner of the top left pixel 
77     f: Y coordinate of the top left corner of the top left pixel 
78     d: rotation, 0 if the raster is oriented "north up"
79     e: rate of change of Y with respect to increasing row, usually
80             a negative number i.e. -1 * pixel height
81     f: Y coordinate of the top left corner of the top left pixel 
82 
83     Finally, additional kwargs are passed to GDAL as driver-specific
84     dataset creation parameters.
85     """
86     if not isinstance(path, string_types):
87         raise TypeError("invalid path: %r" % path)
88     if mode and not isinstance(mode, string_types):
89         raise TypeError("invalid mode: %r" % mode)
90     if driver and not isinstance(driver, string_types):
91         raise TypeError("invalid driver: %r" % driver)
92 
93     if transform:
94         transform = guard_transform(transform)
95     elif 'affine' in kwargs:
96         affine = kwargs.pop('affine')
97         transform = guard_transform(affine)
98 
99     if mode == 'r':
100         from rasterio._io import RasterReader
101         s = RasterReader(path)
102     elif mode == 'r+':
103         from rasterio._io import writer
104         s = writer(path, mode)
105     elif mode == 'r-':
106         from rasterio._base import DatasetReader
107         s = DatasetReader(path)
108     elif mode == 'w':
109         from rasterio._io import writer
110         s = writer(path, mode, driver=driver,
111                    width=width, height=height, count=count,
112                    crs=crs, transform=transform, dtype=dtype,
113                    nodata=nodata,
114                    **kwargs)
115     else:
116         raise ValueError(
117             "mode string must be one of 'r', 'r+', or 'w', not %s" % mode)
118     s.start()
119     return s
120 
121 
122 def copy(src, dst, **kw):
123     """Copy a source dataset to a new destination with driver specific
124     creation options.
125 
126     ``src`` must be an existing file and ``dst`` a valid output file.
127 
128     A ``driver`` keyword argument with value like 'GTiff' or 'JPEG' is
129     used to control the output format.
130     
131     This is the one way to create write-once files like JPEGs.
132     """
133     from rasterio._copy import RasterCopier
134     with drivers():
135         return RasterCopier()(src, dst, **kw)
136 
137 
138 def drivers(**kwargs):
139     """Returns a gdal environment with registered drivers."""
140     if driver_count() == 0:
141         log.debug("Creating a chief GDALEnv in drivers()")
142         return GDALEnv(True, **kwargs)
143     else:
144         log.debug("Creating a not-responsible GDALEnv in drivers()")
145         return GDALEnv(False, **kwargs)
146 
147 
148 Band = namedtuple('Band', ['ds', 'bidx', 'dtype', 'shape'])
149 
150 def band(ds, bidx):
151     """Wraps a dataset and a band index up as a 'Band'"""
152     return Band(
153         ds, 
154         bidx, 
155         set(ds.dtypes).pop(),
156         ds.shape)
157 
158 
159 def pad(array, transform, pad_width, mode=None, **kwargs):
160     """Returns a padded array and shifted affine transform matrix.
161     
162     Array is padded using `numpy.pad()`."""
163     import numpy
164     transform = guard_transform(transform)
165     padded_array = numpy.pad(array, pad_width, mode, **kwargs)
166     padded_trans = list(transform)
167     padded_trans[2] -= pad_width*padded_trans[0]
168     padded_trans[5] -= pad_width*padded_trans[4]
169     return padded_array, Affine(*padded_trans[:6])
170
```
--- 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/__init__.py b/rasterio/__init__.py
--- a/rasterio/__init__.py
+++ b/rasterio/__init__.py
@@ -167,3 +167,83 @@
     padded_trans[2] -= pad_width*padded_trans[0]
     padded_trans[5] -= pad_width*padded_trans[4]
     return padded_array, Affine(*padded_trans[:6])
+
+
+def get_data_window(arr, nodata=None):
+    """
+    Returns a window for the non-nodata pixels within the input array.
+
+    Parameters
+    ----------
+    arr: numpy ndarray, <= 3 dimensions
+    nodata: number
+        If None, will either return a full window if arr is not a masked
+        array, or will use the mask to determine non-nodata pixels.
+        If provided, it must be a number within the valid range of the dtype
+        of the input array.
+
+    Returns
+    -------
+    ((row_start, row_stop), (col_start, col_stop))
+
+    """
+
+    from rasterio._io import get_data_window
+    return get_data_window(arr, nodata)
+
+
+def window_union(windows):
+    """
+    Union windows and return the outermost extent they cover.
+
+    Parameters
+    ----------
+    windows: list-like of window objects
+        ((row_start, row_stop), (col_start, col_stop))
+
+    Returns
+    -------
+    ((row_start, row_stop), (col_start, col_stop))
+    """
+
+    from rasterio._io import window_union
+    return window_union(windows)
+
+
+def window_intersection(windows):
+    """
+    Intersect windows and return the innermost extent they cover.
+
+    Will raise ValueError if windows do not intersect.
+
+    Parameters
+    ----------
+    windows: list-like of window objects
+        ((row_start, row_stop), (col_start, col_stop))
+
+    Returns
+    -------
+    ((row_start, row_stop), (col_start, col_stop))
+    """
+
+    from rasterio._io import window_intersection
+    return window_intersection(windows)
+
+
+def windows_intersect(windows):
+    """
+    Test if windows intersect.
+
+    Parameters
+    ----------
+    windows: list-like of window objects
+        ((row_start, row_stop), (col_start, col_stop))
+
+    Returns
+    -------
+    boolean:
+        True if all windows intersect.
+    """
+
+    from rasterio._io import windows_intersect
+    return windows_intersect(windows)

{"golden_diff": "diff --git a/rasterio/__init__.py b/rasterio/__init__.py\n--- a/rasterio/__init__.py\n+++ b/rasterio/__init__.py\n@@ -167,3 +167,83 @@\n     padded_trans[2] -= pad_width*padded_trans[0]\n     padded_trans[5] -= pad_width*padded_trans[4]\n     return padded_array, Affine(*padded_trans[:6])\n+\n+\n+def get_data_window(arr, nodata=None):\n+    \"\"\"\n+    Returns a window for the non-nodata pixels within the input array.\n+\n+    Parameters\n+    ----------\n+    arr: numpy ndarray, <= 3 dimensions\n+    nodata: number\n+        If None, will either return a full window if arr is not a masked\n+        array, or will use the mask to determine non-nodata pixels.\n+        If provided, it must be a number within the valid range of the dtype\n+        of the input array.\n+\n+    Returns\n+    -------\n+    ((row_start, row_stop), (col_start, col_stop))\n+\n+    \"\"\"\n+\n+    from rasterio._io import get_data_window\n+    return get_data_window(arr, nodata)\n+\n+\n+def window_union(windows):\n+    \"\"\"\n+    Union windows and return the outermost extent they cover.\n+\n+    Parameters\n+    ----------\n+    windows: list-like of window objects\n+        ((row_start, row_stop), (col_start, col_stop))\n+\n+    Returns\n+    -------\n+    ((row_start, row_stop), (col_start, col_stop))\n+    \"\"\"\n+\n+    from rasterio._io import window_union\n+    return window_union(windows)\n+\n+\n+def window_intersection(windows):\n+    \"\"\"\n+    Intersect windows and return the innermost extent they cover.\n+\n+    Will raise ValueError if windows do not intersect.\n+\n+    Parameters\n+    ----------\n+    windows: list-like of window objects\n+        ((row_start, row_stop), (col_start, col_stop))\n+\n+    Returns\n+    -------\n+    ((row_start, row_stop), (col_start, col_stop))\n+    \"\"\"\n+\n+    from rasterio._io import window_intersection\n+    return window_intersection(windows)\n+\n+\n+def windows_intersect(windows):\n+    \"\"\"\n+    Test if windows intersect.\n+\n+    Parameters\n+    ----------\n+    windows: list-like of window objects\n+        ((row_start, row_stop), (col_start, col_stop))\n+\n+    Returns\n+    -------\n+    boolean:\n+        True if all windows intersect.\n+    \"\"\"\n+\n+    from rasterio._io import windows_intersect\n+    return windows_intersect(windows)\n", "issue": "Extract data bounds (excluding NODATA) from raster\nI have a need for auto-cropping rasters that have large amounts of `NODATA` around the periphery.  To support that, it seems like we could use a general function similar to `bounds`, e.g., `data_bounds` which would return the minimum bounding rectangle of non `NODATA` pixels.\n\nI looked for prior works here and in scipy and didn't see anything obvious.\n\n@sgillies any issues with adding this here?\n\n", "before_files": [{"content": "# rasterio\n\nfrom collections import namedtuple\nimport logging\nimport os\nimport warnings\n\nfrom rasterio._base import eval_window, window_shape, window_index\nfrom rasterio._drivers import driver_count, GDALEnv\nimport rasterio.dtypes\nfrom rasterio.dtypes import (\n    bool_, ubyte, uint8, uint16, int16, uint32, int32, float32, float64,\n    complex_)\nfrom rasterio.five import string_types\nfrom rasterio.profiles import default_gtiff_profile\nfrom rasterio.transform import Affine, guard_transform\n\n# These modules are imported from the Cython extensions, but are also import\n# here to help tools like cx_Freeze find them automatically\nfrom rasterio import _err, coords, enums\n\n# Classes in rasterio._io are imported below just before we need them.\n\n__all__ = [\n    'band', 'open', 'drivers', 'copy', 'pad']\n__version__ = \"0.29.0\"\n\nlog = logging.getLogger('rasterio')\nclass NullHandler(logging.Handler):\n    def emit(self, record):\n        pass\nlog.addHandler(NullHandler())\n\n\ndef open(\n        path, mode='r', \n        driver=None,\n        width=None, height=None,\n        count=None,\n        crs=None, transform=None,\n        dtype=None,\n        nodata=None,\n        **kwargs):\n    \"\"\"Open file at ``path`` in ``mode`` \"r\" (read), \"r+\" (read/write),\n    or \"w\" (write) and return a ``Reader`` or ``Updater`` object.\n    \n    In write mode, a driver name such as \"GTiff\" or \"JPEG\" (see GDAL\n    docs or ``gdal_translate --help`` on the command line), ``width``\n    (number of pixels per line) and ``height`` (number of lines), the\n    ``count`` number of bands in the new file must be specified.\n    Additionally, the data type for bands such as ``rasterio.ubyte`` for\n    8-bit bands or ``rasterio.uint16`` for 16-bit bands must be\n    specified using the ``dtype`` argument.\n\n    A coordinate reference system for raster datasets in write mode can\n    be defined by the ``crs`` argument. It takes Proj4 style mappings\n    like\n    \n      {'proj': 'longlat', 'ellps': 'WGS84', 'datum': 'WGS84',\n       'no_defs': True}\n\n    An affine transformation that maps ``col,row`` pixel coordinates to\n    ``x,y`` coordinates in the coordinate reference system can be\n    specified using the ``transform`` argument. The value may be either\n    an instance of ``affine.Affine`` or a 6-element sequence of the\n    affine transformation matrix coefficients ``a, b, c, d, e, f``.\n    These coefficients are shown in the figure below.\n\n      | x |   | a  b  c | | c |\n      | y | = | d  e  f | | r |\n      | 1 |   | 0  0  1 | | 1 |\n\n    a: rate of change of X with respect to increasing column, i.e.\n            pixel width\n    b: rotation, 0 if the raster is oriented \"north up\" \n    c: X coordinate of the top left corner of the top left pixel \n    f: Y coordinate of the top left corner of the top left pixel \n    d: rotation, 0 if the raster is oriented \"north up\"\n    e: rate of change of Y with respect to increasing row, usually\n            a negative number i.e. -1 * pixel height\n    f: Y coordinate of the top left corner of the top left pixel \n\n    Finally, additional kwargs are passed to GDAL as driver-specific\n    dataset creation parameters.\n    \"\"\"\n    if not isinstance(path, string_types):\n        raise TypeError(\"invalid path: %r\" % path)\n    if mode and not isinstance(mode, string_types):\n        raise TypeError(\"invalid mode: %r\" % mode)\n    if driver and not isinstance(driver, string_types):\n        raise TypeError(\"invalid driver: %r\" % driver)\n\n    if transform:\n        transform = guard_transform(transform)\n    elif 'affine' in kwargs:\n        affine = kwargs.pop('affine')\n        transform = guard_transform(affine)\n\n    if mode == 'r':\n        from rasterio._io import RasterReader\n        s = RasterReader(path)\n    elif mode == 'r+':\n        from rasterio._io import writer\n        s = writer(path, mode)\n    elif mode == 'r-':\n        from rasterio._base import DatasetReader\n        s = DatasetReader(path)\n    elif mode == 'w':\n        from rasterio._io import writer\n        s = writer(path, mode, driver=driver,\n                   width=width, height=height, count=count,\n                   crs=crs, transform=transform, dtype=dtype,\n                   nodata=nodata,\n                   **kwargs)\n    else:\n        raise ValueError(\n            \"mode string must be one of 'r', 'r+', or 'w', not %s\" % mode)\n    s.start()\n    return s\n\n\ndef copy(src, dst, **kw):\n    \"\"\"Copy a source dataset to a new destination with driver specific\n    creation options.\n\n    ``src`` must be an existing file and ``dst`` a valid output file.\n\n    A ``driver`` keyword argument with value like 'GTiff' or 'JPEG' is\n    used to control the output format.\n    \n    This is the one way to create write-once files like JPEGs.\n    \"\"\"\n    from rasterio._copy import RasterCopier\n    with drivers():\n        return RasterCopier()(src, dst, **kw)\n\n\ndef drivers(**kwargs):\n    \"\"\"Returns a gdal environment with registered drivers.\"\"\"\n    if driver_count() == 0:\n        log.debug(\"Creating a chief GDALEnv in drivers()\")\n        return GDALEnv(True, **kwargs)\n    else:\n        log.debug(\"Creating a not-responsible GDALEnv in drivers()\")\n        return GDALEnv(False, **kwargs)\n\n\nBand = namedtuple('Band', ['ds', 'bidx', 'dtype', 'shape'])\n\ndef band(ds, bidx):\n    \"\"\"Wraps a dataset and a band index up as a 'Band'\"\"\"\n    return Band(\n        ds, \n        bidx, \n        set(ds.dtypes).pop(),\n        ds.shape)\n\n\ndef pad(array, transform, pad_width, mode=None, **kwargs):\n    \"\"\"Returns a padded array and shifted affine transform matrix.\n    \n    Array is padded using `numpy.pad()`.\"\"\"\n    import numpy\n    transform = guard_transform(transform)\n    padded_array = numpy.pad(array, pad_width, mode, **kwargs)\n    padded_trans = list(transform)\n    padded_trans[2] -= pad_width*padded_trans[0]\n    padded_trans[5] -= pad_width*padded_trans[4]\n    return padded_array, Affine(*padded_trans[:6])\n", "path": "rasterio/__init__.py"}], "after_files": [{"content": "# rasterio\n\nfrom collections import namedtuple\nimport logging\nimport os\nimport warnings\n\nfrom rasterio._base import eval_window, window_shape, window_index\nfrom rasterio._drivers import driver_count, GDALEnv\nimport rasterio.dtypes\nfrom rasterio.dtypes import (\n    bool_, ubyte, uint8, uint16, int16, uint32, int32, float32, float64,\n    complex_)\nfrom rasterio.five import string_types\nfrom rasterio.profiles import default_gtiff_profile\nfrom rasterio.transform import Affine, guard_transform\n\n# These modules are imported from the Cython extensions, but are also import\n# here to help tools like cx_Freeze find them automatically\nfrom rasterio import _err, coords, enums\n\n# Classes in rasterio._io are imported below just before we need them.\n\n__all__ = [\n    'band', 'open', 'drivers', 'copy', 'pad']\n__version__ = \"0.28.0\"\n\nlog = logging.getLogger('rasterio')\nclass NullHandler(logging.Handler):\n    def emit(self, record):\n        pass\nlog.addHandler(NullHandler())\n\n\ndef open(\n        path, mode='r', \n        driver=None,\n        width=None, height=None,\n        count=None,\n        crs=None, transform=None,\n        dtype=None,\n        nodata=None,\n        **kwargs):\n    \"\"\"Open file at ``path`` in ``mode`` \"r\" (read), \"r+\" (read/write),\n    or \"w\" (write) and return a ``Reader`` or ``Updater`` object.\n    \n    In write mode, a driver name such as \"GTiff\" or \"JPEG\" (see GDAL\n    docs or ``gdal_translate --help`` on the command line), ``width``\n    (number of pixels per line) and ``height`` (number of lines), the\n    ``count`` number of bands in the new file must be specified.\n    Additionally, the data type for bands such as ``rasterio.ubyte`` for\n    8-bit bands or ``rasterio.uint16`` for 16-bit bands must be\n    specified using the ``dtype`` argument.\n\n    A coordinate reference system for raster datasets in write mode can\n    be defined by the ``crs`` argument. It takes Proj4 style mappings\n    like\n    \n      {'proj': 'longlat', 'ellps': 'WGS84', 'datum': 'WGS84',\n       'no_defs': True}\n\n    An affine transformation that maps ``col,row`` pixel coordinates to\n    ``x,y`` coordinates in the coordinate reference system can be\n    specified using the ``transform`` argument. The value may be either\n    an instance of ``affine.Affine`` or a 6-element sequence of the\n    affine transformation matrix coefficients ``a, b, c, d, e, f``.\n    These coefficients are shown in the figure below.\n\n      | x |   | a  b  c | | c |\n      | y | = | d  e  f | | r |\n      | 1 |   | 0  0  1 | | 1 |\n\n    a: rate of change of X with respect to increasing column, i.e.\n            pixel width\n    b: rotation, 0 if the raster is oriented \"north up\" \n    c: X coordinate of the top left corner of the top left pixel \n    f: Y coordinate of the top left corner of the top left pixel \n    d: rotation, 0 if the raster is oriented \"north up\"\n    e: rate of change of Y with respect to increasing row, usually\n            a negative number i.e. -1 * pixel height\n    f: Y coordinate of the top left corner of the top left pixel \n\n    Finally, additional kwargs are passed to GDAL as driver-specific\n    dataset creation parameters.\n    \"\"\"\n    if not isinstance(path, string_types):\n        raise TypeError(\"invalid path: %r\" % path)\n    if mode and not isinstance(mode, string_types):\n        raise TypeError(\"invalid mode: %r\" % mode)\n    if driver and not isinstance(driver, string_types):\n        raise TypeError(\"invalid driver: %r\" % driver)\n\n    if transform:\n        transform = guard_transform(transform)\n    elif 'affine' in kwargs:\n        affine = kwargs.pop('affine')\n        transform = guard_transform(affine)\n\n    if mode == 'r':\n        from rasterio._io import RasterReader\n        s = RasterReader(path)\n    elif mode == 'r+':\n        from rasterio._io import writer\n        s = writer(path, mode)\n    elif mode == 'r-':\n        from rasterio._base import DatasetReader\n        s = DatasetReader(path)\n    elif mode == 'w':\n        from rasterio._io import writer\n        s = writer(path, mode, driver=driver,\n                   width=width, height=height, count=count,\n                   crs=crs, transform=transform, dtype=dtype,\n                   nodata=nodata,\n                   **kwargs)\n    else:\n        raise ValueError(\n            \"mode string must be one of 'r', 'r+', or 'w', not %s\" % mode)\n    s.start()\n    return s\n\n\ndef copy(src, dst, **kw):\n    \"\"\"Copy a source dataset to a new destination with driver specific\n    creation options.\n\n    ``src`` must be an existing file and ``dst`` a valid output file.\n\n    A ``driver`` keyword argument with value like 'GTiff' or 'JPEG' is\n    used to control the output format.\n    \n    This is the one way to create write-once files like JPEGs.\n    \"\"\"\n    from rasterio._copy import RasterCopier\n    with drivers():\n        return RasterCopier()(src, dst, **kw)\n\n\ndef drivers(**kwargs):\n    \"\"\"Returns a gdal environment with registered drivers.\"\"\"\n    if driver_count() == 0:\n        log.debug(\"Creating a chief GDALEnv in drivers()\")\n        return GDALEnv(True, **kwargs)\n    else:\n        log.debug(\"Creating a not-responsible GDALEnv in drivers()\")\n        return GDALEnv(False, **kwargs)\n\n\nBand = namedtuple('Band', ['ds', 'bidx', 'dtype', 'shape'])\n\ndef band(ds, bidx):\n    \"\"\"Wraps a dataset and a band index up as a 'Band'\"\"\"\n    return Band(\n        ds, \n        bidx, \n        set(ds.dtypes).pop(),\n        ds.shape)\n\n\ndef pad(array, transform, pad_width, mode=None, **kwargs):\n    \"\"\"Returns a padded array and shifted affine transform matrix.\n    \n    Array is padded using `numpy.pad()`.\"\"\"\n    import numpy\n    transform = guard_transform(transform)\n    padded_array = numpy.pad(array, pad_width, mode, **kwargs)\n    padded_trans = list(transform)\n    padded_trans[2] -= pad_width*padded_trans[0]\n    padded_trans[5] -= pad_width*padded_trans[4]\n    return padded_array, Affine(*padded_trans[:6])\n\n\ndef get_data_window(arr, nodata=None):\n    \"\"\"\n    Returns a window for the non-nodata pixels within the input array.\n\n    Parameters\n    ----------\n    arr: numpy ndarray, <= 3 dimensions\n    nodata: number\n        If None, will either return a full window if arr is not a masked\n        array, or will use the mask to determine non-nodata pixels.\n        If provided, it must be a number within the valid range of the dtype\n        of the input array.\n\n    Returns\n    -------\n    ((row_start, row_stop), (col_start, col_stop))\n\n    \"\"\"\n\n    from rasterio._io import get_data_window\n    return get_data_window(arr, nodata)\n\n\ndef window_union(windows):\n    \"\"\"\n    Union windows and return the outermost extent they cover.\n\n    Parameters\n    ----------\n    windows: list-like of window objects\n        ((row_start, row_stop), (col_start, col_stop))\n\n    Returns\n    -------\n    ((row_start, row_stop), (col_start, col_stop))\n    \"\"\"\n\n    from rasterio._io import window_union\n    return window_union(windows)\n\n\ndef window_intersection(windows):\n    \"\"\"\n    Intersect windows and return the innermost extent they cover.\n\n    Will raise ValueError if windows do not intersect.\n\n    Parameters\n    ----------\n    windows: list-like of window objects\n        ((row_start, row_stop), (col_start, col_stop))\n\n    Returns\n    -------\n    ((row_start, row_stop), (col_start, col_stop))\n    \"\"\"\n\n    from rasterio._io import window_intersection\n    return window_intersection(windows)\n\n\ndef windows_intersect(windows):\n    \"\"\"\n    Test if windows intersect.\n\n    Parameters\n    ----------\n    windows: list-like of window objects\n        ((row_start, row_stop), (col_start, col_stop))\n\n    Returns\n    -------\n    boolean:\n        True if all windows intersect.\n    \"\"\"\n\n    from rasterio._io import windows_intersect\n    return windows_intersect(windows)\n", "path": "rasterio/__init__.py"}]}