Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Refactor, test and optimize compute_synchrony_metrics #2528

Closed

Conversation

chrishalcrow
Copy link
Collaborator

Planning to standardise, correctness test and optimise the quality metrics module. First one: the compute_synchrony_metrics function.

I'm pretty new to this, so all feedback will be listened to and much appreciated! I think @samuelgarcia agreed to give me some detailed feedback in the future, so I'll put this on draft until then.

Two main things in this:

  • The generating function synthesize_random_firings and synthesize_poisson_spike_vectors were adjusted so that you can insert specific spikes, useful for testing. These are used in the new tests.
  • A new function compute_synchrony_counts is introduced, which computes the synchrony counts.

Some things I'm not sure about:

  1. The documentation said that compute_synchrony_metrics returns a dict, but it previously outputted a named tuple. We can either change the documentation or the output. I changed the output, as most quality metrics functions return a dict.
  2. I flattened any multi-segment spike trains into a single array, which avoids a for loop down the line. Is there a reason not to do this?
  3. The algorithm assumes the spike train is sorted in time. Can this be assumed?

I adjusted the algorithm in compute_synchrony_counts, which should be easier to understand and is significantly faster. I benchmarked using the following code:

import numpy as np
from time import perf_counter

from spikeinterface.core import synthesize_random_firings
from spikeinterface.qualitymetrics import get_synchrony_counts

unit_ids = np.arange(100)

Ns = 10**np.array(np.arange(3,5.1,0.1))

times_by_size=[]
how_many = 100

for train_length in Ns:

    times_list = []

    for _ in range(0,how_many):

        spike_train = synthesize_random_firings(num_units=100, duration=train_length/1000, firing_rates=10.0)

        start = perf_counter()
        get_synchrony_counts(spike_train, np.array((2,4,8)), list(unit_ids))        
        end = perf_counter()

        times_list.append(end - start)

    times_by_size.append( np.median( times_list ) )

The results are below. I tabulated (half of) the actual times, and create a log-log plot to check the algorithm's complexity.

benchmarch_sync

@alejoe91 alejoe91 added qualitymetrics Related to qualitymetrics module refactor Refactor of code, with no change to functionality labels Mar 1, 2024
pre-commit-ci bot and others added 25 commits March 20, 2024 10:05
Co-authored-by: Zach McKenzie <92116279+zm711@users.noreply.github.com>
Co-authored-by: Zach McKenzie <92116279+zm711@users.noreply.github.com>
@chrishalcrow chrishalcrow changed the base branch from dev to main March 20, 2024 10:16
@alejoe91
Copy link
Member

@chrishalcrow not sure what happened here with the conflicts..maybe easier to make a new PR directly to main with the changes to the metrics?

@chrishalcrow
Copy link
Collaborator Author

@chrishalcrow not sure what happened here with the conflicts..maybe easier to make a new PR directly to main with the changes to the metrics?

Yes, I tried to merge with the main after the SortingAnalyzer change and have somehow created this mess. Will start again...

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
qualitymetrics Related to qualitymetrics module refactor Refactor of code, with no change to functionality
Projects
None yet
Development

Successfully merging this pull request may close these issues.

8 participants