Skip to content

Commit 6a4f6ed

Browse files
committed
behavior_only option
1 parent 6dcbc97 commit 6a4f6ed

File tree

6 files changed

+78
-29
lines changed

6 files changed

+78
-29
lines changed

src/trodes_to_nwb/convert.py

Lines changed: 29 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -112,6 +112,7 @@ def create_nwbs(
112112
n_workers: int = 1,
113113
query_expression: str | None = None,
114114
disable_ptp: bool = False,
115+
behavior_only: bool = False,
115116
):
116117
"""
117118
Convert SpikeGadgets data to NWB format.
@@ -166,6 +167,7 @@ def pass_func(args):
166167
output_dir,
167168
video_directory,
168169
convert_video,
170+
behavior_only=behavior_only,
169171
)
170172
return True
171173
except Exception as e:
@@ -194,6 +196,7 @@ def pass_func(args):
194196
video_directory,
195197
convert_video,
196198
disable_ptp,
199+
behavior_only=behavior_only,
197200
)
198201

199202

@@ -206,6 +209,7 @@ def _create_nwb(
206209
video_directory: str = "",
207210
convert_video: bool = False,
208211
disable_ptp: bool = False,
212+
behavior_only: bool = False,
209213
):
210214
# create loggers
211215
logger = setup_logger("convert", f"{session[1]}{session[0]}_convert.log")
@@ -217,7 +221,10 @@ def _create_nwb(
217221
logger.info("CREATING REC DATA ITERATORS")
218222
# make generic rec file data chunk iterator to pass to functions
219223
rec_dci = RecFileDataChunkIterator(
220-
rec_filepaths, interpolate_dropped_packets=False, stream_id="trodes"
224+
rec_filepaths,
225+
interpolate_dropped_packets=False,
226+
stream_id="ECU_analog" if behavior_only else "trodes",
227+
behavior_only=behavior_only,
221228
)
222229
rec_dci_timestamps = (
223230
rec_dci.timestamps
@@ -263,30 +270,36 @@ def _create_nwb(
263270
add_acquisition_devices(nwb_file, metadata)
264271
add_tasks(nwb_file, metadata)
265272
add_associated_files(nwb_file, metadata)
266-
add_electrode_groups(
267-
nwb_file, metadata, device_metadata, hw_channel_map, ref_electrode_map
268-
)
269273
add_header_device(nwb_file, rec_header)
270274
add_associated_video_files(
271275
nwb_file, metadata, session_df, video_directory, convert_video
272276
)
273277
add_optogenetics(nwb_file, metadata, device_metadata)
274278

275-
logger.info("ADDING EPHYS DATA")
276-
# add rec file data
277-
map_row_ephys_data_to_row_electrodes_table = list(
278-
range(len(nwb_file.electrodes))
279-
) # TODO: Double check this
280-
add_raw_ephys(
281-
nwb_file,
282-
rec_filepaths,
283-
map_row_ephys_data_to_row_electrodes_table,
284-
metadata,
285-
)
279+
if not behavior_only:
280+
add_electrode_groups(
281+
nwb_file, metadata, device_metadata, hw_channel_map, ref_electrode_map
282+
)
283+
logger.info("ADDING EPHYS DATA")
284+
# add rec file data
285+
map_row_ephys_data_to_row_electrodes_table = list(
286+
range(len(nwb_file.electrodes))
287+
) # TODO: Double check this
288+
add_raw_ephys(
289+
nwb_file,
290+
rec_filepaths,
291+
map_row_ephys_data_to_row_electrodes_table,
292+
metadata,
293+
)
286294
logger.info("ADDING DIO DATA")
287295
add_dios(nwb_file, rec_filepaths, metadata)
288296
logger.info("ADDING ANALOG DATA")
289-
add_analog_data(nwb_file, rec_filepaths, timestamps=rec_dci_timestamps)
297+
add_analog_data(
298+
nwb_file,
299+
rec_filepaths,
300+
timestamps=rec_dci_timestamps,
301+
behavior_only=behavior_only,
302+
)
290303
logger.info("ADDING SAMPLE COUNTS")
291304
add_sample_count(nwb_file, rec_dci)
292305
logger.info("ADDING EPOCHS")

src/trodes_to_nwb/convert_analog.py

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,11 @@
1515

1616

1717
def add_analog_data(
18-
nwbfile: NWBFile, rec_file_path: list[str], timestamps: np.ndarray = None, **kwargs
18+
nwbfile: NWBFile,
19+
rec_file_path: list[str],
20+
timestamps: np.ndarray = None,
21+
behavior_only: bool = False,
22+
**kwargs,
1923
) -> None:
2024
"""Adds analog streams to the nwb file.
2125
@@ -46,9 +50,10 @@ def add_analog_data(
4650
rec_dci = RecFileDataChunkIterator(
4751
rec_file_path,
4852
nwb_hw_channel_order=analog_channel_ids,
49-
stream_index=2,
53+
stream_id="ECU_analog",
5054
is_analog=True,
5155
timestamps=timestamps,
56+
behavior_only=behavior_only,
5257
)
5358

5459
# add headstage channel IDs to the list of analog channel IDs

src/trodes_to_nwb/convert_ephys.py

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@ def __init__(
4747
is_analog: bool = False,
4848
interpolate_dropped_packets: bool = False,
4949
timestamps=None, # Use this if you already have timestamps from intializing another rec iterator on the same files
50+
behavior_only: bool = False,
5051
**kwargs,
5152
):
5253
"""
@@ -69,6 +70,8 @@ def __init__(
6970
whether to interpolate single dropped packets, by default False
7071
timestamps : [type], optional
7172
timestamps to use. Can provide efficiency improvements by skipping recalculating timestamps from rec files, by default None
73+
behavior_only : bool, optional
74+
indicate if file contains only behavior data (no e-phys), by default False
7275
kwargs : dict
7376
additional arguments to pass to GenericDataChunkIterator
7477
"""
@@ -94,7 +97,12 @@ def __init__(
9497
# trodes
9598
assert all([neo_io.block_count() == 1 for neo_io in self.neo_io])
9699
assert all([neo_io.segment_count(0) == 1 for neo_io in self.neo_io])
97-
assert all([neo_io.signal_streams_count() == 4 for neo_io in self.neo_io])
100+
assert all(
101+
[
102+
neo_io.signal_streams_count() == 4 - behavior_only
103+
for neo_io in self.neo_io
104+
]
105+
)
98106

99107
self.block_index = 0
100108
self.seg_index = 0
@@ -113,6 +121,10 @@ def __init__(
113121
else: # if stream id is not provided
114122
stream_id = self.neo_io[0].get_stream_id_from_index(stream_index)
115123

124+
if behavior_only and stream_id == "trodes":
125+
raise ValueError(
126+
"Behavior only recordings do not contain a `trodes` stream"
127+
)
116128
self.stream_id = stream_id
117129
self.stream_index = stream_index
118130

src/trodes_to_nwb/convert_optogenetics.py

Lines changed: 22 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -32,16 +32,29 @@ def add_optogenetics(nwbfile: NWBFile, metadata: dict, device_metadata: List[dic
3232
List of dictionaries containing metadata for devices used in the experiment.
3333
"""
3434
logger = logging.getLogger("convert")
35-
if not all(
36-
[
37-
x in metadata
38-
for x in [
39-
"virus_injection",
40-
"opto_excitation_source",
41-
"optical_fiber",
42-
"optogenetic_stimulation_software",
35+
if not (
36+
all(
37+
[
38+
x in metadata
39+
for x in [
40+
"virus_injection",
41+
"opto_excitation_source",
42+
"optical_fiber",
43+
"optogenetic_stimulation_software",
44+
]
4345
]
44-
]
46+
)
47+
and all(
48+
[
49+
len(metadata[x]) > 0
50+
for x in [
51+
"virus_injection",
52+
"opto_excitation_source",
53+
"optical_fiber",
54+
"optogenetic_stimulation_software",
55+
]
56+
]
57+
)
4558
):
4659
logger.info("No available optogenetic metadata")
4760
return

src/trodes_to_nwb/convert_position.py

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1250,7 +1250,12 @@ def add_associated_video_files(
12501250
epoch = video_metadata["task_epochs"][0]
12511251
# get the video file path
12521252
video_path = None
1253-
for file in session_df[session_df.file_extension == ".h264"].full_path:
1253+
for file in session_df[
1254+
np.logical_or(
1255+
session_df.file_extension == ".h264",
1256+
session_df.file_extension == ".mp4",
1257+
)
1258+
].full_path:
12541259
if video_metadata["name"].rsplit(".", 1)[0] in file:
12551260
video_path = file
12561261
break

src/trodes_to_nwb/data_scanner.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
"rec", # binary file containing the ephys recording, accelerometer, gyroscope, magnetometer, DIO data, header
1313
"videoPositionTracking", # trodes tracked position
1414
"h264", # video file
15+
"mp4", # video file
1516
"cameraHWSync", # position timestamps
1617
"stateScriptLog", # state script controls the experimenter parameters
1718
"yml", # metadata file

0 commit comments

Comments
 (0)