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

[Neuropixels] Add temporal alignment #21

Merged
merged 3 commits into from
Nov 19, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -129,6 +129,29 @@ column_descriptions = dict(
)
```

### Temporal alignment

Align TTL signals to Raw Bpod trial times:
Compute the time shift from raw Bpod trial start times to the aligned center port timestamps.
The aligned center port times can be accessed from the processed behavior data using the `"Cled"` field.

```python
from ndx_structured_behavior.utils import loadmat

bpod_data = loadmat("path/to/bpod_session.mat")["SessionData"] # should contain "SessionData" named struct
S_struct_data = loadmat("path/to/processed_behavior.mat")["S"] # should contain "S" named struct

# The trial start times from the Bpod data
bpod_trial_start_times = bpod_data['TrialStartTimestamp']

# "Cled" field contains the aligned onset and offset times for each trial [2 x ntrials]
center_port_aligned_onset_times = [center_port_times[0] for center_port_times in S_struct_data["Cled"]]
time_shift = bpod_trial_start_times[0] - center_port_aligned_onset_times[0]
```

We are using this computed time shift to shift the ephys timestamps.


### Mapping to NWB

The following UML diagram shows the mapping of source data to NWB.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -141,3 +141,31 @@ def get_metadata(self):
)

return metadata

def temporally_align_data_interfaces(self):
processed_behavior_interface = self.data_interface_objects["ProcessedBehavior"]
center_port_aligned_times = processed_behavior_interface._get_aligned_center_port_times()

raw_behavior_interface = self.data_interface_objects["RawBehavior"]
trial_start_times_from_bpod, _ = raw_behavior_interface.get_trial_times()
bpod_first_trial_start_time = trial_start_times_from_bpod[0]
time_shift = bpod_first_trial_start_time - center_port_aligned_times[0]

recording_interface_names = [
interface_name for interface_name in self.data_interface_objects if "Recording" in interface_name
]

for recording_interface_name in recording_interface_names:
recording_interface = self.data_interface_objects[recording_interface_name]
unaligned_timestamps = recording_interface.get_timestamps()
unaligned_starting_time = unaligned_timestamps[0]
if unaligned_starting_time + time_shift < 0:
raise ValueError("The recording aligned starting time should not be negative.")
recording_interface.set_aligned_starting_time(aligned_starting_time=time_shift)

sorting_interface_names = [
interface_name for interface_name in self.data_interface_objects if "Sorting" in interface_name
]
for sorting_interface_name in sorting_interface_names:
sorting_interface = self.data_interface_objects[sorting_interface_name]
sorting_interface.register_recording(self.data_interface_objects[recording_interface_names[0]])