OpenEphysLoader.jl Documentation
A set of tools to load data files made by the Open Ephys GUI
Package Features
- Provides easy access to sample values, time stamps, and recording numbers through an Array interface.
- Data can be accessed in their raw form, or converted to voltage and seconds.
- Accessing a data file does not require loading the entirety of its contents into RAM.
- Provides tools to read the metadata for Open Ephys recordings.
Example Usage
Data in a file can be accessed by creating a SampleArray, TimeArray, or JointArray. These arrays can be constructed with a IOStream at the beginning of an open .continuous data file, or alternatively the name of a .continuous file.
Accessing sample values
For this example, we will demonstrate how to access sample values using SampleArray.
using OpenEphysLoader
io = open(path, "r") # Where 'path' is the path to a .continuous file
A = SampleArray(io) # A is a regular julia matrix
A[1:3] # Show the first three sampled voltages (in uV) in the file3-element Array{Float64,1}:
-0.089573
-0.090134
-0.090134Once constructed, SampleArray objects can be used like a normal Julia array.
Sample values are stored in .continuous files as ADC codes (Int16 codes for the RHD2000 family), which OpenEphysLoader.jl automatically converts to voltages by default. In order to access the raw ADC codes, pass an integer type (ADC reads are Int16 for the RHD2000 family) as the first argument when constructing a SampleArray:
seek(io, 0) # IOStream neeeds to be at the beginning of the data file
A = SampleArray(Int16, io)
A[1:3]3-element Array{Int16,1}:
-2395
-2410
-2410If a floating point type is specified, the ADC codes are converted into voltages. If no sample type is specified, then the default is Float64.
Here we moved the IOStream back to the beginning of the file, because we used this IOStream for our previous example. When using the REPL, if you reuse IOStream objects to create new OpenEphysLoader arrays, you must return the IOStream to the beginning of the file.
Accessing time stamps
Time stamps can be accessed with TimeArray.
Accessing the time stamps returns sample time by default, but the raw sample numbers can be easily accessed as well:
io = open(path, "r")
B = TimeArray(io) # Time of each sample in seconds, equivalent to TimeArray(Float64, io)
B[1]2750.399966666667io = open(path, "r")
B = TimeArray(Int64, io) # sample number for each sample
B[1]82512000Accessing all information about a sample
JointArray provides access to the sample value, timestamp, and recording number for each sample. If you want to access both the time stamps and values for samples in a data file, it is most efficient to use a JointArray:
io = open(path, "r")
C = JointArray(io) # Time of each sample in seconds
(sampval, timestamp, recno) = C[1] # Access information about the first sample(-0.089573, 2750.399966666667, 0)Elements of the JointArray are three-tuples, which can be destructured as shown above.
sampval # inspect the destructured sample value from above-0.089573Copying file contents into RAM
Arrays in OpenEphysLoader.jl access the data directly from disk. In order to pull the contents into memory, Create a regular Julia Array from OpenEphysLoader.jl arrays.
io = open(path, "r")
A = SampleArray(Int16, io) # Elements of A will be read from disk
D = Array(A) # This will copy the entire contents of A into a regular Julia array in RAM
D[1:3]3-element Array{Int16,1}:
-2395
-2410
-2410Recording metadata
The metadata of recordings can be accessed using the metadata function:
using OpenEphysLoader
meta = metadata(datadir) # Where datadir is the path to your recording directoryfile_version: v"0.4.0"
experiment_number: 1
separate_files: false
recordings: OERecordingMeta{OERhythmProcessor{String}}[recording 0]
settings:
info:
gui_version: v"0.3.5"
plugin_api_version: v"0.0.0"
datetime: 2015-07-21T14:50:12
os: "Windows 7"
machine: "RIGDESK"
recording_chain: OpenEphysLoader.OESignalTree{OERhythmProcessor{String}}(OpenEphysLoader.SignalNode{OERhythmProcessor{String}}[
id: 100
lowcut: 1.0
highcut: 7500.0
adcs_on: false
noiseslicer: false
ttl_fastsettle: true
dac_ttl: false
dac_hpf: true
dsp_offset: true
dsp_cutoff: 0.0
channels: OEChannel{String}[CH1, CH2, CH3, CH4, CH5, CH6, CH7, CH8, CH9, CH10 … CH26, CH27, CH28, CH29, CH30, CH31, CH32, AUX1, AUX2, AUX3]
])Dealing with corrupted files
For whatever reason, Open Ephys seems to regularly produce data files that are missing samples at the end of the file. Because this library will by default check each file for corruption before attempting to access its data, such files will fail to open with a CorruptedException.
In order to access the samples that are intact, use the optional third parameter of SampleArray to disable checking for corruption prior to opening a file:
io = open(path, "r")
A = SampleArray(Float64, io, false)
A[1:3]3-element Array{Float64,1}:
-0.089573
-0.090134
-0.090134Another common cause of receiving CorruptedException when opening a file is using an IOStream that is not at the beginning of the file. Either use a new IOStream object, or return the IOStream to the beginning of file with seek(io, 0) where io is the name of the IOStream variable.