Skip to content

Commit 288b69b

Browse files
authored
Merge pull request #3 from h-mayorquin/use_pathlib
Use pathlib for Intan PR and simplify data type for non header-attached formats
2 parents 9826634 + 02cfb91 commit 288b69b

File tree

1 file changed

+41
-72
lines changed

1 file changed

+41
-72
lines changed

neo/rawio/intanrawio.py

Lines changed: 41 additions & 72 deletions
Original file line numberDiff line numberDiff line change
@@ -125,62 +125,45 @@ def _parse_header(self):
125125
channel_number_dict,
126126
) = read_rhd(self.filename, self.file_format)
127127

128-
# memmap raw data with the complicated structured dtype
128+
# memmap the raw data for each format type
129129
# if header-attached there is one giant memory-map
130130
if self.file_format == "header-attached":
131131
self._raw_data = np.memmap(self.filename, dtype=data_dtype, mode="r", offset=header_size)
132-
else:
132+
133+
# for 'one-file-per-signal' we have one memory map / neo stream
134+
elif self.file_format == "one-file-per-signal":
133135
self._raw_data = {}
134136
for stream_index, (stream_index_key, stream_datatype) in enumerate(data_dtype.items()):
135-
# for 'one-file-per-signal' we have one memory map / neo stream
136-
if self.file_format == "one-file-per-signal":
137-
n_chans = channel_number_dict[stream_index_key]
138-
if stream_index_key == 4 or stream_index_key == 5:
139-
n_samples = int(os.path.getsize(raw_file_paths_dict[stream_index_key]) / 2) # uint16 2 bytes
140-
else:
141-
n_samples = int(
142-
os.path.getsize(raw_file_paths_dict[stream_index_key]) / (n_chans * 2)
143-
) # unit16 2 bytes
144-
if stream_index_key != 6:
145-
self._raw_data[stream_index] = np.memmap(
146-
raw_file_paths_dict[stream_index_key],
147-
dtype=stream_datatype,
148-
shape=(n_chans, n_samples),
149-
mode="r",
150-
).T
151-
else:
152-
self._raw_data[stream_index] = np.memmap(
153-
raw_file_paths_dict[stream_index_key], dtype=stream_datatype, mode="r"
154-
)
155-
# for one-file-per-channel we have one memory map / channel stored as a list / neo stream
156-
else:
157-
self._raw_data[stream_index] = []
158-
for channel_index, channel_datatype in enumerate(stream_datatype):
159-
if stream_index_key != 6:
160-
self._raw_data[stream_index].append(
161-
np.memmap(
162-
raw_file_paths_dict[stream_index_key][channel_index],
163-
dtype=channel_datatype,
164-
mode="r",
165-
)
166-
)
167-
else:
168-
self._raw_data[stream_index].append(
169-
np.memmap(
170-
raw_file_paths_dict[stream_index_key][channel_index],
171-
dtype=[channel_datatype],
172-
mode="r",
173-
)
174-
)
137+
num_channels = channel_number_dict[stream_index_key]
138+
file_path = raw_file_paths_dict[stream_index_key]
139+
size_in_bytes = file_path.stat().st_size
140+
dtype_size = np.dtype(stream_datatype).itemsize
141+
n_samples = size_in_bytes // (dtype_size * num_channels)
142+
signal_stream_memmap = np.memmap(file_path, dtype=stream_datatype, mode="r", shape=(num_channels, n_samples)).T
143+
self._raw_data[stream_index] = signal_stream_memmap
144+
145+
# for one-file-per-channel we have one memory map / channel stored as a list / neo stream
146+
elif self.file_format == "one-file-per-channel":
147+
self._raw_data = {}
148+
for stream_index, (stream_index_key, stream_datatype) in enumerate(data_dtype.items()):
149+
self._raw_data[stream_index] = []
150+
num_channels = channel_number_dict[stream_index_key]
151+
for channel_index in range(num_channels):
152+
file_path = raw_file_paths_dict[stream_index_key][channel_index]
153+
channel_memmap = np.memmap(file_path, dtype=stream_datatype, mode="r")
154+
self._raw_data[stream_index].append(channel_memmap)
155+
175156

176157
# check timestamp continuity
177158
if self.file_format == "header-attached":
178159
timestamp = self._raw_data["timestamp"].flatten()
179160
# timestamps are always the last stream
180161
elif self.file_format == "one-file-per-signal":
181-
timestamp = self._raw_data[max(self._raw_data.keys())]["timestamp"].flatten()
182-
else:
183-
timestamp = self._raw_data[max(self._raw_data.keys())][0]["timestamp"].flatten()
162+
time_stream_index = max(self._raw_data.keys())
163+
timestamp = self._raw_data[time_stream_index]
164+
elif self.file_format == "one-file-per-channel":
165+
time_stream_index = max(self._raw_data.keys())
166+
timestamp = self._raw_data[time_stream_index][0]
184167

