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

Opto #9

Merged
merged 14 commits into from
Oct 22, 2024
1 change: 1 addition & 0 deletions src/schneider_lab_to_nwb/schneider_2024/__init__.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
from .schneider_2024_behaviorinterface import Schneider2024BehaviorInterface
from .schneider_2024_optogeneticinterface import Schneider2024OptogeneticInterface
from .schneider_2024_intrinsic_signal_imaging_interface import Schneider2024IntrinsicSignalOpticalImagingInterface
from .schneider_2024_nwbconverter import Schneider2024NWBConverter
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,10 @@ def session_to_nwb(
source_data.update({metadata_key_name: dict(file_paths=[video_file_path], metadata_key_name=metadata_key_name)})
conversion_options.update({metadata_key_name: dict()})

# Add Optogenetic
source_data.update(dict(Optogenetic=dict(file_path=behavior_file_path)))
conversion_options.update(dict(Optogenetic=dict()))

# Add Intrinsic Signal Optical Imaging
source_data.update(dict(ISOI=dict(folder_path=intrinsic_signal_optical_imaging_folder_path)))
conversion_options.update(dict(ISOI=dict()))
Expand Down Expand Up @@ -118,7 +122,7 @@ def main():
sorting_folder_path = (
data_dir_path / "Schneider sample Data" / "Processed Ephys" / "m69_2023-10-31_17-24-15_Day1_A1"
)
behavior_file_path = data_dir_path / "NWB_Share" / "Sample behavior data" / "m74_ephysSample.mat"
behavior_file_path = data_dir_path / "NWB_Share" / "Sample behavior data" / "m74_optoSample.mat"
video_folder_path = data_dir_path / "Schneider sample Data" / "Video" / "m69_231031"
intrinsic_signal_optical_imaging_folder_path = data_dir_path / "NWB_Share" / "Sample Intrinsic imaging data"
session_to_nwb(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,22 @@ Behavior:
Sorting:
units_description: Neural spikes will be sorted offline using Kilosort 2.5 and Phy2 software and manually curated to ensure precise spike time acquisition.

Optogenetics:
Device:
name: optogenetic_stimulation_laser
pauladkisson marked this conversation as resolved.
Show resolved Hide resolved
description: Real time optogenetic stimulation of brain regions of interest will be accomplished via TTL control of an all solidstate 473nm blue laser (MBL-III-473/1~100mW, Opto Engine LLC). Bifurcated fiber cables (ThorLabs, Ø200 µm Core Multimode Fiber) will be used for light delivery.
manufacturer: Opto Engine LLC
OptogeneticStimulusSite:
name: optogenetic_stimulus_site
description: To identify cortical neurons that project from the auditory cortex to motor regions (Aim 2), stereotaxic injections of AAV-ChR2 will be made into the primary auditory cortex (-2.8 AP, 4.2 ML relative to bregma; guided by intrinsic optical imaging) during head-fixation and animals will be trained while expression occurs (~2 weeks). In addition, fiber optics will be implanted to target cell bodies in the secondary motor cortex (1.0-1.5 AP, 0.5-0.7 ML).
excitation_lambda: 473.0 # nm
injection_location: Primary Auditory Cortex (-2.8 AP, 4.2 ML relative to bregma; guided by intrinsic optical imaging)
stimulation_location: Secondary Motor Cortex (1.0-1.5 AP, 0.5-0.7 ML)
OptogeneticSeries:
name: optogenetic_series
pauladkisson marked this conversation as resolved.
Show resolved Hide resolved
description: In optogenetic perturbation trials (~33% of trials), during each lever press, continuous wave stimulation of 473nm light (15-20mW) will be delivered bilaterally over primary auditory cortex A1 (or secondary motor cortex, M2, as necessary using similar protocol - see Aim 2) to activate the terminals of ChR2 expressing neurons.
power: 0.020 # 15-20 mW

IntrinsicSignalOpticalImaging:
Module:
name: intrinsic_signal_optical_imaging
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,18 @@

## Video

## Optogenetics
- is_opto_trial in the trials table is `np.logical_not(np.isnan(onset_times))` rather than reading from the .mat file
to ensure consistency with the onset/offset times.

## Intrinsic Signal Optical Imaging
- Just including raw blood vessel image and processed overlay + pixel locations bc including the isoi roi response series would really require an extension for context, but seems like it has limited reuse potential.
- Used the Audette paper for description of overlay image.
- Need pixel locs for ephys
- Need device info for 2p microscope and red light laser
- Why is the overlaid image flipped left/right compared to the original?


## Data Requests
- Mice sexes
- Remaining data for Grant's project
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@

from schneider_lab_to_nwb.schneider_2024 import (
Schneider2024BehaviorInterface,
Schneider2024OptogeneticInterface,
Schneider2024IntrinsicSignalOpticalImagingInterface,
)

Expand All @@ -22,5 +23,6 @@ class Schneider2024NWBConverter(NWBConverter):
Behavior=Schneider2024BehaviorInterface,
VideoCamera1=VideoInterface,
VideoCamera2=VideoInterface,
Optogenetic=Schneider2024OptogeneticInterface,
ISOI=Schneider2024IntrinsicSignalOpticalImagingInterface,
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
"""Primary class for converting optogenetic stimulation."""
from pynwb.file import NWBFile
from pydantic import FilePath
import numpy as np
from pymatreader import read_mat
from pynwb.device import Device
from pynwb.ogen import OptogeneticSeries, OptogeneticStimulusSite

from neuroconv.basedatainterface import BaseDataInterface
from neuroconv.utils import DeepDict


class Schneider2024OptogeneticInterface(BaseDataInterface):
"""Optogenetic interface for schneider_2024 conversion"""

keywords = ["optogenetics"]

def __init__(self, file_path: FilePath):
super().__init__(file_path=file_path)

def get_metadata(self) -> DeepDict:
metadata = super().get_metadata()

return metadata

def get_metadata_schema(self) -> dict:
metadata_schema = super().get_metadata_schema()
return metadata_schema

def add_to_nwbfile(self, nwbfile: NWBFile, metadata: dict):
# Read Data
file_path = self.source_data["file_path"]
file = read_mat(file_path)
onset_times = file["events"]["push"]["opto_time"]
is_opto_trial = np.logical_not(np.isnan(onset_times))
onset_times = onset_times[is_opto_trial]
offset_times = file["events"]["push"]["opto_time_end"]
offset_times = offset_times[is_opto_trial]
assert np.all(
np.logical_not(np.isnan(offset_times))
), "Some of the offset times are nan when onset times are not nan."
power = metadata["Optogenetics"]["OptogeneticSeries"]["power"]

timestamps, data = [], []
for onset_time, offset_time in zip(onset_times, offset_times):
timestamps.append(onset_time)
data.append(power)
timestamps.append(offset_time)
data.append(0)
pauladkisson marked this conversation as resolved.
Show resolved Hide resolved
timestamps, data = np.array(timestamps, dtype=np.float64), np.array(data, dtype=np.float64)

# Add Data to NWBFile
# Add Device
device = Device(**metadata["Optogenetics"]["Device"])
nwbfile.add_device(device)

# Add OptogeneticStimulusSite
site_metadata = metadata["Optogenetics"]["OptogeneticStimulusSite"]
location = f"Injection location: {site_metadata['injection_location']} \n Stimulation location: {site_metadata['stimulation_location']}"
ogen_site = OptogeneticStimulusSite(
name=site_metadata["name"],
device=device,
description=site_metadata["description"],
excitation_lambda=site_metadata["excitation_lambda"],
location=location,
)
nwbfile.add_ogen_site(ogen_site)

# Add OptogeneticSeries
series_metadata = metadata["Optogenetics"]["OptogeneticSeries"]
optogenetic_series = OptogeneticSeries(
name=series_metadata["name"],
site=ogen_site,
description=series_metadata["description"],
data=data,
timestamps=timestamps,
)
nwbfile.add_stimulus(optogenetic_series)