Add snap_in/fuzzyval to NeighborList
This commit is contained in:
parent
a514385ff5
commit
7868e57520
@ -242,5 +242,41 @@ class RaiseTests(TestCase):
|
||||
self.assertEqual(self.nl.idx, 4)
|
||||
|
||||
|
||||
class SnapInTests(TestCase):
|
||||
|
||||
"""Tests for the fuzzyval/_snap_in features."""
|
||||
|
||||
def setUp(self):
|
||||
self.nl = NeighborList([20, 9, 1, 5])
|
||||
|
||||
def test_bigger(self):
|
||||
self.nl.fuzzyval = 7
|
||||
self.assertEqual(self.nl.nextitem(), 9)
|
||||
self.assertEqual(self.nl.idx, 1)
|
||||
self.assertEqual(self.nl.nextitem(), 1)
|
||||
self.assertEqual(self.nl.idx, 2)
|
||||
|
||||
def test_smaller(self):
|
||||
self.nl.fuzzyval = 7
|
||||
self.assertEqual(self.nl.previtem(), 5)
|
||||
self.assertEqual(self.nl.idx, 3)
|
||||
self.assertEqual(self.nl.previtem(), 1)
|
||||
self.assertEqual(self.nl.idx, 2)
|
||||
|
||||
def test_equal_bigger(self):
|
||||
self.nl.fuzzyval = 9
|
||||
self.assertEqual(self.nl.nextitem(), 9)
|
||||
self.assertEqual(self.nl.idx, 1)
|
||||
self.assertEqual(self.nl.nextitem(), 1)
|
||||
self.assertEqual(self.nl.idx, 2)
|
||||
|
||||
def test_equal_smaller(self):
|
||||
self.nl.fuzzyval = 9
|
||||
self.assertEqual(self.nl.previtem(), 9)
|
||||
self.assertEqual(self.nl.idx, 1)
|
||||
self.assertEqual(self.nl.previtem(), 20)
|
||||
self.assertEqual(self.nl.idx, 0)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main()
|
||||
|
@ -21,6 +21,7 @@ Module attributes:
|
||||
_UNSET: Used as default argument in the constructor so default can be None.
|
||||
"""
|
||||
|
||||
import operator
|
||||
import logging
|
||||
|
||||
_UNSET = object()
|
||||
@ -63,6 +64,7 @@ class NeighborList:
|
||||
|
||||
Attributes:
|
||||
idx: The current position in the list.
|
||||
fuzzyval: The value which is currently set but not in the list.
|
||||
_items: A list of all items, accessed through item property.
|
||||
_mode: The current mode.
|
||||
"""
|
||||
@ -90,6 +92,20 @@ class NeighborList:
|
||||
else:
|
||||
self.idx = None
|
||||
self._mode = mode
|
||||
self.fuzzyval = None
|
||||
|
||||
def _snap_in(self, offset):
|
||||
"""Set the current item to the closest item to self.fuzzyval.
|
||||
|
||||
Args:
|
||||
offset: negative to get the next smaller item, positive for the
|
||||
next bigger one.
|
||||
"""
|
||||
op = operator.le if offset < 0 else operator.ge
|
||||
items = [(idx, e) for (idx, e) in enumerate(self._items)
|
||||
if op(e, self.fuzzyval)]
|
||||
close_item = min(items, key=lambda tpl: abs(self.fuzzyval - tpl[1]))
|
||||
self.idx = close_item[0]
|
||||
|
||||
@property
|
||||
def items(self):
|
||||
@ -113,6 +129,16 @@ class NeighborList:
|
||||
self.idx, offset))
|
||||
if not self._items:
|
||||
raise IndexError("No items found!")
|
||||
if self.fuzzyval is not None:
|
||||
# Value has been set to something not in the list, so we snap in to
|
||||
# the closest value in the right direction and count this as one
|
||||
# step towards offset.
|
||||
self._snap_in(offset)
|
||||
if offset > 0:
|
||||
offset -= 1
|
||||
else:
|
||||
offset += 1
|
||||
self.fuzzyval = None
|
||||
try:
|
||||
if self.idx + offset >= 0:
|
||||
new = self._items[self.idx + offset]
|
||||
|
Loading…
Reference in New Issue
Block a user