|
8 | 8 |
|
9 | 9 | RHS supported version 1.0 |
10 | 10 | RHD supported version 1.0 1.1 1.2 1.3 2.0 3.0, 3.1 |
11 | | -RHD headerless binary support 3.1 |
| 11 | +RHD headerless binary support 3.x |
| 12 | +RHS headerless binary support 3.x |
12 | 13 |
|
13 | 14 | See: |
14 | 15 | * http://intantech.com/files/Intan_RHD2000_data_file_formats.pdf |
@@ -44,27 +45,43 @@ class IntanRawIO(BaseRawIO): |
44 | 45 | Parameters |
45 | 46 | ---------- |
46 | 47 | filename: str, default: '' |
47 | | - name of the 'rhd' or 'rhs' data file |
| 48 | + name of the 'rhd' or 'rhs' data/header file |
48 | 49 |
|
49 | 50 | Notes |
50 | 51 | ----- |
51 | | - * Intan reader can handle two file formats 'rhd' and 'rhs'. It will automatically |
| 52 | + * The Intan reader can handle two file formats 'rhd' and 'rhs'. It will automatically |
52 | 53 | check for the file extension and will gather the header information based on the |
53 | | - extension. Additionally it functions with RHS v 1.0 and RHD 1.0, 1.1, 1.2, 1.3, 2.0, |
54 | | - 3.0, and 3.1 files. |
| 54 | + extension. Additionally it functions with RHS v 1.0 and v 3.x and RHD 1.0, 1.1, 1.2, 1.3, 2.0, |
| 55 | + 3.x files. |
| 56 | +
|
| 57 | + * The Intan reader can also handle the headerless binary formats 'one-file-per-signal' and |
| 58 | + 'one-file-per-channel' which have a header file called 'info.rhd' or 'info.rhs' and a series |
| 59 | + of binary files with the '.dat' suffix |
55 | 60 |
|
56 | 61 | * Intan files contain amplifier channels labeled 'A', 'B' 'C' or 'D' |
57 | 62 | depending on the port in which they were recorded along with the following |
58 | | - additional channels. |
59 | | - 0: 'RHD2000' amplifier channel |
| 63 | + additional channels for RHD: |
| 64 | +
|
| 65 | + 0: 'RHD2000 amplifier channel' |
60 | 66 | 1: 'RHD2000 auxiliary input channel', |
61 | 67 | 2: 'RHD2000 supply voltage channel', |
62 | 68 | 3: 'USB board ADC input channel', |
63 | 69 | 4: 'USB board digital input channel', |
64 | 70 | 5: 'USB board digital output channel' |
65 | 71 |
|
| 72 | + And for RHS: |
| 73 | +
|
| 74 | + 0: 'RHS2000 amplfier channel' |
| 75 | + 3: 'USB board ADC input channel', |
| 76 | + 4: 'USB board ADC output channel', |
| 77 | + 5: 'USB board digital input channel', |
| 78 | + 6: 'USB board digital output channel', |
| 79 | + 10: 'DC Amplifier channel', |
| 80 | + 11: 'Stim channel', |
| 81 | +
|
66 | 82 | * Due to the structure of the digital input and output channels these can be accessed |
67 | | - as one long vector, which must be post-processed. |
| 83 | + as one long vector, which must be post-processed in the case of 'header-attached' or |
| 84 | + 'one-file-per-stream' formats. |
68 | 85 |
|
69 | 86 | Examples |
70 | 87 | -------- |
@@ -96,6 +113,7 @@ def _parse_header(self): |
96 | 113 | if not filename.exists() or not filename.is_file(): |
97 | 114 | raise FileNotFoundError(f"{filename} does not exist") |
98 | 115 |
|
| 116 | + # see comment below for RHD which explains the division between file types |
99 | 117 | if self.filename.endswith(".rhs"): |
100 | 118 | if filename.name == "info.rhs": |
101 | 119 | if any((filename.parent / file).exists() for file in one_file_per_signal_filenames_rhs): |
@@ -236,6 +254,7 @@ def _parse_header(self): |
236 | 254 | # are in a list we just take the first channel in each list of channels |
237 | 255 | else: |
238 | 256 | self._max_sigs_length = max([raw_data[0].size for raw_data in self._raw_data.values()]) |
| 257 | + |
239 | 258 | # No events |
240 | 259 | event_channels = [] |
241 | 260 | event_channels = np.array(event_channels, dtype=_event_channel_dtype) |
@@ -263,13 +282,19 @@ def _parse_header(self): |
263 | 282 | signal_annotation["intan_version"] = ( |
264 | 283 | f"{self._global_info['major_version']}." f"{self._global_info['minor_version']}" |
265 | 284 | ) |
266 | | - global_keys_to_skip = ["major_version", "minor_version", "sampling_rate", "magic_number", "reference_channel"] |
| 285 | + global_keys_to_skip = [ |
| 286 | + "major_version", |
| 287 | + "minor_version", |
| 288 | + "sampling_rate", |
| 289 | + "magic_number", |
| 290 | + "reference_channel", |
| 291 | + ] |
267 | 292 | global_keys_to_annotate = set(self._global_info.keys()) - set(global_keys_to_skip) |
268 | 293 | for key in global_keys_to_annotate: |
269 | 294 | signal_annotation[key] = self._global_info[key] |
270 | 295 |
|
271 | 296 | reference_channel = self._global_info.get("reference_channel", None) |
272 | | - # Following the pdf specification |
| 297 | + # Following the pdf specification |
273 | 298 | reference_channel = "hardware" if reference_channel == "n/a" else reference_channel |
274 | 299 |
|
275 | 300 | # Add channel annotations |
@@ -664,6 +689,10 @@ def read_rhs(filename, file_format: str): |
664 | 689 | else: |
665 | 690 | data_dtype[sig_type] = "uint16" |
666 | 691 |
|
| 692 | + # per discussion with Intan developers before version 3 of their software the 'notch_filter_mode' |
| 693 | + # was a request for postprocessing to be done in one of their scripts. From version 3+ the notch |
| 694 | + # filter is now applied to the data in realtime and only the post notched amplifier data is |
| 695 | + # saved. |
667 | 696 | if global_info["notch_filter_mode"] == 2 and global_info["major_version"] >= Version("3.0"): |
668 | 697 | global_info["notch_filter"] = "60Hz" |
669 | 698 | elif global_info["notch_filter_mode"] == 1 and global_info["major_version"] >= Version("3.0"): |
@@ -939,6 +968,10 @@ def read_rhd(filename, file_format: str): |
939 | 968 | else: |
940 | 969 | data_dtype[sig_type] = "uint16" |
941 | 970 |
|
| 971 | + # per discussion with Intan developers before version 3 of their software the 'notch_filter_mode' |
| 972 | + # was a request for postprocessing to be done in one of their scripts. From version 3+ the notch |
| 973 | + # filter is now applied to the data in realtime and only the post notched amplifier data is |
| 974 | + # saved. |
942 | 975 | if global_info["notch_filter_mode"] == 2 and version >= Version("3.0"): |
943 | 976 | global_info["notch_filter"] = "60Hz" |
944 | 977 | elif global_info["notch_filter_mode"] == 1 and version >= Version("3.0"): |
|
0 commit comments