66"""
77
88from copy import deepcopy
9+
10+ from neo .core import filters
911from neo .core .baseneo import BaseNeo , _reference_name , _container_name
1012from neo .core .objectlist import ObjectList
1113from neo .core .spiketrain import SpikeTrain
@@ -21,24 +23,25 @@ def unique_objs(objs):
2123 return [obj for obj in objs
2224 if id (obj ) not in seen and not seen .add (id (obj ))]
2325
24-
2526def filterdata (data , targdict = None , objects = None , ** kwargs ):
2627 """
2728 Return a list of the objects in data matching *any* of the search terms
2829 in either their attributes or annotations. Search terms can be
2930 provided as keyword arguments or a dictionary, either as a positional
30- argument after data or to the argument targdict. targdict can also
31- be a list of dictionaries, in which case the filters are applied
32- sequentially. If targdict and kwargs are both supplied, the
33- targdict filters are applied first, followed by the kwarg filters.
34- A targdict of None or {} and objects = None corresponds to no filters
35- applied, therefore returning all child objects.
36- Default targdict and objects is None.
31+ argument after data or to the argument targdict.
32+ A key of a provided dictionary is the name of the requested annotation
33+ and the value is a FilterCondition object.
34+ E.g.: Equal(x), LessThan(x), InRange(x, y).
3735
36+ targdict can also
37+ be a list of dictionaries, in which case the filters are applied
38+ sequentially.
3839
39- objects (optional) should be the name of a Neo object type,
40- a neo object class, or a list of one or both of these. If specified,
41- only these objects will be returned.
40+ A list of dictionaries is handled as follows: [ { or } and { or } ]
41+ If targdict and kwargs are both supplied, the
42+ targdict filters are applied first, followed by the kwarg filters.
43+ A targdict of None or {} corresponds to no filters applied, therefore
44+ returning all child objects. Default targdict is None.
4245 """
4346
4447 # if objects are specified, get the classes
@@ -72,20 +75,26 @@ def filterdata(data, targdict=None, objects=None, **kwargs):
7275 else :
7376 # do the actual filtering
7477 results = []
75- for key , value in sorted (targdict .items ()):
76- for obj in data :
77- if (hasattr (obj , key ) and getattr (obj , key ) == value and
78- all ([obj is not res for res in results ])):
78+ for obj in data :
79+ for key , value in sorted (targdict .items ()):
80+ if hasattr (obj , key ) and getattr (obj , key ) == value :
7981 results .append (obj )
80- elif (key in obj .annotations and obj .annotations [key ] == value and
81- all ([obj is not res for res in results ])):
82+ break
83+ if isinstance (value , filters .FilterCondition ) and key in obj .annotations :
84+ if value .evaluate (obj .annotations [key ]):
85+ results .append (obj )
86+ break
87+ if key in obj .annotations and obj .annotations [key ] == value :
8288 results .append (obj )
89+ break
90+
91+ # remove duplicates from results
92+ results = list ({ id (res ): res for res in results }.values ())
8393
8494 # keep only objects of the correct classes
8595 if objects :
8696 results = [result for result in results if
87- result .__class__ in objects or
88- result .__class__ .__name__ in objects ]
97+ result .__class__ in objects or result .__class__ .__name__ in objects ]
8998
9099 if results and all (isinstance (obj , SpikeTrain ) for obj in results ):
91100 return SpikeTrainList (results )
@@ -366,9 +375,17 @@ def filter(self, targdict=None, data=True, container=False, recursive=True,
366375 Return a list of child objects matching *any* of the search terms
367376 in either their attributes or annotations. Search terms can be
368377 provided as keyword arguments or a dictionary, either as a positional
369- argument after data or to the argument targdict. targdict can also
378+ argument after data or to the argument targdict.
379+ A key of a provided dictionary is the name of the requested annotation
380+ and the value is a FilterCondition object.
381+ E.g.: equal(x), less_than(x), InRange(x, y).
382+
383+ targdict can also
370384 be a list of dictionaries, in which case the filters are applied
371- sequentially. If targdict and kwargs are both supplied, the
385+ sequentially.
386+
387+ A list of dictionaries is handled as follows: [ { or } and { or } ]
388+ If targdict and kwargs are both supplied, the
372389 targdict filters are applied first, followed by the kwarg filters.
373390 A targdict of None or {} corresponds to no filters applied, therefore
374391 returning all child objects. Default targdict is None.
@@ -391,6 +408,8 @@ def filter(self, targdict=None, data=True, container=False, recursive=True,
391408 >>> obj.filter(name="Vm")
392409 >>> obj.filter(objects=neo.SpikeTrain)
393410 >>> obj.filter(targdict={'myannotation':3})
411+ >>> obj.filter(name=neo.core.filters.Equal(5))
412+ >>> obj.filter({'name': neo.core.filters.LessThan(5)})
394413 """
395414
396415 if isinstance (targdict , str ):
0 commit comments