-
Notifications
You must be signed in to change notification settings - Fork 2
/
rocarea_torben.m
132 lines (114 loc) · 3.63 KB
/
rocarea_torben.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
function [D, P, SEM] = rocarea(x,y,varargin)
%ROCAREA Receiver-operator characteristic.
% D = ROCAREA(X,Y) calculates area under ROC curve (D) for the samples X
% and Y.
%
% [D P SEM] = ROCAREA(X,Y,'BOOTSTRAP',N) calculates permutation test p-value
% (N, number of bootstrap samples) and returns standard deviation of permutation test.
%
% Optional input parameter-value paits (with default values):
% 'bootstrap', 0 - size of bootstrap sample; 0 corresponds to no
% bootstrap analysis
% 'transform', 'none' - 'swap': rescales results between 0.5 - 1
% 'scale' - rescales results between -1 to 1
% 'display', false - controls plotting of the ROC curve
% Edit log: AK 2/2002; AK 4/2005, BH 10/29/13, TO 8/2018
% Default arguments
prs = inputParser;
addRequired(prs,'x',@isnumeric) % first sample
addRequired(prs,'y',@isnumeric) % second sample
addParamValue(prs,'bootstrap',0,@isnumeric) % size of bootstrap sample
addParamValue(prs,'transform','none',@(s)ismember(s,{'none' 'swap' 'scale'})) % rescaling
addParamValue(prs,'display',false,@(s)islogical(s)|ismember(s,[0 1])) % control displaying rasters and PSTHs
parse(prs,x,y,varargin{:})
g = prs.Results;
% Binning
x = x(:); % convert to column vector
y = y(:);
nbin = ceil(max(length(x)*1.2,length(y)*1.2)); % bin number
mn = min([x; y]);
mx = max([x; y]);
bin_size = (mx - mn) / nbin; % bin size
bins = mn-bin_size:bin_size:mx+bin_size;
Lx = length(x);
Ly = length(y);
% AUROC
[D cdfx cdfy] = auc(x,y,Lx,Ly,bins);
% Bootstrap
if g.bootstrap > 0
z = [x; y];
Dboot = nan(1,g.bootstrap);
for k = 1:g.bootstrap
order = round(rand(1,Lx+Ly)*(Lx+Ly-1))+1; % resample
px = z(order(1:Lx));
py = z(order(Lx+1:Lx+Ly));
Dboot(k)= auc(px,py,Lx,Ly,bins); % bootstrap ROC
end
% p-value
P = iprctile(Dboot,D);
if D > mean(Dboot) % decide which side it should be on
P = 1 - P;
end
%sem
SEM = std(Dboot);
end
% Rescale
switch g.transform
case 'swap'
D = abs(D-0.5) + 0.5; % 'swap'
case 'scale'
D = 2 * (D - 0.5); % 'scale'
end
% Plot
if g.display
figure
hold on
plot(cdfx,cdfy,'b','LineWidth',2);
plot([0 1],[0 1],'k');
xlabel('x');
ylabel('y');
title(num2str(D));
end
% -------------------------------------------------------------------------
function [D cdfx cdfy] = auc(x,y,Lx,Ly,bins)
% Distributions
px = histc(x,bins); % distribution of first sample
px = px(1:end-1);
py = histc(y,bins); % distribution of second sample
py = py(1:end-1);
cdfx = cumsum(px) / Lx; % CDF of first sample
cdfy = cumsum(py) / Ly; % CDF of second sample
% AUROC
if isempty(cdfx) || isempty(cdfy)
D = NaN;
else
D = trapz(cdfx,cdfy); % ROC area under the curve
end
function p = iprctile(x,value)
%IPRCTILE Percentile.
% P = IPRCTILE(X,PCT) returns the PCT (between 0 and 1) percentile of X.
%
% See also PRCTILE.
% Edit log: AK 2/2005, BH 1/28/13
% Convert to column vector
x = x(:)';
% If all values are the same, return that value
if length(unique(x)) == 1
p = (unique(x) == value);
return
end
% Get percentile by intepolation
xx = sort(x); % sorted input
Lx = length(x); % length of input
ind = find(diff(xx)~=0); % indices where the input changes
ind = [ind+1 ind(end)+2];
xx = [-Inf xx Inf];
q = [0 ((0.5:Lx-0.5)/Lx) 1]; % predefined percentiles for interpolation
try
p = interp1(xx(ind),q(ind),value,'linear','extrap'); % interpolate percentile
p = max(0,min(1,p));
catch ME
disp(ME.message) % interpolation failed
warning('ipercentile:interpolationProblem','Error in IPERCENTILE.')
p = NaN;
end