Repository navigation
Conversation
extend() and += now convert their input to a list, then check every object before changing anything. This rejects duplicates within the iterable (1), handles generators (2), and leaves the list and the objects' parent links unchanged if any object is rejected (5). Membership tests (in, index(), count(), remove()) now compare by identity, as the duplicate check in append() already does (3). reverse() no longer raises after reversing (4). __setitem__ now does the same type, duplicate and parent checks as append(), for both integer and slice keys (6). Container._set_object_list() now raises the TypeError it builds (7). SpikeTrainList's append(), extend(), __setitem__ and += now delegate to ObjectList after converting a multiplexed list to SpikeTrain objects, so they get the same fixes. Fixes NeuralEnsemble#1935. See also NeuralEnsemble#1927.
|
Just glancing this looks great! I'll do a careful read over this tomorrow. |
|
I found one remaining inconsistency in the eager import neo
import quantities as pq
from neo.core.spiketrainlist import SpikeTrainList
st = neo.SpikeTrain([1] * pq.ms, t_stop=10 * pq.ms)
items = SpikeTrainList([st])
items += SpikeTrainList([st])
print(len(items), items.count(st))This prints
If duplicate identities are meant to be rejected here too, this path needs validation before modifying the list. Otherwise, |
|
I see that @viranovskaya. So here do python-neo/neo/core/spiketrainlist.py Lines 178 to 189 in dcc73a0 |
SpikeTrainList's constructor, the in-place `stl += other_stl` path and the list branch of __radd__ add spike trains without the duplicate check, so the same SpikeTrain can be stored twice, after which count() and the list disagree. These paths now go through extend(), or in the case of the constructor perform the same check, which also stops the constructor from silently dropping the contents of a generator. See NeuralEnsemble#1935.
extend() checks each incoming object against the existing items with _contains(), which scans the whole list, so extending a list of n objects by m objects is O(n·m). Since the previous commit routes `stl += other_stl` through extend(), this makes combining two lists of 10,000 SpikeTrains take over a second, where it previously took under a millisecond. extend() now builds the set of existing ids once per call.
|
Thanks @viranovskaya, good catch. Several other Routing
The multiplexed representation is unaffected: |
zm711
left a comment
There was a problem hiding this comment.
This looks good to me now. I'll leave it open until Monday in case anyone else wants to give it a read unless you wanted it merged sooner @apdavison.
Fixes #1935: several bugs in
ObjectList(and its subclassSpikeTrainList) around adding objects, membership tests and validation.Two behaviour changes may surprise anyone relying on the current behaviour:
in,index(),count()andremove()now compare by identity rather than equality, so a different object with equal data is no longer matched.ObjectListto a container's child list (e.g.seg.analogsignals = (sig,)) now raisesTypeErrorinstead of being silently ignored.New tests in
neo/test/coretest/test_objectlist.py,test_spiketrainlist.pyandtest_container.py; 20 of them fail on master.