1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
/*!
# Intan Importer
A Rust library for importing and processing Intan Technologies RHS data files. This crate provides
strongly-typed interfaces to Intan's neural recording file formats, used in electrophysiology research.
## Overview
Intan Technologies manufactures hardware for neural recording, including systems that record electrical signals
from the brain and nervous system. These systems generate data files in proprietary formats (RHS/RHD).
This library provides tools to read and process these files, making the data accessible for analysis.
## Main Features
- **Single File or Directory Loading**: Load individual RHS files or automatically combine multiple files from a directory
- **Comprehensive Parsing**: Read and parse Intan RHS files with full support for all sections
- **Strong Typing**: All data structures are strongly typed with appropriate Rust types
- **Automatic Processing**:
- Signal scaling to meaningful units (μV, V)
- Notch filter application for line noise removal
- Timestamp alignment and verification
- **Efficient Implementation**:
- Fast binary parsing with minimal allocations
- Proper error handling with descriptive messages
- Memory-efficient data structures
## Quick Start
```rust
use intan_importer::load;
// Load single RHS file
let result = load("path/to/your/file.rhs");
// Or load all RHS files from a directory
let result = load("path/to/recording/directory");
match result {
Ok(rhs_file) => {
// Access header information
println!("Sample rate: {} Hz", rhs_file.header.sample_rate);
println!("Number of channels: {}", rhs_file.header.amplifier_channels.len());
// Access recording data if present
if rhs_file.data_present {
if let Some(data) = &rhs_file.data {
if let Some(amp_data) = &data.amplifier_data {
// Process amplifier data
println!("Data dimensions: {:?}", amp_data.shape());
}
}
}
},
Err(e) => println!("Error loading file: {}", e),
}
```
## Data Structure
The crate organizes Intan data into a hierarchy of structs:
- `RhsFile`: Top-level container with header and data
- `RhsHeader`: Configuration, channel info, and recording parameters
- `Version`, `Notes`, `FrequencyParameters`, etc.
- Lists of channels: `amplifier_channels`, `board_adc_channels`, etc.
- `RhsData`: Actual recorded signals
- `timestamps`, `amplifier_data`, `stim_data`, etc.
## Error Handling
The library provides descriptive errors for various failure scenarios (file format errors,
I/O failures, etc.) through the `IntanError` type.
*/
use Error;
use Path;
use fs;
// Re-export types
pub use *;
/// Loads RHS data from a file or directory.
///
/// This function can handle two input types:
/// 1. **Single file**: Loads a single RHS file
/// 2. **Directory**: Loads and combines all RHS files in the directory
///
/// When loading from a directory, all RHS files are combined chronologically into
/// a single dataset. Files must have compatible headers (same channels, sample rates, etc.).
///
/// # Parameters
///
/// * `path` - Path to an RHS file or a directory containing RHS files
///
/// # Returns
///
/// * `Result<RhsFile, Box<dyn Error>>` - Either the loaded file data or an error
///
/// # Examples
///
/// ## Loading a single file
/// ```no_run
/// use intan_importer::load;
///
/// let result = load("recording.rhs");
/// match result {
/// Ok(rhs_file) => {
/// println!("Loaded {} seconds of data", rhs_file.duration());
/// },
/// Err(e) => println!("Error: {}", e),
/// }
/// ```
///
/// ## Loading from a directory
/// ```no_run
/// use intan_importer::load;
///
/// // Load all RHS files from a recording session split across multiple files
/// let result = load("recording_session/");
/// match result {
/// Ok(rhs_file) => {
/// println!("Combined {} files", rhs_file.source_files.as_ref().unwrap().len());
/// println!("Total duration: {} seconds", rhs_file.duration());
/// },
/// Err(e) => println!("Error: {}", e),
/// }
/// ```
///
/// # Performance Considerations
///
/// When loading multiple files, the entire combined dataset is loaded into memory.
/// Be aware of memory usage when dealing with lengthy recording sessions.
/// Loads and combines all RHS files from a directory