Skip to content
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
33 changes: 33 additions & 0 deletions src/lerner_lab_to_nwb/seiler_2024/seiler_2024_convert_dataset.py
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@
split_western_blot,
)
from lerner_lab_to_nwb.seiler_2024.medpc_helpers import get_medpc_variables, read_medpc_file
from lerner_lab_to_nwb.seiler_2024.seiler_2024csvbehaviorinterface import Seiler2024CSVBehaviorInterface


def dataset_to_nwb(
Expand Down Expand Up @@ -252,6 +253,32 @@ def get_session_key_from_kwargs(session_to_nwb_kwargs: dict):
return session_key


def get_subject_session_start(session_to_nwb_kwargs: dict) -> tuple[str, str, str]:
"""Get the subject ID, start date, and start time of a session.

For CSV behavior files, the start date and time are read from the CSV itself.

Parameters
----------
session_to_nwb_kwargs : dict
The arguments for session_to_nwb.

Returns
-------
tuple[str, str, str]
The subject ID, start date (mm/dd/yy), and start time (HH:MM:SS) of the session.
"""
behavior_file_path = session_to_nwb_kwargs["behavior_file_path"]
if behavior_file_path.suffix in (".csv", ".CSV"):
behavior_metadata = Seiler2024CSVBehaviorInterface(file_path=str(behavior_file_path)).get_metadata()["Behavior"]
start_date = behavior_metadata["start_date"]
start_time = behavior_metadata["start_time"]
else:
start_date = session_to_nwb_kwargs["session_conditions"]["Start Date"]
start_time = session_to_nwb_kwargs["session_conditions"]["Start Time"]
return session_to_nwb_kwargs["subject_id"], start_date, start_time


def safe_session_to_nwb(*, session_to_nwb_kwargs: dict, exception_file_path: Union[Path, str]):
"""Convert a session to NWB while handling any errors by recording error messages to the exception_file_path.

Expand Down Expand Up @@ -731,6 +758,10 @@ def opto_to_nwb(
continue
unique_session_keys.add(session_key)
session_to_nwb_args_per_session.append(session_to_nwb_args)
subject_session_starts = {
get_subject_session_start(session_to_nwb_args) for session_to_nwb_args in session_to_nwb_args_per_session
}

# DLS Excitatory raw files by date
raw_files_by_date_path = data_dir_path / "Opto Experiments" / "DLS Excitatory"
start_dates, start_times, msns, file_paths, subjects, box_numbers = [], [], [], [], [], []
Expand Down Expand Up @@ -765,6 +796,8 @@ def opto_to_nwb(
}
if subject in partial_subject_ids_to_subject_id:
subject = partial_subject_ids_to_subject_id[subject]
if (subject, start_date, start_time) in subject_session_starts:
continue # already converted from the subject's own folder, which also gives the treatment
session_to_nwb_args = dict(
data_dir_path=data_dir_path,
output_dir_path=output_dir_path,
Expand Down
70 changes: 70 additions & 0 deletions tests/test_opto_session_deduplication.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
from pathlib import Path

import pytest

from lerner_lab_to_nwb.seiler_2024.seiler_2024_convert_dataset import opto_to_nwb

TREATMENT_FOLDERS = [
"DLS Excitatory/ChR2",
"DLS Excitatory/EYFP",
"DLS Excitatory/Scrambled",
"DMS Excitatory/ChR2",
"DMS Excitatory/EYFP",
"DMS Excitatory/Scrambled",
"DMS Inhibitory/Group 1/Halo",
"DMS Inhibitory/Group 1/EYFP",
"DMS Inhibitory/Group 1/Scrambled",
"DMS Inhibitory/Group 2/NpHr",
"DMS Inhibitory/Group 2/EYFP",
"DMS Inhibitory/Group 2/Scrambled",
]


def medpc_run(subject: str, box: str) -> str:
return (
"Start Date: 09/29/20\n"
"End Date: 09/29/20\n"
f"Subject: {subject}\n"
"Experiment: \n"
"Group: \n"
f"Box: {box}\n"
"Start Time: 11:36:53\n"
"End Time: 12:36:45\n"
"MSN: Footshock Degradation Left\n"
)


@pytest.fixture
def data_dir_path(tmp_path) -> Path:
opto_path = tmp_path / "Opto Experiments"
for treatment_folder in TREATMENT_FOLDERS:
(opto_path / treatment_folder).mkdir(parents=True)

# 300.405's run exported to its own folder as a CSV
subject_folder_path = opto_path / "DLS Excitatory" / "Scrambled" / "300_405"
subject_folder_path.mkdir()
(subject_folder_path / "300.405_09-29-20.csv").write_text(
",Start Date,End Date,Subject,Experiment,Group,Box,Start Time,End Time,MSN\n"
"0,09/29/20,09/29/20,300.405,,,5,11:36:53,12:36:45,Footshock Degradation Left\n"
)

# The same run and another mouse's run in the date-organized MED-PC file
(opto_path / "DLS Excitatory" / "2020-09-29").write_text(
"\n" + medpc_run(subject="418.404", box="1") + "\n" + medpc_run(subject="300.405", box="5")
)
return tmp_path


class TestOptoToNwb:
def test_by_date_run_already_in_subject_folder_is_skipped(self, data_dir_path, tmp_path):
session_to_nwb_args_per_session = opto_to_nwb(
data_dir_path=data_dir_path,
output_dir_path=tmp_path / "nwb",
start_variable="Start Date",
verbose=False,
)
subject_and_treatment = sorted(
(session_to_nwb_args["subject_id"], session_to_nwb_args["optogenetic_treatment"])
for session_to_nwb_args in session_to_nwb_args_per_session
)
assert subject_and_treatment == [("300.405", "ChR2Scrambled"), ("418.404", "Unknown")]