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

How to get sync timestamps from spikeglx and open ephys #3425

Open
gabrielstine opened this issue Sep 18, 2024 · 12 comments
Open

How to get sync timestamps from spikeglx and open ephys #3425

gabrielstine opened this issue Sep 18, 2024 · 12 comments
Labels
question General question regarding SI

Comments

@gabrielstine
Copy link

gabrielstine commented Sep 18, 2024

Hi Guys,

I have a simple question that I'm having trouble finding the answer to in the documentation. I am recording simultaneously from a neuropixels probe (recorded in spikeGLX) and a DBC probe (recorded in open ephys). I'd like to extract the timestamps of the sync events from each stream and save them as .npy files. In open ephys, the sync signal is a ttl pulse fed into digital input 1. I imagine there are straightforward functions for extracting and saving these, but I can't find them!

Thanks!
Gabe

@zm711
Copy link
Collaborator

zm711 commented Sep 18, 2024

I feel like @alejoe91 is going to need to be the person to comment on this. I don't actually use ephys or any of the event based code in spikeinterface. So just ping this issue if you don't get a response soon!

@zm711 zm711 added the question General question regarding SI label Sep 18, 2024
@alejoe91
Copy link
Member

Hi @gabrielstine !

You should be able to read the open ephys events with this function:

events = se.read_openephys_events(openephys_folder)

This will return an Event object, which will allow you to interact with the event data. There can be events from multiple channel ids, which you can retrieve with the events.channel_ids field.
In particular, calling evts = events.get_events(channel_id) will return a structured numpy array with the following field:
dtype([('time', '<f8'), ('duration', '<f8'), ('label', '<U100')]). For open ephys, the label is the channel the event was recorded on, so you can select all events from channel 1 as follows:

evts_1 = evts[evts["label"] == "1"]

Let me know if you have other questions!

@gabrielstine
Copy link
Author

Thanks @alejoe91. And is there a way to automatically get the timestamps at which the sync channel went high in the spikeGLX data, or do I need to extract this manually? If not, could be nice to have a built-in function that takes the channel as input and returns timestamps.

@alejoe91
Copy link
Member

You can try the event_spikeglx = se.read_spikeglx_events(spikeglx_folder) ;)

@chongtianyifa
Copy link

@alejoe91 It seems that se does not have read_spikeglx_event module.
image

@alejoe91
Copy link
Member

Did you try this?

import spikeinterface.extractors as se

event = se.read_spikeglx_event(path-to-sglx-folder)

It's a function and not a module. Can you paste the error you're getting?

@chongtianyifa
Copy link

with se.read_spikeglx_event(path-to-sglx-folder), no error came out. However, no events were detected. My event signals were actually synchronization signal with 1s on and 29 s off.
image

@alejoe91
Copy link
Member

Maybe then you used the SYNC channel (i.e. the 385th signal)?

@chongtianyifa
Copy link

Yes, the event was recorded in the SYNC channel. Is there a way to extract events from this channel?

@gabrielstine
Copy link
Author

@alejoe91 I'm still struggling with this, and not seeing anything in the docs. Feels like it should be very easy/simple given how ubiquitous this step is in neuropixels pipelines. To reiterate/clarify, channel 385 receives TTL pulses that are used to synchronize my spikeGLX data to other data streams. I need to extract this signal and find the timepoints at which it went "high." Previously I was using catGT for preprocessing, which does this automatically. Does something like the below exist?

rec_imec0 = read_spikeglx(spkGLX_folder, stream_name='imec0.ap')
sync_times_imec0 = get_sync_times_spikeglx(rec_imec0)

If not, could you walk me through how I would, at the very least, extract the signal on channel 385? I believe this is what @chongtianyifa is asking for as well.

@alejoe91
Copy link
Member

I see, sorry I misunderstood. @samuelgarcia was planning to work on such automated sync function for spikeGLX, so let's ping him!

You can extract the sync channel recording as follows:

recording_ap_with_sync = se.read_spikeglx(spkGLX_folder, stream_name='imec0.ap', load_sync_channel=True)
# only select the last SYNC channel
recording_sync = recording_ap_with_sync.select_channels([recording_ap_with_sync.channel_ids[-1]])

Then you can get the sync channel traces and look for rising edges:

traces_sync = recording_sync.get_traces()[:, 0] # the slicing is to get a 1d array

rising_edges = np.where(np.diff(traces_sync) > 0)[0]

@gabrielstine
Copy link
Author

Thanks Alessio! Appreciate all of the work you guys do.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
question General question regarding SI
Projects
None yet
Development

No branches or pull requests

4 participants