Skip to content
Browse files

WIP Prof of concept adding setitem support to lix.

  • Loading branch information...
1 parent 3a68b19 commit 370a09ee51c25e694c14d0d2cb80596c7de5a8b4 @kwgoodman committed
Showing with 124 additions and 23 deletions.
  1. +2 −2 README.rst
  2. +69 −13 la/deflarry.py
  3. +53 −8 la/tests/lix_test.py
View
4 README.rst
@@ -122,9 +122,9 @@ After you have installed ``la``, run the suite of unit tests::
>>> import la
>>> la.test()
<snip>
- Ran 3002 tests in 9.225s
+ Ran 3009 tests in 9.225s
OK
- <nose.result.TextTestResult run=3002 errors=0 failures=0>
+ <nose.result.TextTestResult run=3009 errors=0 failures=0>
The ``la`` package contains C extensions that speed up common alignment
operations such as adding two unaligned larrys. If the C extensions don't
View
82 la/deflarry.py
@@ -1926,7 +1926,7 @@ def lix(self):
array([1, 4])
"""
- return Getitemlabel(self)
+ return Lix(self)
def __setitem__(self, index, value):
"""
@@ -4848,13 +4848,15 @@ def __repr__(self):
# Label indexing support functions for the lix method ------------------------
-class Getitemlabel(object):
+class Lix(object):
"Utility class for the lix method."
def __init__(self2, self):
self2.lar = self
def __getitem__(self2, index):
+ # Note: setitem uses the same (slightly modified) code
+ # So if you update this code update setitem as well
y = self2.lar
if y.shape == (0,):
return self2.lar
@@ -4866,9 +4868,9 @@ def __getitem__(self2, index):
if typ == list:
# Example: lar.lix[['a', 'b', 'c']]
index2 = labels2indices(y.label[0], index)
- if len(index) == 1:
+ if len(index) == 1:
index2 = index2[0]
- return y[index2]
+ return y[index2]
elif typ == slice:
# Examples: lar.lix[['a']:], lar.lix[['a']:['b']],
# lar.lix[['a']:['b']:2], lar.lix[2:['b']]
@@ -4881,35 +4883,90 @@ def __getitem__(self2, index):
elif len(index) < y.ndim:
index3 = list(index) + [slice(None)] * (y.ndim - len(index))
else:
- raise IndexError, 'Invalid index'
+ raise IndexError, 'Invalid index'
for ax, idx in enumerate(index3):
typ = type(idx)
if typ == list:
idx2 = labels2indices(y.label[ax], idx)
- if len(idx) > 1:
+ if len(idx) > 1:
label.append(idx)
index2.append(idx2)
- elif typ == slice:
+ elif typ == slice:
s = slicemaker(idx, y.labelindex, ax)
slar = range(*s.indices(y.shape[ax]))
lab = y.label[ax][s]
if len(lab) > 1:
- label.append(lab)
+ label.append(lab)
index2.append(slar)
elif isscalar(idx):
- index2.append([idx])
+ index2.append([idx])
else:
raise IndexError, 'Unsupported indexing operation.'
x = np.squeeze(y.x[np.ix_(*index2)])
if x.ndim == 0:
return x[()]
else:
- return larry(x, label)
+ return larry(x, label)
elif isscalar(index):
# Example: lar.lix[0]
- return y[index]
+ return y[index]
else:
- raise IndexError, 'Unsupported indexing operation.'
+ raise IndexError, 'Unsupported indexing operation.'
+
+ def __setitem__(self2, index, value):
+ # Note: getitem uses the same (slightly modified) code
+ # So if you update this code update getitem as well
+ y = self2.lar
+ if y.shape == (0,):
+ raise IndexError('index out of bounds')
+ elif 0 in y.shape:
+ msg = 'lix does not support shapes that contain 0 '
+ msg += 'such as (0,) and (2, 0 ,3).'
+ raise ValueError, msg
+ typ = type(index)
+ if typ == list:
+ # Example: lar.lix[['a', 'b', 'c']]
+ index2 = labels2indices(y.label[0], index)
+ if len(index) == 1:
+ index2 = index2[0]
+ y[index2] = value
+ elif typ == slice:
+ # Examples: lar.lix[['a']:], lar.lix[['a']:['b']],
+ # lar.lix[['a']:['b']:2], lar.lix[2:['b']]
+ y[slicemaker(index, y.labelindex, 0)] = value
+ elif typ == tuple:
+ index2 = []
+ label = []
+ if len(index) == y.ndim:
+ index3 = index
+ elif len(index) < y.ndim:
+ index3 = list(index) + [slice(None)] * (y.ndim - len(index))
+ else:
+ raise IndexError, 'Invalid index'
+ for ax, idx in enumerate(index3):
+ typ = type(idx)
+ if typ == list:
+ idx2 = labels2indices(y.label[ax], idx)
+ if len(idx) > 1:
+ label.append(idx)
+ index2.append(idx2)
+ elif typ == slice:
+ s = slicemaker(idx, y.labelindex, ax)
+ slar = range(*s.indices(y.shape[ax]))
+ lab = y.label[ax][s]
+ if len(lab) > 1:
+ label.append(lab)
+ index2.append(slar)
+ elif isscalar(idx):
+ index2.append([idx])
+ else:
+ raise IndexError, 'Unsupported indexing operation.'
+ y.x[np.ix_(*index2)] = value
+ elif isscalar(index):
+ # Example: lar.lix[0]
+ y[index] = value
+ else:
+ raise IndexError, 'Unsupported indexing operation.'
def slicemaker(index, labelindex, axis):
"Convert a slice that may contain labels to a slice with indices."
@@ -4944,4 +5001,3 @@ def labels2indices(label, labels):
except ValueError:
raise ValueError, 'Could not map label to index value.'
return indices
-
View
61 la/tests/lix_test.py
@@ -3,8 +3,10 @@
import numpy as np
from numpy.testing import assert_equal
+import la
from la import larry
from la.util.misc import isscalar
+from la.util.testing import assert_larry_equal as ale
S = slice
N = None
@@ -106,11 +108,54 @@ def test_lix(si=si):
msg = '\nlix fail on shape %s and index %s\n'
yield assert_equal, actual, desired, msg % (str(shape), str(index))
-
-
-
-
-
-
-
-
+# ---------------------------------------------------------------------------
+# Test lix setitem
+
+def lix_setitem_test_01():
+ actual = la.lrange(label=[['a', 'b']])
+ actual.lix[['a']] = 9
+ desired = la.lrange(label=[['a', 'b']])
+ desired[0] = 9
+ ale(actual, desired)
+
+def lix_setitem_test_02():
+ actual = la.lrange(label=[['a', 'b'], ['c', 'd']])
+ actual.lix[['a']] = 9
+ desired = la.lrange(label=[['a', 'b'], ['c', 'd']])
+ desired[0] = 9
+ ale(actual, desired)
+
+def lix_setitem_test_03():
+ actual = la.lrange(label=[['a', 'b'], ['c', 'd']])
+ actual.lix[0] = 9
+ desired = la.lrange(label=[['a', 'b'], ['c', 'd']])
+ desired[0] = 9
+ ale(actual, desired)
+
+def lix_setitem_test_04():
+ actual = la.lrange(label=[['a', 'b'], ['c', 'd']])
+ actual.lix[['a']:['b']] = 9
+ desired = la.lrange(label=[['a', 'b'], ['c', 'd']])
+ desired[0:1] = 9
+ ale(actual, desired)
+
+def lix_setitem_test_05():
+ actual = la.lrange(label=[['a', 'b'], ['c', 'd']])
+ actual.lix[['b'], ['d']] = 9
+ desired = la.lrange(label=[['a', 'b'], ['c', 'd']])
+ desired[1, 1] = 9
+ ale(actual, desired)
+
+def lix_setitem_test_06():
+ actual = la.lrange(label=[['a', 'b', 'c'], ['1', '2', '3']])
+ actual.lix[['a', 'b'], ['1', '2']] = 9
+ desired = la.lrange(label=[['a', 'b', 'c'], ['1', '2', '3']])
+ desired[:2, :2] = 9
+ ale(actual, desired)
+
+def lix_setitem_test_07():
+ actual = la.lrange(label=[['a', 'b', 'c'], ['1', '2', '3']])
+ actual.lix[['a', 'b'], ['1', '2']] = np.arange(4).reshape(2, 2)
+ desired = la.lrange(label=[['a', 'b', 'c'], ['1', '2', '3']])
+ desired[:2, :2] = np.arange(4).reshape(2, 2)
+ ale(actual, desired)

0 comments on commit 370a09e

Please sign in to comment.
Something went wrong with that request. Please try again.