Commit ee62861e authored by Antoine Laudrain's avatar Antoine Laudrain
Browse files

cut_array: can handle nd-arrays.

parent e4ccf9c7
Pipeline #140103 passed with stages
in 4 minutes and 27 seconds
......@@ -32,6 +32,10 @@ def cut_array(data, every=None, average=None):
Use only one in `every` point.
@param[in] average: int, default None
Average over `average` successive points.
If the length of the last dimension is not a multiple of the
averaging value, the last dimension is truncated.
For example, an input array with shape (10,10,14) and requesting
a 4-average will return an array with shape (10,10,3).
return: np.array
"""
......@@ -39,14 +43,18 @@ def cut_array(data, every=None, average=None):
logger.warning("Selecting one every %d points AND averaging over %d "
"points. This might not do what you expect.")
if every is not None:
data = data[::every]
data = data[...,::every]
if average is not None:
# Truncate last points is average is not a divisor of the data length.
max_len = (len(data) // average) * average
if len(data) != max_len:
max_len = (data.shape[-1] // average) * average
if data.shape[-1] != max_len:
logger.info("Truncating %d points due to averaging.",
len(data) - max_len)
data = data[:max_len].reshape((-1, average)).mean(-1)
data.shape[-1] - max_len)
# Idea: reshape the last dimension, and average over the newly created
# dimension. The original shape is conserved, expect for the length of
# the last dimension.
new_shape = data.shape[:-1] + (-1, average)
data = data[...,:max_len].reshape(new_shape).mean(-1)
return data
......
......@@ -19,11 +19,11 @@ class TestCutArray(ut.TestCase):
def test_no_processing(self):
"""No every and no average should return same as input."""
expected = np.random.rand(10)
expected = np.random.rand(2, 5, 10)
np.testing.assert_equal(cut_array(expected), expected)
def test_every(self):
"""Test every returns sliced points."""
def test_1d_every(self):
"""Test every returns sliced points on 1d arrays."""
np.testing.assert_equal(
cut_array(
np.array([0, 1, 2, 3, 4, 5, 6, 7, 8]),
......@@ -32,8 +32,8 @@ class TestCutArray(ut.TestCase):
np.array([0, 3, 6])
)
def test_average(self):
"""Test averaging."""
def test_1d_average(self):
"""Test averaging on 1d arrays."""
np.testing.assert_equal(
cut_array(
np.array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13]),
......@@ -42,6 +42,70 @@ class TestCutArray(ut.TestCase):
np.array([1.5, 5.5, 9.5])
)
def test_nd_every(self):
"""Test every returned slides points on last dimension."""
np.testing.assert_equal(
cut_array(
np.array([
[
[11, 12, 13, 14, 15, 16, 17, 18, 19],
[21, 22, 23, 24, 25, 26, 27, 28, 29],
[31, 32, 33, 34, 35, 36, 37, 38, 39],
],
[
[41, 42, 43, 44, 45, 46, 47, 48, 49],
[51, 52, 53, 54, 55, 56, 57, 58, 59],
[61, 62, 63, 64, 65, 66, 67, 68, 69],
],
]),
every=2
),
np.array([
[
[11, 13, 15, 17, 19],
[21, 23, 25, 27, 29],
[31, 33, 35, 37, 39],
],
[
[41, 43, 45, 47, 49],
[51, 53, 55, 57, 59],
[61, 63, 65, 67, 69],
],
])
)
def test_nd_average(self):
"""Test averaging on (2,3,9) arrays."""
np.testing.assert_equal(
cut_array(
np.array([
[
[11, 12, 13, 14, 15, 16, 17, 18, 19],
[21, 22, 23, 24, 25, 26, 27, 28, 29],
[31, 32, 33, 34, 35, 36, 37, 38, 39],
],
[
[41, 42, 43, 44, 45, 46, 47, 48, 49],
[51, 52, 53, 54, 55, 56, 57, 58, 59],
[61, 62, 63, 64, 65, 66, 67, 68, 69],
],
]),
average=2
),
np.array([
[
[11.5, 13.5, 15.5, 17.5],
[21.5, 23.5, 25.5, 27.5],
[31.5, 33.5, 35.5, 37.5],
],
[
[41.5, 43.5, 45.5, 47.5],
[51.5, 53.5, 55.5, 57.5],
[61.5, 63.5, 65.5, 67.5],
]
])
)
class TestGetExtsList(ut.TestCase):
"""Test cases for get_exts_list."""
......
......@@ -36,6 +36,10 @@ def cut_array(data, every=None, average=None):
Use only one in `every` point.
@param[in] average: int, default None
Average over `average` successive points.
If the length of the last dimension is not a multiple of the
averaging value, the last dimension is truncated.
For example, an input array with shape (10,10,14) and requesting
a 4-average will return an array with shape (10,10,3).
return: np.array
"""
......@@ -43,14 +47,18 @@ def cut_array(data, every=None, average=None):
logger.warning("Selecting one every %d points AND averaging over %d "
"points. This might not do what you expect.")
if every is not None:
data = data[::every]
data = data[...,::every]
if average is not None:
# Truncate last points is average is not a divisor of the data length.
max_len = (len(data) // average) * average
if len(data) != max_len:
max_len = (data.shape[-1] // average) * average
if data.shape[-1] != max_len:
logger.info("Truncating %d points due to averaging.",
len(data) - max_len)
data = data[:max_len].reshape((-1, average)).mean(-1)
data.shape[-1] - max_len)
# Idea: reshape the last dimension, and average over the newly created
# dimension. The original shape is conserved, expect for the length of
# the last dimension.
new_shape = data.shape[:-1] + (-1, average)
data = data[...,:max_len].reshape(new_shape).mean(-1)
return data
......
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