Fixed #27421 -- Added shape, size, and offset controls to GDALRaster constructor.
Thanks Tim Graham for the review.
This commit is contained in:
parent
501c993010
commit
2dc07da497
|
@ -108,9 +108,22 @@ class GDALRaster(GDALBase):
|
|||
# Set band data if provided
|
||||
for i, band_input in enumerate(ds_input.get('bands', [])):
|
||||
band = self.bands[i]
|
||||
band.data(band_input['data'])
|
||||
if 'nodata_value' in band_input:
|
||||
band.nodata_value = band_input['nodata_value']
|
||||
# Instantiate band filled with nodata values if only
|
||||
# partial input data has been provided.
|
||||
if band.nodata_value is not None and (
|
||||
'data' not in band_input or
|
||||
'size' in band_input or
|
||||
'shape' in band_input):
|
||||
band.data(data=(band.nodata_value,), shape=(1, 1))
|
||||
# Set band data values from input.
|
||||
band.data(
|
||||
data=band_input.get('data'),
|
||||
size=band_input.get('size'),
|
||||
shape=band_input.get('shape'),
|
||||
offset=band_input.get('offset'),
|
||||
)
|
||||
|
||||
# Set SRID
|
||||
self.srs = ds_input.get('srid')
|
||||
|
@ -339,16 +352,12 @@ class GDALRaster(GDALBase):
|
|||
if 'datatype' not in ds_input:
|
||||
ds_input['datatype'] = self.bands[0].datatype()
|
||||
|
||||
# Set the number of bands
|
||||
ds_input['nr_of_bands'] = len(self.bands)
|
||||
# Instantiate raster bands filled with nodata values.
|
||||
ds_input['bands'] = [{'nodata_value': bnd.nodata_value} for bnd in self.bands]
|
||||
|
||||
# Create target raster
|
||||
target = GDALRaster(ds_input, write=True)
|
||||
|
||||
# Copy nodata values to warped raster
|
||||
for index, band in enumerate(self.bands):
|
||||
target.bands[index].nodata_value = band.nodata_value
|
||||
|
||||
# Select resampling algorithm
|
||||
algorithm = GDAL_RESAMPLE_ALGORITHMS[resampling]
|
||||
|
||||
|
|
|
@ -1119,14 +1119,37 @@ blue.
|
|||
'/path/to/your/raster.tif'
|
||||
>>> rst.width, rst.height # This file has 163 x 174 pixels
|
||||
(163, 174)
|
||||
>>> rst = GDALRaster({'srid': 4326, 'width': 1, 'height': 2, 'datatype': 1
|
||||
... 'bands': [{'data': [0, 1]}]}) # Creates in-memory raster
|
||||
>>> rst = GDALRaster({ # Creates an in-memory raster
|
||||
... 'srid': 4326,
|
||||
... 'width': 4,
|
||||
... 'height': 4,
|
||||
... 'datatype': 1,
|
||||
... 'bands': [{
|
||||
... 'data': (2, 3),
|
||||
... 'offset': (1, 1),
|
||||
... 'size': (2, 2),
|
||||
... 'shape': (2, 1),
|
||||
... 'nodata_value': 5,
|
||||
... }]
|
||||
... })
|
||||
>>> rst.srs.srid
|
||||
4326
|
||||
>>> rst.width, rst.height
|
||||
(1, 2)
|
||||
(4, 4)
|
||||
>>> rst.bands[0].data()
|
||||
array([[0, 1]], dtype=int8)
|
||||
array([[5, 5, 5, 5],
|
||||
[5, 2, 3, 5],
|
||||
[5, 2, 3, 5],
|
||||
[5, 5, 5, 5]], dtype=uint8)
|
||||
|
||||
.. versionchanged:: 1.11
|
||||
|
||||
Added the ability to pass the ``size``, ``shape``, and ``offset``
|
||||
parameters when creating :class:`GDALRaster` objects. The parameters
|
||||
can be passed through the ``ds_input`` dictionary. This allows to
|
||||
finely control initial pixel values. The functionality is similar to
|
||||
the :meth:`GDALBand.data()<django.contrib.gis.gdal.GDALBand.data>`
|
||||
method.
|
||||
|
||||
.. attribute:: name
|
||||
|
||||
|
|
|
@ -148,6 +148,9 @@ Minor features
|
|||
|
||||
* PostGIS migrations can now change field dimensions.
|
||||
|
||||
* Added the ability to pass the `size`, `shape`, and `offset` parameter when
|
||||
creating :class:`~django.contrib.gis.gdal.GDALRaster` objects.
|
||||
|
||||
:mod:`django.contrib.messages`
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
|
|
|
@ -190,6 +190,64 @@ class GDALRasterTests(unittest.TestCase):
|
|||
else:
|
||||
self.assertEqual(restored_raster.bands[0].data(), self.rs.bands[0].data())
|
||||
|
||||
def test_offset_size_and_shape_on_raster_creation(self):
|
||||
rast = GDALRaster({
|
||||
'datatype': 1,
|
||||
'width': 4,
|
||||
'height': 4,
|
||||
'srid': 4326,
|
||||
'bands': [{
|
||||
'data': (1,),
|
||||
'offset': (1, 1),
|
||||
'size': (2, 2),
|
||||
'shape': (1, 1),
|
||||
'nodata_value': 2,
|
||||
}],
|
||||
})
|
||||
# Get array from raster.
|
||||
result = rast.bands[0].data()
|
||||
if numpy:
|
||||
result = result.flatten().tolist()
|
||||
# Band data is equal to nodata value except on input block of ones.
|
||||
self.assertEqual(
|
||||
result,
|
||||
[2, 2, 2, 2, 2, 1, 1, 2, 2, 1, 1, 2, 2, 2, 2, 2]
|
||||
)
|
||||
|
||||
def test_set_nodata_value_on_raster_creation(self):
|
||||
# Create raster filled with nodata values.
|
||||
rast = GDALRaster({
|
||||
'datatype': 1,
|
||||
'width': 2,
|
||||
'height': 2,
|
||||
'srid': 4326,
|
||||
'bands': [{'nodata_value': 23}],
|
||||
})
|
||||
# Get array from raster.
|
||||
result = rast.bands[0].data()
|
||||
if numpy:
|
||||
result = result.flatten().tolist()
|
||||
# All band data is equal to nodata value.
|
||||
self.assertEqual(result, [23, ] * 4)
|
||||
|
||||
def test_set_nodata_none_on_raster_creation(self):
|
||||
if GDAL_VERSION < (2, 1):
|
||||
self.skipTest("GDAL >= 2.1 is required for this test.")
|
||||
# Create raster without data and without nodata value.
|
||||
rast = GDALRaster({
|
||||
'datatype': 1,
|
||||
'width': 2,
|
||||
'height': 2,
|
||||
'srid': 4326,
|
||||
'bands': [{'nodata_value': None}],
|
||||
})
|
||||
# Get array from raster.
|
||||
result = rast.bands[0].data()
|
||||
if numpy:
|
||||
result = result.flatten().tolist()
|
||||
# Band data is equal to zero becaues no nodata value has been specified.
|
||||
self.assertEqual(result, [0] * 4)
|
||||
|
||||
def test_raster_warp(self):
|
||||
# Create in memory raster
|
||||
source = GDALRaster({
|
||||
|
@ -246,6 +304,29 @@ class GDALRasterTests(unittest.TestCase):
|
|||
12.0, 13.0, 14.0, 15.0]
|
||||
)
|
||||
|
||||
def test_raster_warp_nodata_zone(self):
|
||||
# Create in memory raster.
|
||||
source = GDALRaster({
|
||||
'datatype': 1,
|
||||
'driver': 'MEM',
|
||||
'width': 4,
|
||||
'height': 4,
|
||||
'srid': 3086,
|
||||
'origin': (500000, 400000),
|
||||
'scale': (100, -100),
|
||||
'skew': (0, 0),
|
||||
'bands': [{
|
||||
'data': range(16),
|
||||
'nodata_value': 23,
|
||||
}],
|
||||
})
|
||||
# Warp raster onto a location that does not cover any pixels of the original.
|
||||
result = source.warp({'origin': (200000, 200000)}).bands[0].data()
|
||||
if numpy:
|
||||
result = result.flatten().tolist()
|
||||
# The result is an empty raster filled with the correct nodata value.
|
||||
self.assertEqual(result, [23] * 16)
|
||||
|
||||
def test_raster_transform(self):
|
||||
if GDAL_VERSION < (1, 8, 1):
|
||||
self.skipTest("GDAL >= 1.8.1 is required for this test")
|
||||
|
|
Loading…
Reference in New Issue