185168
assert np.all(np.diff(timestamp) == 1), (
186169
"Timestamp have gaps, this could be due " "to a corrupted file or an inappropriate file merge"
@@ -346,6 +329,7 @@ def _get_analogsignal_chunk_header_attached(self, i_start, i_stop, stream_index,
346329

347330
return sigs_chunk
348331

332+
349333
def _get_analogsignal_chunk_one_file_per_channel(self, i_start, i_stop, stream_index, channel_indexes):
350334

351335
signal_data_memmap_list = self._raw_data[stream_index]
@@ -368,6 +352,7 @@ def _get_analogsignal_chunk_one_file_per_channel(self, i_start, i_stop, stream_i
368352

369353
return sigs_chunk
370354

355+
371356
def _get_analogsignal_chunk_one_file_per_signal(self, i_start, i_stop, stream_index, channel_indexes):
372357

373358
# One memmap per stream case
@@ -697,23 +682,13 @@ def read_rhd(filename, file_format: str):
697682
if file_format == "header-attached":
698683
data_dtype = [("timestamp", "int32", BLOCK_SIZE)]
699684
else:
700-
data_dtype[6] = [
701-
(
702-
"timestamp",
703-
"int32",
704-
)
705-
]
685+
data_dtype[6] = "int32"
706686
channel_number_dict[6] = 1
707687
else:
708688
if file_format == "header-attached":
709689
data_dtype = [("timestamp", "uint32", BLOCK_SIZE)]
710690
else:
711-
data_dtype[6] = [
712-
(
713-
"timestamp",
714-
"uint32",
715-
)
716-
]
691+
data_dtype[6] = "uint32"
717692
channel_number_dict[6] = 1
718693

719694
# 0: RHD2000 amplifier channel
@@ -727,12 +702,12 @@ def read_rhd(filename, file_format: str):
727702
else:
728703
chan_info["offset"] = 0.0
729704
ordered_channels.append(chan_info)
705+
730706
if file_format == "header-attached":
731707
data_dtype += [(name, "uint16", BLOCK_SIZE)]
732-
elif file_format == "one-file-per-signal":
733-
data_dtype[0] = "int16"
734708
else:
735-
data_dtype[0] += ["int16"]
709+
data_dtype[0] = "int16"
710+
736711

737712
# 1: RHD2000 auxiliary input channel
738713
for chan_info in channels_by_type[1]:
@@ -744,10 +719,9 @@ def read_rhd(filename, file_format: str):
744719
ordered_channels.append(chan_info)
745720
if file_format == "header-attached":
746721
data_dtype += [(name, "uint16", BLOCK_SIZE // 4)]
747-
elif file_format == "one-file-per-signal":
748-
data_dtype[1] = "uint16"
749722
else:
750-
data_dtype[1] += ["uint16"]
723+
data_dtype[1] = "uint16"
724+
751725

752726
# 2: RHD2000 supply voltage channel
753727
for chan_info in channels_by_type[2]:
@@ -759,10 +733,8 @@ def read_rhd(filename, file_format: str):
759733
ordered_channels.append(chan_info)
760734
if file_format == "header-attached":
761735
data_dtype += [(name, "uint16")]
762-
elif file_format == "one-file-per-signal":
736+
else:
763737
data_dtype[2] = "uint16"
764-
else:
765-
data_dtype[2] += ["uint16"]
766738

767739
# temperature is not an official channel in the header
768740
for i in range(global_info["num_temp_sensor_channels"]):
@@ -792,10 +764,8 @@ def read_rhd(filename, file_format: str):
792764
ordered_channels.append(chan_info)
793765
if file_format == "header-attached":
794766
data_dtype += [(name, "uint16", BLOCK_SIZE)]
795-
elif file_format == "one-file-per-signal":
796-
data_dtype[3] = "uint16"
797767
else:
798-
data_dtype[3] += ["uint16"]
768+
data_dtype[3] = "uint16"
799769

800770
# 4: USB board digital input channel
801771
# 5: USB board digital output channel
@@ -817,10 +787,9 @@ def read_rhd(filename, file_format: str):
817787
ordered_channels.append(chan_info)
818788
if file_format == "header-attached":
819789
data_dtype += [(name, "uint16", BLOCK_SIZE)]
820-
elif file_format == "one-file-per-signal":
821-
data_dtype[sig_type] = "uint16"
822790
else:
823-
data_dtype[sig_type] += ["uint16"]
791+
data_dtype[sig_type] = "uint16"
792+
824793

825794
if global_info["notch_filter_mode"] == 2 and version >= V("3.0"):
826795
global_info["notch_filter"] = "60Hz"

0 commit comments

Comments
 (0)