Commit 9127bcd5 authored by Daniel Scheffler's avatar Daniel Scheffler

Fixed GeoArray.get_subset().

parent 976ca203
Pipeline #1700 passed with stages
in 1 minute and 25 seconds
......@@ -1409,7 +1409,7 @@ class GeoArray(object):
progress=progress)
return sub_arr, sub_gt, sub_prj
def get_subset(self, xslice=slice(None), yslice=slice(None), zslice=slice(None), return_GeoArray=True,
def get_subset(self, xslice=None, yslice=None, zslice=None, return_GeoArray=True,
reset_bandnames=False):
# type: (slice, slice, slice, bool, bool) -> GeoArray
"""Returns a new instance of GeoArray representing a subset of the initial one wit respect to given array position.
......@@ -1422,26 +1422,38 @@ class GeoArray(object):
'B1', 'B2', 'B3', ...
:return:
"""
sub_arr = self[yslice, xslice, zslice] # row, col, band
xslice, yslice, zslice = xslice or slice(None), yslice or slice(None), zslice or slice(None)
zslicing = zslice.start is not None or zslice.stop is not None or zslice.step is not None # type: bool
# get sub_arr
if zslicing:
# validation
if self.ndim == 2:
raise ValueError('Invalid zslice. A 2D GeoArray is not slicable in z-direction.')
sub_arr = self[yslice, xslice, zslice] # row, col, band
else:
sub_arr = self[yslice, xslice] # row, col
if sub_arr is None:
raise ValueError('Unable to return an array for the given slice parameters.')
# adapt geotransform
sub_ulXY = imXY2mapXY((xslice.start or 0, yslice.start or 0), self.gt)
sub_gt = (sub_ulXY[0], self.gt[1], self.gt[2], sub_ulXY[1], self.gt[4], self.gt[5])
# apply zslice to bandnames and metadata
if zslice:
if zslicing:
bNs_out = list(np.array(list(self.bandnames))[zslice])
meta_out = None if self._metadata is None else self.meta[list(np.array(range(self.bands))[zslice])]
_meta_out = None if self._metadata is None else self.meta[list(np.array(range(self.bands))[zslice])]
else:
bNs_out = list(self.bandnames)
meta_out = self.meta
_meta_out = self.meta
# get output GeoArray and copy some properties from the input GeoArray
sub_gA = GeoArray(sub_arr, sub_gt, self.prj,
bandnames=bNs_out, nodata=self.nodata, progress=self.progress, q=self.q)
sub_gA.meta = meta_out
sub_gA._metadata = _meta_out
sub_gA.filePath = self.filePath
if reset_bandnames:
......
......@@ -450,7 +450,7 @@ class Test_GeoarrayFunctions(unittest.TestCase):
for ((rS, rE), (cS, cE)), tile in tiles:
self.assertTrue(np.array_equal(tile, self.testtiff[rS: rE + 1, cS: cE + 1]))
def test_get_subset(self):
def test_get_subset_3D_geoarray(self):
# test without resetting band names
sub_gA = self.testtiff.get_subset(xslice=slice(2, 5), yslice=slice(None, 3), zslice=slice(1, 2))
self.assertIsInstance(sub_gA, GeoArray)
......@@ -483,6 +483,43 @@ class Test_GeoarrayFunctions(unittest.TestCase):
self.assertIsInstance(out[1], tuple)
self.assertIsInstance(out[2], str)
def test_get_subset_2D_geoarray(self):
gA_2D = GeoArray(self.testtiff[0])
# test without resetting band names
sub_gA = self.testtiff.get_subset(xslice=slice(2, 5), yslice=slice(None, 3))
self.assertIsInstance(sub_gA, GeoArray)
self.assertTrue(list(sub_gA.bandnames), list(self.testtiff.bandnames)[1])
# test with providing only xslice
sub_gA = gA_2D.get_subset(xslice=slice(2, 5))
self.assertIsInstance(sub_gA, GeoArray)
# test with providing only yslice
sub_gA = gA_2D.get_subset(yslice=slice(None, 3))
self.assertIsInstance(sub_gA, GeoArray)
# test without providing zslice
sub_gA = gA_2D.get_subset(xslice=slice(2, 5), yslice=slice(None, 3))
self.assertIsInstance(sub_gA, GeoArray)
# test with resetting band names
sub_gA = gA_2D.get_subset(xslice=slice(2, 5), yslice=slice(None, 3), reset_bandnames=True)
self.assertTrue(list(sub_gA.bandnames), ['B1'])
# test not to return GeoArray
out = gA_2D.get_subset(xslice=slice(2, 5), yslice=slice(None, 3), return_GeoArray=False)
# test with provided zslice
with self.assertRaises(ValueError):
gA_2D.get_subset(xslice=slice(2, 5), yslice=slice(None, 3), zslice=slice(1, 2))
self.assertIsInstance(out, tuple)
self.assertTrue(len(out), 3)
self.assertIsInstance(out[0], np.ndarray)
self.assertIsInstance(out[1], tuple)
self.assertIsInstance(out[2], str)
def test_save(self):
"""
Testing the function: save,
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment