This repository has been archived by the owner on Mar 20, 2024. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 176
/
load_open_ephys_binary.m
137 lines (130 loc) · 4.99 KB
/
load_open_ephys_binary.m
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
function D=load_open_ephys_binary(jsonFile, type, index, varargin)
%function D=load_open_ephys_binary(oebinFile, type, index)
%
%Loads data recorded by Open Ephys in Binary format
% oebinFile: The path for the structure.oebin json file
% type: The type of data to load. Can be 'continuous', 'events' or
% 'spikes'
% index: The index of the recorded element as appears in the oebin file
%(See also list_open_ephys_binary to extract recorded elements and indexes)
%
%Returns a structure with the header and relevant loaded data
%
%Example:
%D=load_open_ephys_binary('recording_1/structure.oebin','spikes',2)
%
%When loading continuous data, an optional fourth argument 'mmap' can be
%used:
%D=load_open_ephys_binary('recording_1/structure.oebin','continuous',1,'mmap')
%In this case, the Data member from the returned structure contains not an
%array with the data itself but a memory-mapped object of the file, which
%can be used to access its contents. This helps loading big-sized files, as
%it does not require loading the entire file in memory.
%In this case, the data may be accessed using the field D.Data.Data(1).mapped
%For example: D.Data.Data(1).mapped(chan,startSample:endSample)
%
%
%Limitations:
%-TEXT events are not supported by the NPY reading library, so their data
%will not load, but all other fields will.
%-Some metadata structures might not be supported by the NPY reading
%library. In this case the metadata will not be loaded
%In both cases a warning message will be displayed but the program will not
%fail
%
%
%This functions requires the functions readNPY and readNPYHeader
%from npy-matlab package from kwik-team
%(https://github.com/kwikteam/npy-matlab)
%Requires minimum MATLAB version: R2016b
if (exist('readNPY.m','file') == 0)
error('OpenEphys:loadBinary:npyLibraryNotfound','readNPY not found. Please be sure that npy-matlab is accessible');
end
if (exist('readNPYheader.m','file') == 0)
error('OpenEphys:loadBinary:npyLibraryNotfound','readNPYheader not found. Please be sure that npy-matlab is accessible');
end
if (nargin > 3 && strcmp(varargin{1},'mmap'))
continuousmap = true;
else
continuousmap = false;
end
json=jsondecode(fileread(jsonFile));
%Load appropriate header data from json
switch type
case 'continuous'
header=json.continuous(index);
case 'spikes'
header=json.spikes(index);
case 'events'
if (iscell(json.events))
header=json.events{index};
else
header=json.events(index);
end
otherwise
error('Data type not supported');
end
%Look for folder
f=java.io.File(jsonFile);
if (~f.isAbsolute())
f=java.io.File(fullfile(pwd,jsonFile));
end
f=java.io.File(f.getParentFile(),fullfile(type, header.folder_name));
if(~f.exists())
error('Data folder not found');
end
folder = char(f.getCanonicalPath());
D=struct();
D.Header = header;
switch type
case 'continuous'
D.Timestamps = readNPY(fullfile(folder,'timestamps.npy'));
contFile=fullfile(folder,'continuous.dat');
if (continuousmap)
file=dir(contFile);
samples=file.bytes/2/header.num_channels;
D.Data=memmapfile(contFile,'Format',{'int16' [header.num_channels samples] 'mapped'});
else
file=fopen(contFile);
D.Data=fread(file,[header.num_channels Inf],'int16');
fclose(file);
end
case 'spikes'
D.Timestamps = readNPY(fullfile(folder,'spike_times.npy'));
D.Waveforms = readNPY(fullfile(folder,'spike_waveforms.npy'));
D.ElectrodeIndexes = readNPY(fullfile(folder,'spike_electrode_indices.npy'));
D.SortedIndexes = readNPY(fullfile(folder,'spike_clusters.npy'));
case 'events'
D.Timestamps = readNPY(fullfile(folder,'timestamps.npy'));
D.ChannelIndex = readNPY(fullfile(folder,'channels.npy'));
f=java.io.File(folder);
group=char(f.getName());
if (strncmp(group,'TEXT',4))
%D.Data = readNPY(fullfile(folder,'text.npy'));
warning('TEXT files not supported by npy library');
elseif (strncmp(group,'TTL',3))
D.Data = readNPY(fullfile(folder,'channel_states.npy'));
wordfile = fullfile(folder,'full_words.npy');
if (isfile(wordfile))
D.FullWords = readNPY(wordfile);
end
elseif (strncmp(group,'BINARY',6))
D.Data = readNPY(fullfile(folder,'data_array.npy'));
end
end
metadatafile = fullfile(folder,'metadata.npy');
if (isfile(metadatafile))
try
D.MetaData = readNPY(metadatafile);
catch EX
thismsg = sprintf( 'Cannot read metadata file.\nData structure might not be supported.' );
thismsg = [ thismsg sprintf( '\n\nError message: %s', EX.message ) ];
thismsg = [ thismsg sprintf( '\n\nTrace:' ) ];
for i=1:length(EX.stack)
thismsg = [ thismsg sprintf( '\nFile: %s Function: %s Line: %d', ...
EX.stack(i).file, EX.stack(i).name, EX.stack(i).line ) ];
end
warning(thismsg);
end
end
end