-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy pathder_detectArtifacts.m
145 lines (122 loc) · 4.88 KB
/
der_detectArtifacts.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
138
139
140
141
142
143
144
145
function [spikeInfos, EuclDis] = der_detectArtifacts(spikeInfos, threshold, deltaT, minNoEventsToCompaire)
%der_detectArtifacts
% der_detectArtifacts deletes duplicate spike-shapes over different bundles
%
% Input:
% spikeInfos (table) containing the following information for each spike:
% bundleID: number of bundle
% channelID: number of channel
% clusterID: number of cluster of current channel
% timeStamps: time of amplitude of a spike
% SpikeShapes: shape of spike (in out setup using combinato: 64 samples)
%
% threshold: threshold for median eucledian distance to detect duplicate spikes
% deltaT: max time diff between two spikes to calculate their eucledian
% distance of wavelet-decomposition
%
%
% Output:
% spikeInfos without detected duplicate spikes
%
%
% Licence:
% This source code form is subject to the terms of the Mozilla Public
% Licence, v. 2.0. if a copy of the MPL was not distributed with this file,
% you can optain one at http://mozilla.org/MPL/2.0/.
EuclDis = [];
% set parameter
if ~exist('threshold', 'var') || isempty(threshold)
threshold = 14.4;
end
if ~exist('deltaT','var') || isempty(deltaT)
deltaT = .05; % threshold of time-diff between spikes within different bundles in ms
% gitterSamples = 1; % time-gitter as number of samples
end
% % set some variables
% compaire spike shapes from first to a chosen sample after amplitude;
% default is 40, see details in Dehnen & Kehl et al., 2020,....
no_samples = 40;
if ~exist('minNoEventsToCompaire','var') || isempty(minNoEventsToCompaire)
minNoEventsToCompaire = 3;
end
minNoPairs = size(nchoosek([1:minNoEventsToCompaire],2),1);
% sort all spiketimes
if issorted(spikeInfos.timeStamps)
TS = spikeInfos.timeStamps;
else
[TS, idxsort] = sort(spikeInfos.timeStamps);
spikeInfos = spikeInfos(idxsort,:);
warning('Input not sorted according to time stamps!');
fprintf('Sorting input spikes... \n')
end
% find possible duplicate spikes
DiffIndexTS = diff(TS);
duplicateSpikes = find(DiffIndexTS <= deltaT);
diffDuSp = diff(duplicateSpikes);
% loop over time-stamp-cluster
index_duplicateSpikes = [];
currStatus = 0;
for currSpike = 1:length(diffDuSp)
index_DuSp = [];
progress = round((currSpike / length(diffDuSp))*100);
if progress > currStatus
sprintf('%d%%',progress)
currStatus = currStatus + 1;
end
if diffDuSp(currSpike) == 1
ds = currSpike;
while ds < size(diffDuSp,1) && diffDuSp(ds) == 1
index_DuSp = [index_DuSp duplicateSpikes(ds)]; %#ok<*AGROW>
ds = ds + 1;
if ds > size(diffDuSp,1)
break
end
end
index_DuSp = [index_DuSp duplicateSpikes(ds) duplicateSpikes(ds)+1];
% correct for time diff to first spike of current index_DuSp
currTimeDiff = DiffIndexTS(index_DuSp(1:end-1));
if sum(currTimeDiff) > deltaT
currTD = 1;
while sum(currTimeDiff(1:(currTD+1))) <= deltaT
if currTD < length(currTimeDiff)
currTD = currTD + 1;
else
break
end
end
diffLength = length(currTimeDiff) - (currTD);
index_DuSp = index_DuSp(1:end-diffLength);
end
index_chToCompare = nchoosek(index_DuSp,2);
else
index_DuSp = [duplicateSpikes(currSpike) duplicateSpikes(currSpike)+1];
index_chToCompare = index_DuSp;
end
% just compaire within different bundles
diffBundles = diff([spikeInfos.bundleID(index_chToCompare(:,1)) spikeInfos.bundleID(index_chToCompare(:,2))],1,2);
index_chToCompare = index_chToCompare(diffBundles ~=0,:);
if ~isempty(index_chToCompare) && size(index_chToCompare,1) >= minNoPairs
no_spikesToCompaire = size(index_chToCompare,1);
possDuplSpi1 = spikeInfos.SpikeShapes(index_chToCompare(:,1),1:no_samples);
possDuplSpi2 = spikeInfos.SpikeShapes(index_chToCompare(:,2),1:no_samples);
if ~isempty(possDuplSpi1)
% shift the spike just in case of bipolar setting
index_sign = find(sign(possDuplSpi1(20)) ~=sign(possDuplSpi2(20)));
possDuplSpi1(index_sign) = possDuplSpi1(index_sign)*-1;
end
euclDis = nan(no_spikesToCompaire,1);
for spi = 1:no_spikesToCompaire
spikeShapes = [possDuplSpi1(spi,:);possDuplSpi2(spi,:)];
[coeff] = der_wavedec(spikeShapes);
euclDis(spi) = sqrt(sum(diff(coeff).^2));
end
if median(euclDis) <= threshold
index_duplicateSpikes = [index_duplicateSpikes index_DuSp];
end
EuclDis = [EuclDis; euclDis];
end
end
index_duplicateSpikes = reshape(index_duplicateSpikes,[],1);
index_duplicateSpikes = unique(index_duplicateSpikes);
spikeInfos.detectionLabel(index_duplicateSpikes) = spikeInfos.detectionLabel(index_duplicateSpikes)*2;
end