python-neo icon indicating copy to clipboard operation
python-neo copied to clipboard

Feature/new filter

Open kloss-o opened this issue 3 years ago • 7 comments

Until now it was not so easy to filter for multiple values with the filter function in neo. To solve this problem, I introduced "FilterConditions". These can be provided to the filter function as the value of a dictionary.

An example of the syntax:

seg.filter({“electrode_id”: FilterCondition) or seg.filter(electrode_id = FilterCondition)

In order to be able to filter for several electrode_ids, there are some objects that inherit from FilterCondition and provide different filtering options.

For example, seg.filter({"electrode_id": neo.FilterIsIn([0, 1, 5]) can be used to filter for all objects with electrode_id 0, 1 or 5.

List of all currently added FilterConditions:

-FilterEqual(x), returns id == x

-FilterIsNot(x), returns id != x

-FilterLessThan(x), returns id < x

-FilterLessThanEqual(x), returns id <= x

-FilterGreaterThan(x), returns id > x

-FilterGreaterThanEqual(x), returns id >= x

-FilterIsIn([x, y, z]), returns id == x or id == y or id == z

-FilterInRange(a, b), returns a <= id <= b

Additional FilterConditions can be added at any time and without much effort.

kloss-o avatar Feb 04 '22 11:02 kloss-o

Hello @kloss-o! Thanks for updating this PR. We checked the lines you've touched for PEP 8 issues, and found:

There are currently no PEP 8 issues detected in this Pull Request. Cheers! :beers:

Comment last updated at 2022-06-28 12:08:16 UTC

pep8speaks avatar Feb 04 '22 11:02 pep8speaks

Thank you for your feedback and suggestions. I'm looking into it.

kloss-o avatar Feb 10 '22 13:02 kloss-o

Thanks for the PR, Oliver, and for reviewing the code, Julia.

Regarding performance, there is actually another follow-up PR by @kloss-o in prep that would improve filtering speed quite a bit, but unrelated to this concrete implementation. @kloss-o , I think when you did some benchmarking the FilterCondition implementation (without further optimization) was comparable in speed to the traditional implementation?

The idea behind the different Filter classes was, for one, that it would allow users to also define their own "custom" filters as a filter function, like (in pseudocode):

class FilterGoodElectrodesSurroundedByGoodOnes(FilterCondition)
    def test(electrode):
       return is_good_quality[electrode] and np.all(is_good_quality[i] for i in neighbor_electrodes(electrode])

Secondly, that it would not require any new or ambiguous syntax (e.g., something like ["property", "<=", 5]) in the function call to filter(). In particular, the neo filter function would continue to work as before with the existing syntax, but adds additional functionality.

However, I think there are many other options. An alternative could be to revert to, e.g., simple filter functions, at the expense of being slightly more ambiguous.

mdenker avatar Feb 10 '22 13:02 mdenker

The following notebook is intended to show the application of the 'new filter' function in practice. The use cases were derived from the Neo - Elephant tutorials and aim to demonstrate how the suggested 'new filter' improves the workflow.

Link to notebook tutorial_new_filter_examples.ipynb:

GitHub gist: https://gist.github.com/Moritz-Alexander-Kern/afdfb707bde9052c6cd02ccddd2c4b9e GIN: https://gin.g-node.org/NeuralEnsemble/neo_elephant_teaching/src/new_filter/tutorial_new_filter_examples.ipynb

Moritz-Alexander-Kern avatar May 09 '22 10:05 Moritz-Alexander-Kern

Here some notes on the discussion of this PR during the neo core meeting today.

JuliaSprenger avatar May 11 '22 19:05 JuliaSprenger

Hi @kloss-o @Moritz-Alexander-Kern any news on this? Tell me if the notes from the last meeting are not detailed enough for you to continue on this topic.

JuliaSprenger avatar May 31 '22 09:05 JuliaSprenger

-I moved the filter classes to a separate module.

-I also managed to decrease the filtering time. For comparison, I created one Segment that contains x Spiketrains and use a filter that applies to every Spiketrain. (Tested on multiple combinations of Segments, Blocks, Spiketrains, Analogsignals, the result is nearly the same).

Old filtering method: one_segment_only_spiketrains_success_average

New filtering method: one_segment_only_spiketrains_success_average_new

kloss-o avatar Jul 14 '22 10:07 kloss-o

Hey @apdavison and @JuliaSprenger , Thank you for the reviews and the valuable feedback you provided. I considered all your comments and made changes to the code.

If you have any further suggestions or if there are any remaining issues, please don't hesitate to let me or @mdenker know.

Moritz-Alexander-Kern avatar Aug 02 '23 12:08 Moritz-Alexander-Kern