__keyitem__ parameter now assumed to be either integer or slice. No

longer erroring out when mixing resolution reduction with horiz/vert
slicing, but neither is it tested.
This commit is contained in:
John Evans 2014-09-12 16:46:08 -04:00
commit f7b7b9a0df
2 changed files with 34 additions and 54 deletions

View file

@ -759,60 +759,51 @@ class Jp2k(Jp2kBox):
return boxes return boxes
def __getitem__(self, *pargs): def __getitem__(self, pargs):
""" """
Slicing protocol. Slicing protocol.
""" """
if isinstance(pargs[0], slice): if isinstance(pargs, slice):
# Case of jp2[:]
#
# Should have a slice object where start = stop = step = None # Should have a slice object where start = stop = step = None
slc = pargs[0] slc = pargs
if slc.start is None and slc.stop is None and slc.step is None: if slc.start is None and slc.stop is None and slc.step is None:
return self.read() return self.read()
else: else:
raise IndexError("Illegal syntax.") raise IndexError("Illegal syntax.")
if not isinstance(pargs[0], tuple): # Assuming pargs is a tuple from now on.
msg = "Unexpected situation, slicing invoked, but not passed " rows = pargs[0]
msg += "a slice or tuple." cols = pargs[1]
raise RuntimeError(msg) if len(pargs) == 2:
bands = slice(None, None, None)
else:
bands = pargs[2]
# Assuming tuple from now on. if ((rows.step is None) and (cols.step is None)):
ridx = pargs[0][0]
cidx = pargs[0][1]
bidx = pargs[0][2]
if ((ridx.step is None) and (cidx.step is None)):
# Slicing with full resolution. # Slicing with full resolution.
return self.read()[ridx, cidx, bidx] # This can be improved to take advantage of tiling.
return self.read()[rows, cols, bands]
if ((ridx.start is not None) or if rows.step != cols.step:
(ridx.stop is not None) or
(cidx.start is not None) or
(cidx.stop is not None)):
msg = "Only strides are supported when slicing a Jp2k object."
raise IndexError(msg)
if ridx.step is None and cidx.step is None:
step = 1
elif ridx.step != cidx.step:
msg = "Row and column strides must be the same." msg = "Row and column strides must be the same."
raise IndexError(msg) raise IndexError(msg)
else:
step = ridx.step # Ok, reduce layer step is the same in both xy directions, so just take
# one of them.
step = rows.step
if np.log2(step) != np.floor(np.log2(step)): if np.log2(step) != np.floor(np.log2(step)):
msg = "Row and column strides must be powers of 2." msg = "Row and column strides must be powers of 2."
raise IndexError(msg) raise IndexError(msg)
data = self.read(rlevel=np.int(np.log2(step))) data = self.read(rlevel=np.int(np.log2(step)))
if len(pargs[0]) == 2: if len(pargs) == 2:
return data return data
# Ok, 3 arguments in pargs. # Ok, 3 arguments in pargs.
if isinstance(pargs[0][2], slice): return data[:, :, bands]
return data[:,:,pargs[0][2]]
elif isinstance(pargs[0][2], int):
return data[:,:,pargs[0][2]]
def read(self, **kwargs): def read(self, **kwargs):

View file

@ -74,24 +74,11 @@ class TestSliceProtocol(unittest.TestCase):
with self.assertRaises(IndexError): with self.assertRaises(IndexError):
self.j2k[::3, ::3] self.j2k[::3, ::3]
def test_start_and_resolution_stride_not_allowed_at_same_time(self):
with self.assertRaises(IndexError):
self.j2k[2::2, 2::2]
def test_stop_and_resolution_stride_not_allowed_at_same_time(self):
with self.assertRaises(IndexError):
self.j2k[:8:2, :8:2]
def test_integer_index_in_3d(self): def test_integer_index_in_3d(self):
d = self.j2k[:,:,0] for j in [0, 1, 2]:
np.testing.assert_array_equal(self.j2k_data[:,:,0], d) band = self.j2k[:, :, j]
np.testing.assert_array_equal(self.j2k_data[:, :, j], band)
d = self.j2k[:,:,1]
np.testing.assert_array_equal(self.j2k_data[:,:,1], d)
d = self.j2k[:,:,2]
np.testing.assert_array_equal(self.j2k_data[:,:,2], d)
def test_slice_in_third_dimension(self): def test_slice_in_third_dimension(self):
actual = self.j2k[:,:,1:3] actual = self.j2k[:,:,1:3]
@ -103,13 +90,15 @@ class TestSliceProtocol(unittest.TestCase):
all = self.j2k.read(rlevel=1) all = self.j2k.read(rlevel=1)
np.testing.assert_array_equal(all[:,:,1:3], d) np.testing.assert_array_equal(all[:,:,1:3], d)
def test_full_resolution_slicing_by_quarters(self): def test_full_resolution_slicing_by_quarters_upper_left(self):
# upper left actual = self.jp2[:728, :1296]
np.testing.assert_array_equal(self.jp2_data[:728, :1296], expected = self.jp2_data[:728, :1296]
self.jp2[:728, :1296]) np.testing.assert_array_equal(actual, expected)
# lower left
np.testing.assert_array_equal(self.jp2_data[728:, :1296], def test_full_resolution_slicing_by_quarters_lower_left(self):
self.jp2[728:, :1296]) actual = self.jp2[728:, :1296]
expected = self.jp2_data[728:, :1296]
np.testing.assert_array_equal(actual, expected)
def test_full_resolution_slicing_by_quarters_upper_right(self): def test_full_resolution_slicing_by_quarters_upper_right(self):
actual = self.jp2[:728, 1296:] actual = self.jp2[:728, 1296:]