[rasterio] 01/04: Revert "Revert "Merge tag 'upstream/0.26.0'""
Johan Van de Wauw
johanvdw-guest at moszumanska.debian.org
Fri Sep 25 10:08:19 UTC 2015
This is an automated email from the git hooks/post-receive script.
johanvdw-guest pushed a commit to branch master
in repository rasterio.
commit c7657eac83517c7231c1c0671151a721860c8060
Author: Johan Van de Wauw <johan at vandewauw.be>
Date: Tue Sep 15 21:51:05 2015 +0200
Revert "Revert "Merge tag 'upstream/0.26.0'""
This reverts commit 50c4ae398d5f92a8fc6c80e0e109df4103b0cb6c.
---
.gitignore | 76 +++++++++++++++++++++++++++
.travis.yml | 20 +++++--
AUTHORS.txt | 3 +-
CHANGES.txt | 18 +++++++
README.rst | 45 +++++++++++++++-
docs/cli.rst | 133 ++++++++++++++++++++++++++++++++---------------
docs/reproject.rst | 64 +++++++++++++++++++++--
examples/polygonize.py | 10 ++--
rasterio/__init__.py | 2 +-
rasterio/_base.pyx | 35 ++++++++++++-
rasterio/_features.pyx | 10 ++--
rasterio/_fill.pyx | 4 +-
rasterio/_gdal.pxd | 2 +-
rasterio/_io.pyx | 8 +--
rasterio/_warp.pyx | 8 +--
rasterio/dtypes.py | 6 +++
rasterio/enums.py | 2 +-
rasterio/rio/bands.py | 15 +-----
rasterio/rio/convert.py | 6 ++-
rasterio/rio/info.py | 6 +++
rasterio/rio/main.py | 8 +--
rasterio/rio/options.py | 8 ++-
rasterio/rio/overview.py | 6 +--
requirements-dev.txt | 3 +-
setup.py | 3 +-
tests/test_checksum.py | 45 ++++++++++++++++
tests/test_colormap.py | 14 +++--
tests/test_dtypes.py | 21 +++++---
tests/test_overviews.py | 10 ++++
tests/test_rio_bands.py | 6 +--
tests/test_rio_info.py | 16 ++++++
31 files changed, 496 insertions(+), 117 deletions(-)
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..0b87ebd
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,76 @@
+# Byte-compiled / optimized / DLL files
+__pycache__/
+*.py[cod]
+
+# C extensions
+*.so
+
+# Distribution / packaging
+.Python
+env/
+build/
+develop-eggs/
+dist/
+downloads/
+eggs/
+.eggs/
+lib/
+lib64/
+parts/
+sdist/
+var/
+*.egg-info/
+.installed.cfg
+*.egg
+
+# PyInstaller
+# Usually these files are written by a python script from a template
+# before PyInstaller builds the exe, so as to inject date/other infos into it.
+*.manifest
+*.spec
+
+# Installer logs
+pip-log.txt
+pip-delete-this-directory.txt
+
+# Unit test / coverage reports
+htmlcov/
+.tox/
+.coverage
+.coverage.*
+.cache
+nosetests.xml
+coverage.xml
+*,cover
+
+# Translations
+*.mo
+*.pot
+
+# Django stuff:
+*.log
+
+# Sphinx documentation
+docs/_build/
+
+# PyBuilder
+target/
+
+# IDE's etc.
+.idea/
+venv/
+venv2/
+
+# rasterio
+test.tif
+gdal-config.txt
+VERSION.txt
+rasterio/_fill.cpp
+rasterio/_warp.cpp
+rasterio/_base.c
+rasterio/_copy.c
+rasterio/_drivers.c
+rasterio/_err.c
+rasterio/_example.c
+rasterio/_features.c
+rasterio/_io.c
diff --git a/.travis.yml b/.travis.yml
index 440f792..bbf5cc5 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -8,12 +8,22 @@ before_install:
- sudo apt-get update -qq
- sudo apt-get install -y libgdal1h gdal-bin libgdal-dev
install:
- - pip install --install-option="--no-cython-compile" cython
- - "pip install -r requirements-dev.txt"
- - "pip install pytest pytest-cov"
- - "pip install coveralls"
- - "pip install -e ."
+ - pip install --install-option="--no-cython-compile" cython==0.22
+ - pip install -r requirements-dev.txt
+ - pip install -e .
script:
- py.test --cov rasterio --cov-report term-missing
after_success:
- coveralls
+before_deploy:
+ - pip wheel --wheel-dir=/tmp/wheelhouse -r requirements-dev.txt
+ - pip wheel --wheel-dir=/tmp/wheelhouse -r requirements.txt
+ - pip wheel --wheel-dir=/tmp/wheelhouse .
+ - tar -C /tmp -czvf rasterio-travis-wheels-$TRAVIS_PYTHON_VERSION.tar.gz wheelhouse
+deploy:
+ provider: releases
+ api_key:
+ secure: uP/hy8LRdDnN6XHSLChmKYdW9CdIy8pqvUyXFPgTDY/mlItMUdDNdP95bitzn/rNNXnOkCGsARqzRCLeGI3jB0nEGuAzY6fGWYt2igjfMOhpdDG6o3LcaoP4mITuFfe5/kCQeUb8WB3QK6c2cL7nEEPzoSniqZQ6MsxHIvUW7ts=
+ file: rasterio-travis-wheels-$TRAVIS_PYTHON_VERSION.tar.gz
+ on:
+ tags: true
diff --git a/AUTHORS.txt b/AUTHORS.txt
index 481e0ea..5050878 100644
--- a/AUTHORS.txt
+++ b/AUTHORS.txt
@@ -16,9 +16,10 @@ Johan Van de Wauw <johan.vandewauw at gmail.com>
James Seppi <james.seppi at gmail.com>
Jacques Tardie <hi at jacquestardie.org>
Etienne B. Racine <etiennebr at gmail.com>
-cgohlke <cgohlke at uci.edu>
+Christoph Gohlke <cgohlke at uci.edu>
Martijn Visser <mgvisser at gmail.com>
Aldo Culquicondor <alculquicondor at gmail.com>
Robin Wilson <robin at rtwilson.com>
+Patrick Young <patrick.young at digitalglobe.com>
See also https://github.com/mapbox/rasterio/graphs/contributors.
diff --git a/CHANGES.txt b/CHANGES.txt
index b5c549d..96ee33a 100644
--- a/CHANGES.txt
+++ b/CHANGES.txt
@@ -1,6 +1,24 @@
Changes
=======
+0.26.0 (2015-08-11)
+-------------------
+- Add dependency on click-plugins, a new project that takes over the plugin
+ duties formerly assigned to cligj (#426).
+- Change rio-stack's --photometric=RGB option to --rgb (#429). Other
+ photometric interpretations should be assigned using the --co option
+ added in 0.25.0.
+- Allow for ndarray-like objects (like xray arrays), not just numpy arrays,
+ in warp() and elsewhere (#436).
+- Add --rgb flag to rio-convert (#439).
+- Fixed resampling algorithm enumeration bug (#441).
+- Colormap handling was made too strict in 0.24.1 and has been made more
+ forgiving. Callers are now warned when alpha values will be ignored instead
+ of receiving exceptions (#444).
+- Add a .gitignore (#445). Better late than never!
+- Add a checksum() method to base dataset class and checksums to output of
+ rio-info (#449).
+
0.25.0 (2015-07-17)
-------------------
- New rio-warp command (#264, #404).
diff --git a/README.rst b/README.rst
index a113f1e..51ddcc0 100644
--- a/README.rst
+++ b/README.rst
@@ -149,6 +149,18 @@ using Python.
>>> b.min(), b.max(), b.mean()
(1, 255, 44.434478650699106)
+Rio Plugins
+-----------
+
+Rio provides the ability to create additional subcommands using plugins. See
+`cli.rst <https://github.com/mapbox/rasterio/blob/master/docs/cli.rst#rio-plugins>`__
+for more information on building plugins.
+
+See the
+`plugin registry <https://github.com/mapbox/rasterio/wiki/Rio-plugin-registry>`__
+for a list of available plugins.
+
+
Installation
============
@@ -271,12 +283,43 @@ From the repo directory, run py.test
$ py.test
-
Note: some tests do not succeed on Windows (see
`#66
<https://github.com/mapbox/rasterio/issues/66>`__.).
+Downstream testing
+------------------
+
+If your project depends on Rasterio and uses Travis-CI, you can speed up your
+builds by fetching Rasterio and its dependencies as a set of wheels from
+GitHub as done in `rio-plugin-example
+<https://github.com/sgillies/rio-plugin-example/blob/master/.travis.yml>`__.
+
+.. code-block:: yaml
+
+ language: python
+ env:
+ - RASTERIO_VERSION=0.26
+ python:
+ - "2.7"
+ - "3.4"
+ cache:
+ directories:
+ - $HOME/.pip-cache/
+ - $HOME/wheelhouse
+ before_install:
+ - sudo add-apt-repository -y ppa:ubuntugis/ppa
+ - sudo apt-get update -qq
+ - sudo apt-get install -y libgdal1h gdal-bin
+ - curl -L https://github.com/mapbox/rasterio/releases/download/$RASTERIO_VERSION/rasterio-travis-wheels-$TRAVIS_PYTHON_VERSION.tar.gz > /tmp/wheelhouse.tar.gz
+ - tar -xzvf /tmp/wheelhouse.tar.gz -C $HOME
+ install:
+ - pip install --use-wheel --find-links=$HOME/wheelhouse -e .[test] --cache-dir $HOME/.pip-cache
+ script:
+ - py.test
+
+
Documentation
-------------
diff --git a/docs/cli.rst b/docs/cli.rst
index 8db75d5..56f560c 100644
--- a/docs/cli.rst
+++ b/docs/cli.rst
@@ -39,12 +39,30 @@ It is developed using `Click <http://click.pocoo.org/>`__.
Commands are shown below. See ``--help`` of individual commands for more
details.
+creation options
+----------------
+
+For commands that create new datasets, format specific creation options may
+also be passed using ``--co``. For example, to tile a new GeoTIFF output file,
+add the following.
+
+.. code-block:: console
+
+ --co tiled=true --co blockxsize=256 --co blockysize=256
+
+To compress it using the LZW method, add
+
+.. code-block:: console
+
+ --co compress=LZW
+
+
bounds
------
-New in 0.10.
+Added in 0.10.
-The bounds command writes the bounding boxes of raster datasets to GeoJSON for
+The ``bounds`` command writes the bounding boxes of raster datasets to GeoJSON for
use with, e.g., `geojsonio-cli <https://github.com/mapbox/geojsonio-cli>`__.
.. code-block:: console
@@ -93,10 +111,13 @@ use with, e.g., `geojsonio-cli <https://github.com/mapbox/geojsonio-cli>`__.
Shoot the GeoJSON into a Leaflet map using geojsonio-cli by typing
``rio bounds tests/data/RGB.byte.tif | geojsonio``.
+
calc
----
-The calc command reads files as arrays, evaluates lisp-like expressions in
+Added in 0.19
+
+The ``calc`` command reads files as arrays, evaluates lisp-like expressions in
their context, and writes the result as a new file. Members of the numpy
module and arithmetic and logical operators are available builtin functions
and operators. It is intended for simple calculations; any calculations
@@ -139,10 +160,10 @@ Please see `calc.rst <calc.rst>`__ for more details.
convert
-------
-New in 0.25
+Added in 0.25
-Like ``gdal_translate``, rio-convert copies and converts raster datasets to
-other data types and formats.
+The ``convert`` command copies and converts raster datasets to other data types
+and formats (similar to ``gdal_translate``).
Data values may be linearly scaled when copying by using the ``--scale-ratio``
and ``--scale-offset`` options. Destination raster values are calculated as
@@ -158,25 +179,15 @@ as uint8:
$ rio convert in16.tif out8.tif --dtype uint8 --scale-ratio 0.0625
-Format specific creation options may also be passed using --co. To tile a
-new GeoTIFF output file, add the following.
-
-.. code-block:: console
-
- --co tiled=true --co blockxsize=256 --co blockysize=256
+You can use `--rgb` as shorthand for `--co photometric=rgb`.
-To compress it using the LZW method, add
-
-.. code-block:: console
-
- --co compress=LZW
edit-info
---------
-New in 0.24
+Added in 0.24
-The edit-info command allows you edit a raster dataset's metadata, namely
+The ``edit-info`` command allows you edit a raster dataset's metadata, namely
- coordinate reference system
- affine transformation matrix
@@ -186,8 +197,8 @@ The edit-info command allows you edit a raster dataset's metadata, namely
A TIFF created by spatially-unaware image processing software like Photoshop
or Imagemagick can be turned into a GeoTIFF by editing these metadata items.
-You can set or change a dataset's coordinate reference system to, e.g.,
-EPSG:3857 (Web Mercator),
+For example, you can set or change a dataset's coordinate reference system to
+Web Mercator (EPSG:3857),
.. code-block:: console
@@ -209,9 +220,9 @@ or set its nodata value to, e.g., `0`:
mask
----
-New in 0.21
+Added in 0.21
-The mask command masks in pixels from all bands of a raster using features
+The ``mask`` command masks in pixels from all bands of a raster using features
(masking out all areas not covered by features) and optionally crops the output
raster to the extent of the features. Features are assumed to be in the same
coordinate reference system as the input raster.
@@ -240,7 +251,9 @@ keep pixels not covered by features.
info
----
-Rio's info command prints structured information about a dataset.
+Added in 0.13
+
+The ``info`` command prints structured information about a dataset.
.. code-block:: console
@@ -273,7 +286,7 @@ Rio's info command prints structured information about a dataset.
"nodata": 0.0
}
-More information, such as band statistics, can be had using the `--verbose`
+More information, such as band statistics, can be had using the ``--verbose``
option.
.. code-block:: console
@@ -324,10 +337,11 @@ option.
"nodata": 0.0
}
+
insp
----
-The insp command opens a dataset and an interpreter.
+The ``insp`` command opens a dataset and an interpreter.
.. code-block:: console
@@ -339,36 +353,40 @@ The insp command opens a dataset and an interpreter.
>>> print src.bounds
BoundingBox(left=101985.0, bottom=2611485.0, right=339315.0, top=2826915.0)
+
merge
-----
-The merge command can be used to flatten a stack of identically structured
+Added in 0.12.1
+
+The ``merge`` command can be used to flatten a stack of identically structured
datasets.
.. code-block:: console
$ rio merge rasterio/tests/data/R*.tif merged.tif
+
overview
--------
New in 0.25
-A pyramid of overviews computed once and stored in the dataset using
-rio-overview can improve performance in some applications.
+The ``overview`` command creates overviews stored in the dataset, which can
+improve performance in some applications.
The decimation levels at which to build overviews can be specified as a
comma separated list
.. code-block:: console
- $ rio pyramid --build 2,4,8,16
+ $ rio overview --build 2,4,8,16
or a base and range of exponents.
.. code-block:: console
- $ rio pyramid --build 2^1..4
+ $ rio overview --build 2^1..4
Note that overviews can not currently be removed and are not automatically
updated when the dataset's primary bands are modified.
@@ -377,14 +395,15 @@ Information about existing overviews can be printed using the --ls option.
.. code-block:: console
- $ rio pyramid --ls
+ $ rio overview --ls
+
rasterize
---------
New in 0.18.
-The rasterize command rasterizes GeoJSON features into a new or existing
+The ``rasterize`` command rasterizes GeoJSON features into a new or existing
raster.
.. code-block:: console
@@ -425,6 +444,7 @@ Other options are available, see:
$ rio rasterize --help
+
sample
------
@@ -442,13 +462,14 @@ values at that position to stdout.
The output of the transform command (see below) makes good input for sample.
+
shapes
------
New in 0.11.
-The shapes command extracts and writes features of a specified dataset band out
-as GeoJSON.
+The ``shapes`` command extracts and writes features of a specified dataset band
+out as GeoJSON.
.. code-block:: console
@@ -465,15 +486,16 @@ data region.
See http://bl.ocks.org/anonymous/raw/ef244954b719dba97926/.
+
stack
-----
New in 0.15.
-The rio-stack command stack a number of bands from one or more input files into
-a multiband dataset. Input datasets must be of a kind: same data type,
+The ``stack`` command stacks a number of bands from one or more input files
+into a multiband dataset. Input datasets must be of a kind: same data type,
dimensions, etc. The output is cloned from the first input. By default,
-rio-stack will take all bands from each input and write them in same order to
+``stack`` will take all bands from each input and write them in same order to
the output. Optionally, bands for each input may be specified using a simple
syntax:
@@ -492,12 +514,15 @@ Examples using the Rasterio testing dataset that produce a copy of it.
$ rio stack RGB.byte.tif --bidx 1..3 stacked.tif
$ rio stack RGB.byte.tif --bidx ..2 RGB.byte.tif --bidx 3.. stacked.tif
+You can use `--rgb` as shorthand for `--co photometric=rgb`.
+
+
transform
---------
New in 0.10.
-The transform command reads a JSON array of coordinates, interleaved, and
+The ``transform`` command reads a JSON array of coordinates, interleaved, and
writes another array of transformed coordinates to stdout.
To transform a longitude, latitude point (EPSG:4326 is the default) to
@@ -523,11 +548,10 @@ warp
New in 0.25
-The warp command warps (reprojects) a raster based on parameters that can be
+The ``warp`` command warps (reprojects) a raster based on parameters that can be
obtained from a template raster, or input directly. The output is always
overwritten.
-
To copy coordinate reference system, transform, and dimensions from a template
raster, do the following:
@@ -565,4 +589,31 @@ Other options are available, see:
$ rio warp --help
+Rio Plugins
+-----------
+
+Rio uses ``click-plugins`` to provide the ability to create additional
+subcommands using plugins developed outside rasterio. This is ideal for
+commands that require additional dependencies beyond those used by rasterio, or
+that provide functionality beyond the intended scope of rasterio.
+
+For example, `rio-mbtiles <https://github.com/mapbox/rio-mbtiles>`__ provides
+a command ``rio mbtiles`` to export a raster to an MBTiles file.
+
+See `click-plugins <https://github.com/click-contrib/click-plugins>`__ for more
+information on how to build these plugins in general.
+
+In order to use these plugins with rio, add the commands to the
+``rasterio.rio_plugins'`` entry point in your ``setup.py`` file, as described
+`here <https://github.com/click-contrib/click-plugins#developing-plugins>`__
+
+See the
+`plugin registry <https://github.com/mapbox/rasterio/wiki/Rio-plugin-registry>`__
+for a list of available plugins.
+
+
+
+Other commands?
+---------------
+
Suggestions for other commands are welcome!
diff --git a/docs/reproject.rst b/docs/reproject.rst
index 0b467f4..906a60c 100644
--- a/docs/reproject.rst
+++ b/docs/reproject.rst
@@ -54,16 +54,70 @@ transform.
assert not destination.all()
-See `examples/reproject.py <https://github.com/mapbox/rasterio/blob/master/examples/reproject.py>`__ for code that writes the destination array to a GeoTIFF file. I've
-uploaded the resulting file to a Mapbox map to demonstrate that the reprojection is
+See `examples/reproject.py <https://github.com/mapbox/rasterio/blob/master/examples/reproject.py>`__
+for code that writes the destination array to a GeoTIFF file. I've uploaded the
+resulting file to a Mapbox map to demonstrate that the reprojection is
correct: https://a.tiles.mapbox.com/v3/sgillies.hfek2oko/page.html?secure=1#6/0.000/0.033.
Reprojecting a GeoTIFF dataset
------------------------------
-Here's a more real-world example of using ``reproject()`` to make an output dataset zoomed out by a factor of 2.
-Methods of the ``rasterio.Affine`` class help us generate the output dataset's transform matrix and, thereby, its
-spatial extent.
+Reprojecting a GeoTIFF dataset from one coordinate reference system is a common
+use case. Rasterio provides a few utilities to make this even easier:
+
+``transform_bounds()``
+transforms the bounding coordinates of the source raster to the target
+coordinate reference system, densifiying points along the edges to account
+for non-linear transformations of the edges.
+
+
+``calculate_default_transform()``
+transforms bounds to target coordinate system, calculates resolution if not
+provided, and returns destination transform and dimensions.
+
+
+.. code-block:: python
+
+ import numpy
+ import rasterio
+ from rasterio.warp import calculate_default_transform, reproject, RESAMPLING
+
+ dst_crs = 'EPSG:4326'
+
+ with rasterio.open('rasterio/tests/data/RGB.byte.tif') as src:
+ affine, width, height = calculate_default_transform(
+ src.crs, dst_crs, src.width, src.height, *src.bounds)
+ kwargs = src.meta.copy()
+ kwargs.update({
+ 'crs': dst_crs,
+ 'transform': affine,
+ 'affine': affine,
+ 'width': width,
+ 'height': height
+ })
+
+ with rasterio.open('/tmp/RGB.byte.wgs84.tif', 'w', **kwargs) as dst:
+ for i in range(1, src.count + 1):
+ reproject(
+ source=rasterio.band(src, i),
+ destination=rasterio.band(dst, i),
+ src_transform=src.affine,
+ src_crs=src.crs,
+ dst_transform=affine,
+ dst_crs=dst_crs,
+ resampling=RESAMPLING.nearest)
+
+
+See ``rasterio/rio/warp.py`` for more complex examples of reprojection based on
+new bounds, dimensions, and resolution (as well as a command-line interface
+described
+`here <https://github.com/mapbox/rasterio/blob/master/docs/cli.rst#warp>`__).
+
+
+
+It is also possible to use ``reproject()`` to create an output dataset zoomed
+out by a factor of 2. Methods of the ``rasterio.Affine`` class help us generate
+the output dataset's transform matrix and, thereby, its spatial extent.
.. code-block:: python
diff --git a/examples/polygonize.py b/examples/polygonize.py
index ae6e000..e21a97d 100644
--- a/examples/polygonize.py
+++ b/examples/polygonize.py
@@ -1,10 +1,12 @@
import pprint
import rasterio
-import rasterio._features as ftrz
+from rasterio.features import shapes
-with rasterio.open('box.png') as src:
- image = src.read_band(1)
+with rasterio.open('tests/data/shade.tif') as src:
+ image = src.read(1)
+# Print the first two shapes...
pprint.pprint(
- list(ftrz.polygonize(image)))
+ list(shapes(image))[:2]
+)
diff --git a/rasterio/__init__.py b/rasterio/__init__.py
index e03e1bf..7cf55cf 100644
--- a/rasterio/__init__.py
+++ b/rasterio/__init__.py
@@ -23,7 +23,7 @@ from rasterio import _err, coords, enums
__all__ = [
'band', 'open', 'drivers', 'copy', 'pad']
-__version__ = "0.25.0"
+__version__ = "0.26.0"
log = logging.getLogger('rasterio')
class NullHandler(logging.Handler):
diff --git a/rasterio/_base.pyx b/rasterio/_base.pyx
index b514845..caf5e85 100644
--- a/rasterio/_base.pyx
+++ b/rasterio/_base.pyx
@@ -598,7 +598,6 @@ cdef class DatasetReader(object):
def kwds(self):
return self.tags(ns='rio_creation_kwds')
-
# Overviews.
def overviews(self, bidx):
cdef void *hovband = NULL
@@ -612,6 +611,40 @@ cdef class DatasetReader(object):
factors.append(int(round(float(self.width)/float(xsize))))
return factors
+ def checksum(self, bidx, window=None):
+ """Compute an integer checksum for the stored band
+
+ Parameters
+ ----------
+ bidx : int
+ The band's index (1-indexed).
+ window: tuple, optional
+ A window of the band. Default is the entire extent of the band.
+
+ Returns
+ -------
+ An int.
+ """
+ cdef void *hband = NULL
+ cdef int xoff, yoff, width, height
+ if self._hds == NULL:
+ raise ValueError("can't read closed raster file")
+ hband = _gdal.GDALGetRasterBand(self._hds, bidx)
+ if hband == NULL:
+ raise ValueError("NULL band")
+ if not window:
+ xoff = yoff = 0
+ width, height = self.width, self.height
+ else:
+ window = eval_window(window, self.height, self.width)
+ window = crop_window(window, self.height, self.width)
+ xoff = window[1][0]
+ width = window[1][1] - xoff
+ yoff = window[0][0]
+ height = window[0][1] - yoff
+ return _gdal.GDALChecksumImage(hband, xoff, yoff, width, height)
+
+
# Window utils
# A window is a 2D ndarray indexer in the form of a tuple:
# ((row_start, row_stop), (col_start, col_stop))
diff --git a/rasterio/_features.pyx b/rasterio/_features.pyx
index bc83a65..0289303 100644
--- a/rasterio/_features.pyx
+++ b/rasterio/_features.pyx
@@ -67,7 +67,7 @@ def _shapes(image, mask, connectivity, transform):
if is_float:
fieldtp = 2
- if isinstance(image, np.ndarray):
+ if dtypes.is_ndarray(image):
mem_ds = InMemoryRaster(image, transform)
hband = mem_ds.band
elif isinstance(image, tuple):
@@ -76,7 +76,7 @@ def _shapes(image, mask, connectivity, transform):
else:
raise ValueError("Invalid source image")
- if isinstance(mask, np.ndarray):
+ if dtypes.is_ndarray(mask):
# A boolean mask must be converted to uint8 for GDAL
mask_ds = InMemoryRaster(mask.astype('uint8'), transform)
hmaskband = mask_ds.band
@@ -168,7 +168,7 @@ def _sieve(image, size, output, mask, connectivity):
cdef _io.RasterUpdater udr
cdef _io.RasterReader mask_reader
- if isinstance(image, np.ndarray):
+ if dtypes.is_ndarray(image):
in_mem_ds = InMemoryRaster(image)
in_band = in_mem_ds.band
elif isinstance(image, tuple):
@@ -177,7 +177,7 @@ def _sieve(image, size, output, mask, connectivity):
else:
raise ValueError("Invalid source image")
- if isinstance(output, np.ndarray):
+ if dtypes.is_ndarray(output):
log.debug("Output array: %r", output)
out_mem_ds = InMemoryRaster(output)
out_band = out_mem_ds.band
@@ -187,7 +187,7 @@ def _sieve(image, size, output, mask, connectivity):
else:
raise ValueError("Invalid output image")
- if isinstance(mask, np.ndarray):
+ if dtypes.is_ndarray(mask):
# A boolean mask must be converted to uint8 for GDAL
mask_mem_ds = InMemoryRaster(mask.astype('uint8'))
mask_band = mask_mem_ds.band
diff --git a/rasterio/_fill.pyx b/rasterio/_fill.pyx
index 2515564..723af0a 100644
--- a/rasterio/_fill.pyx
+++ b/rasterio/_fill.pyx
@@ -23,7 +23,7 @@ def _fillnodata(image, mask, double max_search_distance=100.0,
cdef _io.RasterReader mrdr
cdef char **alg_options = NULL
- if isinstance(image, np.ndarray):
+ if dtypes.is_ndarray(image):
# copy numpy ndarray into an in-memory dataset.
image_dataset = _gdal.GDALCreate(
memdriver,
@@ -38,7 +38,7 @@ def _fillnodata(image, mask, double max_search_distance=100.0,
else:
raise ValueError("Invalid source image")
- if isinstance(mask, np.ndarray):
+ if dtypes.is_ndarray(mask):
mask_cast = mask.astype('uint8')
mask_dataset = _gdal.GDALCreate(
memdriver,
diff --git a/rasterio/_gdal.pxd b/rasterio/_gdal.pxd
index a4b4154..75b937c 100644
--- a/rasterio/_gdal.pxd
+++ b/rasterio/_gdal.pxd
@@ -232,4 +232,4 @@ cdef extern from "gdal_alg.h":
void GDALDestroyApproxTransformer( void * )
int GDALFillNodata(void *dst_band, void *mask_band, double max_search_distance, int deprecated, int smoothing_iterations, char **options, void *progress_func, void *progress_data)
-
+ int GDALChecksumImage(void *band, int xoff, int yoff, int width, int height)
diff --git a/rasterio/_io.pyx b/rasterio/_io.pyx
index b1bb71b..c317678 100644
--- a/rasterio/_io.pyx
+++ b/rasterio/_io.pyx
@@ -1136,7 +1136,7 @@ cdef class RasterReader(_base.DatasetReader):
stacklevel=2)
if self._hds == NULL:
- raise ValueError("can't write closed raster file")
+ raise ValueError("can't read closed raster file")
hband = _gdal.GDALGetRasterBand(self._hds, 1)
if hband == NULL:
raise ValueError("NULL band mask")
@@ -1684,9 +1684,9 @@ cdef class RasterUpdater(RasterReader):
for i, rgba in colormap.items():
if len(rgba) == 4 and self.driver in ('GTiff'):
- raise ValueError(
- "Format '%s' doesn't support 4 component colormap entries"
- % self.driver)
+ warnings.warn(
+ "This format doesn't support alpha in colormap entries. "
+ "The value will be ignored.")
elif len(rgba) == 3:
rgba = tuple(rgba) + (255,)
diff --git a/rasterio/_warp.pyx b/rasterio/_warp.pyx
index 1e267af..7d4e4f4 100644
--- a/rasterio/_warp.pyx
+++ b/rasterio/_warp.pyx
@@ -246,7 +246,7 @@ def _reproject(
# If the source is an ndarray, we copy to a MEM dataset.
# We need a src_transform and src_dst in this case. These will
# be copied to the MEM dataset.
- if isinstance(source, np.ndarray):
+ if dtypes.is_ndarray(source):
# Convert 2D single-band arrays to 3D multi-band.
if len(source.shape) == 2:
source = source.reshape(1, *source.shape)
@@ -300,7 +300,7 @@ def _reproject(
raise ValueError("Invalid source")
# Next, do the same for the destination raster.
- if isinstance(destination, np.ndarray):
+ if dtypes.is_ndarray(destination):
if len(destination.shape) == 2:
destination = destination.reshape(1, *destination.shape)
if destination.shape[0] != src_count:
@@ -489,11 +489,11 @@ def _reproject(
# _gdal.GDALDestroyApproxTransformer(psWOptions.pTransformerArg)
if psWOptions != NULL:
_gdal.GDALDestroyWarpOptions(psWOptions)
- if isinstance(source, np.ndarray):
+ if dtypes.is_ndarray(source):
if hdsin != NULL:
_gdal.GDALClose(hdsin)
- if reprojected and isinstance(destination, np.ndarray):
+ if reprojected and dtypes.is_ndarray(destination):
retval = _io.io_auto(destination, hdsout, 0)
# TODO: handle errors (by retval).
diff --git a/rasterio/dtypes.py b/rasterio/dtypes.py
index e08f14e..449ec5f 100644
--- a/rasterio/dtypes.py
+++ b/rasterio/dtypes.py
@@ -96,3 +96,9 @@ def get_minimum_int_dtype(values):
return int16
elif min_value >= -2147483648 and max_value <= 2147483647:
return int32
+
+
+def is_ndarray(array):
+ import numpy
+
+ return isinstance(array, numpy.ndarray) or hasattr(array, '__array__')
diff --git a/rasterio/enums.py b/rasterio/enums.py
index 669538e..d33f71d 100644
--- a/rasterio/enums.py
+++ b/rasterio/enums.py
@@ -24,7 +24,7 @@ class Resampling(Enum):
nearest='NEAREST'
gauss='GAUSS'
cubic='CUBIC'
- average='AVERAGE',
+ average='AVERAGE'
mode='MODE'
average_magphase='AVERAGE_MAGPHASE'
none='NONE'
diff --git a/rasterio/rio/bands.py b/rasterio/rio/bands.py
index 09b9c16..f692644 100644
--- a/rasterio/rio/bands.py
+++ b/rasterio/rio/bands.py
@@ -9,26 +9,13 @@ import rasterio
from rasterio.five import zip_longest
-PHOTOMETRIC_CHOICES = [val.lower() for val in [
- 'MINISBLACK',
- 'MINISWHITE',
- 'RGB',
- 'CMYK',
- 'YCBCR',
- 'CIELAB',
- 'ICCLAB',
- 'ITULAB']]
-
-
# Stack command.
@click.command(short_help="Stack a number of bands into a multiband dataset.")
@files_inout_arg
@options.output_opt
@format_opt
@options.bidx_mult_opt
- at click.option('--photometric', default=None,
- type=click.Choice(PHOTOMETRIC_CHOICES),
- help="Photometric interpretation")
+ at options.rgb_opt
@options.creation_options
@click.pass_context
def stack(ctx, files, output, driver, bidx, photometric, creation_options):
diff --git a/rasterio/rio/convert.py b/rasterio/rio/convert.py
index 37fea24..3443b51 100644
--- a/rasterio/rio/convert.py
+++ b/rasterio/rio/convert.py
@@ -29,11 +29,12 @@ warnings.simplefilter('default')
help="Source to destination scaling ratio.")
@click.option('--scale-offset', type=float, default=None,
help="Source to destination scaling offset.")
+ at options.rgb_opt
@options.creation_options
@click.pass_context
def convert(
ctx, files, output, driver, dtype, scale_ratio, scale_offset,
- creation_options):
+ photometric, creation_options):
"""Copy and convert raster datasets to other data types and formats.
Data values may be linearly scaled when copying by using the
@@ -81,6 +82,9 @@ def convert(
profile['dtype'] = dtype
dst_dtype = profile['dtype']
+ if photometric:
+ creation_options['photometric'] = photometric
+
profile.update(**creation_options)
with rasterio.open(outputfile, 'w', **profile) as dst:
diff --git a/rasterio/rio/info.py b/rasterio/rio/info.py
index f6e1890..d86d014 100644
--- a/rasterio/rio/info.py
+++ b/rasterio/rio/info.py
@@ -257,6 +257,9 @@ def env(ctx, key):
@click.option('--stats', 'meta_member', flag_value='stats',
help="Print statistics (min, max, mean) of a single band "
"(use --bidx).")
+ at click.option('--checksum', 'meta_member', flag_value='checksum',
+ help="Print integer checksum of a single band "
+ "(use --bidx).")
@click.option('-v', '--tell-me-more', '--verbose', is_flag=True,
help="Output extra information.")
@options.bidx_opt
@@ -292,6 +295,7 @@ def info(ctx, input, aspect, indent, namespace, meta_member, verbose, bidx,
'mean': float(b.mean())
} for b in src.read(masked=masked)]
info['stats'] = stats
+ info['checksum'] = [src.checksum(i) for i in src.indexes]
if aspect == 'meta':
if meta_member == 'stats':
band = src.read(bidx, masked=masked)
@@ -299,6 +303,8 @@ def info(ctx, input, aspect, indent, namespace, meta_member, verbose, bidx,
float(band.min()),
float(band.max()),
float(band.mean())))
+ elif meta_member == 'checksum':
+ click.echo(str(src.checksum(bidx)))
elif meta_member:
if isinstance(info[meta_member], (list, tuple)):
click.echo(" ".join(map(str, info[meta_member])))
diff --git a/rasterio/rio/main.py b/rasterio/rio/main.py
index 2732654..2282ae5 100644
--- a/rasterio/rio/main.py
+++ b/rasterio/rio/main.py
@@ -8,8 +8,8 @@ from pkg_resources import iter_entry_points
import sys
import click
+from click_plugins import with_plugins
import cligj
-import cligj.plugins
import rasterio
@@ -19,9 +19,9 @@ def configure_logging(verbosity):
logging.basicConfig(stream=sys.stderr, level=log_level)
- at cligj.plugins.group(plugins=(
- ep for ep in list(iter_entry_points('rasterio.rio_commands')) +
- list(iter_entry_points('rasterio.rio_plugins'))))
+ at with_plugins(ep for ep in list(iter_entry_points('rasterio.rio_commands')) +
+ list(iter_entry_points('rasterio.rio_plugins')))
+ at click.group()
@cligj.verbose_opt
@cligj.quiet_opt
@click.version_option(version=rasterio.__version__, message='%(version)s')
diff --git a/rasterio/rio/options.py b/rasterio/rio/options.py
index 1bd6521..0e5aeb8 100644
--- a/rasterio/rio/options.py
+++ b/rasterio/rio/options.py
@@ -153,4 +153,10 @@ creation_options = click.option(
callback=_cb_key_val,
help="Driver specific creation options."
"See the documentation for the selected output driver for "
- "more information.")
\ No newline at end of file
+ "more information.")
+
+rgb_opt = click.option(
+ '--rgb', 'photometric',
+ flag_value='rgb',
+ default=False,
+ help="Set RGB photometric interpretation")
diff --git a/rasterio/rio/overview.py b/rasterio/rio/overview.py
index 1c7892c..231e2d0 100644
--- a/rasterio/rio/overview.py
+++ b/rasterio/rio/overview.py
@@ -50,11 +50,11 @@ def overview(ctx, input, build, ls, rebuild, resampling):
The decimation levels at which to build overviews can be specified as
a comma separated list
- rio pyramid --build 2,4,8,16
+ rio overview --build 2,4,8,16
or a base and range of exponents.
- rio pyramid --build 2^1..4
+ rio overview --build 2^1..4
Note that overviews can not currently be removed and are not
automatically updated when the dataset's primary bands are
@@ -63,7 +63,7 @@ def overview(ctx, input, build, ls, rebuild, resampling):
Information about existing overviews can be printed using the --ls
option.
- rio pyramid --ls
+ rio overview --ls
"""
verbosity = (ctx.obj and ctx.obj.get('verbosity')) or 1
diff --git a/requirements-dev.txt b/requirements-dev.txt
index 5b7ff43..a3e8d64 100644
--- a/requirements-dev.txt
+++ b/requirements-dev.txt
@@ -1,11 +1,12 @@
affine
cligj
coveralls>=0.4
-cython>=0.21.2
+cython==0.22
delocate
enum34
numpy>=1.8.0
snuggs>=1.2
pytest
+pytest-cov
setuptools>=0.9.8
wheel
diff --git a/setup.py b/setup.py
index a45f8b4..c5b2c23 100755
--- a/setup.py
+++ b/setup.py
@@ -197,7 +197,8 @@ inst_reqs = [
'affine>=1.0',
'cligj>=0.2.0',
'Numpy>=1.7',
- 'snuggs>=1.3.1']
+ 'snuggs>=1.3.1',
+ 'click-plugins']
if sys.version_info < (3, 4):
inst_reqs.append('enum34')
diff --git a/tests/test_checksum.py b/tests/test_checksum.py
new file mode 100644
index 0000000..1a6fd4e
--- /dev/null
+++ b/tests/test_checksum.py
@@ -0,0 +1,45 @@
+import rasterio
+
+
+def test_checksum_band():
+ with rasterio.open('tests/data/RGB.byte.tif') as src:
+ checksums = [src.checksum(i) for i in src.indexes]
+ assert checksums == [25420, 29131, 37860]
+
+
+def test_checksum_band_window():
+ with rasterio.open('tests/data/RGB.byte.tif') as src:
+ window = ((0, src.height), (0, src.width))
+ checksums = [src.checksum(i, window=window) for i in src.indexes]
+ assert checksums == [25420, 29131, 37860]
+
+
+def test_checksum_band_window_min():
+ with rasterio.open('tests/data/RGB.byte.tif') as src:
+ window = ((0, 1), (0, 1))
+ checksums = [src.checksum(i, window=window) for i in src.indexes]
+ assert checksums == [0, 0, 0]
+
+
+def test_checksum_band_window_quarter():
+ """A quarter window's checksum is different from the full image's"""
+ with rasterio.open('tests/data/RGB.byte.tif') as src:
+ window = ((0, src.height//2), (0, src.width//2))
+ checksums = [src.checksum(i, window=window) for i in src.indexes]
+ assert checksums != [25420, 29131, 37860]
+
+
+def test_checksum_band_window_too_tall():
+ """Windows get truncated to maximum extent"""
+ with rasterio.open('tests/data/RGB.byte.tif') as src:
+ window = ((0, 10000), (0, src.width))
+ checksums = [src.checksum(i, window=window) for i in src.indexes]
+ assert checksums == [25420, 29131, 37860]
+
+
+def test_checksum_band_window_too_short():
+ """Negative values in windows get evaluated properly"""
+ with rasterio.open('tests/data/RGB.byte.tif') as src:
+ window = ((0, -1), (0, src.width))
+ checksums = [src.checksum(i, window=window) for i in src.indexes]
+ assert checksums == [25420, 29131, 37860]
diff --git a/tests/test_colormap.py b/tests/test_colormap.py
index 112ebfa..5fc7778 100644
--- a/tests/test_colormap.py
+++ b/tests/test_colormap.py
@@ -2,24 +2,28 @@ import logging
import pytest
import subprocess
import sys
+import warnings
import rasterio
+
logging.basicConfig(stream=sys.stderr, level=logging.DEBUG)
-def test_write_colormap_err(tmpdir):
+def test_write_colormap_warn(tmpdir, recwarn):
with rasterio.drivers():
with rasterio.open('tests/data/shade.tif') as src:
- meta = src.meta
+ profile = src.meta
tiffname = str(tmpdir.join('foo.tif'))
- with rasterio.open(tiffname, 'w', **meta) as dst:
- with pytest.raises(ValueError):
- dst.write_colormap(1, {0: (255, 0, 0, 255), 255: (0, 0, 0, 0)})
+ with rasterio.open(tiffname, 'w', **profile) as dst:
+ dst.write_colormap(1, {0: (255, 0, 0, 255), 255: (0, 0, 0, 0)})
+
+ w = recwarn.pop(UserWarning)
+ assert "The value will be ignored" in str(w.message)
def test_write_colormap(tmpdir):
diff --git a/tests/test_dtypes.py b/tests/test_dtypes.py
index 7a41fc7..1826ec5 100644
--- a/tests/test_dtypes.py
+++ b/tests/test_dtypes.py
@@ -1,14 +1,23 @@
import numpy as np
-import rasterio.dtypes
+from rasterio import dtypes, ubyte
+
+
+def test_is_ndarray():
+ assert dtypes.is_ndarray(np.zeros((1,)))
+ assert dtypes.is_ndarray([0]) == False
+ assert dtypes.is_ndarray((0,)) == False
+
def test_np_dt_uint8():
- assert rasterio.dtypes.check_dtype(np.uint8)
+ assert dtypes.check_dtype(np.uint8)
+
def test_dt_ubyte():
- assert rasterio.dtypes.check_dtype(rasterio.ubyte)
+ assert dtypes.check_dtype(ubyte)
+
def test_gdal_name():
- assert rasterio.dtypes._gdal_typename(rasterio.ubyte) == 'Byte'
- assert rasterio.dtypes._gdal_typename(np.uint8) == 'Byte'
- assert rasterio.dtypes._gdal_typename(np.uint16) == 'UInt16'
+ assert dtypes._gdal_typename(ubyte) == 'Byte'
+ assert dtypes._gdal_typename(np.uint8) == 'Byte'
+ assert dtypes._gdal_typename(np.uint16) == 'UInt16'
diff --git a/tests/test_overviews.py b/tests/test_overviews.py
index 381a06e..a219f75 100644
--- a/tests/test_overviews.py
+++ b/tests/test_overviews.py
@@ -38,3 +38,13 @@ def test_build_overviews_two(data):
assert src.overviews(1) == [2, 4]
assert src.overviews(2) == [2, 4]
assert src.overviews(3) == [2, 4]
+
+
+def test_build_overviews_three(data):
+ inputfile = str(data.join('RGB.byte.tif'))
+ with rasterio.open(inputfile, 'r+') as src:
+ overview_factors = [2, 4]
+ src.build_overviews(overview_factors, resampling=Resampling.average)
+ assert src.overviews(1) == [2, 4]
+ assert src.overviews(2) == [2, 4]
+ assert src.overviews(3) == [2, 4]
diff --git a/tests/test_rio_bands.py b/tests/test_rio_bands.py
index dfc6b18..d6d9dd0 100644
--- a/tests/test_rio_bands.py
+++ b/tests/test_rio_bands.py
@@ -5,10 +5,6 @@ import rasterio
from rasterio.rio import bands
-def test_photometic_choices():
- assert len(bands.PHOTOMETRIC_CHOICES) == 8
-
-
def test_stack(tmpdir):
outputname = str(tmpdir.join('stacked.tif'))
runner = CliRunner()
@@ -54,7 +50,7 @@ def test_stack_single_slice(tmpdir):
[
'tests/data/RGB.byte.tif', '--bidx', '1',
'tests/data/RGB.byte.tif', '--bidx', '2..',
- '--photometric', 'rgb',
+ '--rgb',
outputname])
assert result.exit_code == 0
with rasterio.open(outputname) as out:
diff --git a/tests/test_rio_info.py b/tests/test_rio_info.py
index 79c5184..eb4e1f3 100644
--- a/tests/test_rio_info.py
+++ b/tests/test_rio_info.py
@@ -641,3 +641,19 @@ def test_insp_err():
'tests'
])
assert result.exit_code == 1
+
+
+def test_info_checksums():
+ runner = CliRunner()
+ result = runner.invoke(
+ info.info, ['tests/data/RGB.byte.tif', '--tell-me-more'])
+ assert result.exit_code == 0
+ assert '"checksum": [25420, 29131, 37860]' in result.output
+
+
+def test_info_checksums_only():
+ runner = CliRunner()
+ result = runner.invoke(
+ info.info, ['tests/data/RGB.byte.tif', '--checksum', '--bidx', '2'])
+ assert result.exit_code == 0
+ assert result.output.strip() == '29131'
--
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-grass/rasterio.git
More information about the Pkg-grass-devel
mailing list