cortex-lab / KiloSort

GPU code for spike sorting
GNU General Public License v2.0
176 stars 100 forks source link

Sampling rate and template alignment #177

Open dimokaramanlis opened 5 years ago

dimokaramanlis commented 5 years ago

Hello,

thank you for your great tool.

We mainly use a sampling rate of 10k in our recordings. In my understanding, Kilosort was developed initially for 25k recordings. To accommodate for the different rate, we set:

Kilosort seems to work fine, except for one thing. When loading Kilosort results in phy, the templates seem to be shifted relative to the spike waveforms by one time sample:

template_allignment_zoom

Why do you think we are getting this shift?

In my understanding, the parameter responsible for that is nt0min (defined in fitTemplates.m). While nt0min is corrected for the length of the temporal window (ceil(20 * nt0/61)), there is a difference of one time sample for 25k recordings (nt0 at 20 vs spike trough at 21). For 10k recordings, both numbers end up at the 8th time sample.

Best, Dimos

marius10p commented 5 years ago

Hi Dimos, looks like your nt0 ends up even (24). Can you please try 25 and let us know if you get the same problem? - Marius

dimokaramanlis commented 5 years ago

Hi Marius,

I tried running Kilosort with odd nt0=25, with nt0min=9. Now it appears that the templates are shifted two samples relative to the spikes:

template_shift2

Another thing I've noticed is that at the TraceView, one can see the actual waveform below the template (instead of the residual?), and both data and template are properly aligned:

traceview

dimokaramanlis commented 5 years ago

If I subtract 1 or 2 from the spike times (for nt0 = 24 or 25, respectively), before saving them in phy's format, the spike traces and the templates end up properly aligned in phy.

The batch buffer is another parameter that might be relevant and I have changed to match our10k recordings (ops.ntbuff=26).

marius10p commented 5 years ago

Hmm, maybe it is the batch buffer. That doesn't need to be changed, since it's just the overlap between consecutive batches that we need to resolve those boundary spikes. Can you please try without changing it? Did you also change ops.NT by any chance? That also shouldn't be necessary.

dimokaramanlis commented 5 years ago

Sure, I will try again with the original buffer.

For NT, I use ops.NT = 32*512+ops.ntbuff, since my GPU goes out of memory for larger batch sizes. GPU has only 2GB, recordings come from 252 electrodes, and I ask for 960 templates.

marius10p commented 5 years ago

Ok about ops.NT, that should be fine.

dimokaramanlis commented 5 years ago

Hi Marius,

returning ntbuff to 64 didn't affect the shifts. I still get shifts of 1 or 2 two time samples, depending on the value of nt0 (24 or 25).

My only worry is that there may be a misalignment during the matching pursuit pass, ultimately affecting spike detection.

dimokaramanlis commented 5 years ago

I managed to solve the problem, I think it was related to template initialization 'fromData'. Now the spike waveforms are aligned to the templates and the residual appears properly in TraceView:

solved_problem

Before, I was using the default principal components (PCs), calculated for spike waveforms of 61 samples, centered at sample 20. The algorithm tried to downsample the PCs to match my nt0 values, but this might have messed up with the actual trough alignment.

I set nt0=25, centered some of my spikes at 8 and calculated PCs from those waveforms. Then, I used the following values to run Kilosort:

I'm not entirely sure where to pinpoint the problem, but at least Kilosort works even better now. Proper alignment and PCs from my data actually led to better templates and higher spike amplitudes.

Thanks again for the help.

Best, Dimos

brendonw1 commented 5 years ago

I'm another user on this forum and I generally like and use KiloSort. Thanks for bringing up this issue.

This sounds important. Is it something likely to be affecting all of us? Is there a way to instantiate a systemic change in Kilosort?

On Fri, Feb 1, 2019 at 5:38 AM Dimokratis Karamanlis < notifications@github.com> wrote:

I managed to solve the problem, I think it was related to template initialization 'fromData'. Now the spike waveforms are aligned to the templates and the residual appears properly in TraceView:

[image: solved_problem] https://user-images.githubusercontent.com/1114242/52116553-b5ecb800-2611-11e9-8410-7fc6f1c2f5a7.png

Before, I was using the default principal components (PCs), calculated for spike waveforms of 61 samples, centered at sample 20. The algorithm tried to downsample the PCs to match my nt0 values, but this might have messed up with the actual trough alignment.

I set nt0=25, centered some of my spikes at 8 and calculated PCs from those waveforms. Then, I used the following values to run Kilosort:

  • dt =-9+ [1:size(wPCA,1)] in get_PCproj.m.
  • nt0min=8

I'm not entirely sure where to pinpoint the problem, but at least Kilosort works even better now. Proper alignment and PCs from my data actually led to better templates and higher spike amplitudes.

Thanks again for the help.

Best, Dimos

— You are receiving this because you are subscribed to this thread. Reply to this email directly, view it on GitHub https://github.com/cortex-lab/KiloSort/issues/177#issuecomment-459680308, or mute the thread https://github.com/notifications/unsubscribe-auth/ADXrTdkLWfQnnYU1vZvB-3JUnaezc0Rxks5vJBkogaJpZM4aV7uC .

marius10p commented 5 years ago

@dimos glad to hear it works now. The PCs are only used for initialization, and they are quickly forgotten during the template optimization. They are also used for visualization in Phy, but they play no role in the actual spike extraction and assignment.