forked from gmishne/diffusion_maps
-
Notifications
You must be signed in to change notification settings - Fork 0
/
calcDiffusionMap.m
104 lines (88 loc) · 2.94 KB
/
calcDiffusionMap.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
function [diffusion_map, Lambda, Psi, Ms, Phi, K_rw] = calcDiffusionMap(K,configParams)
% calculate diffusion map
%
% Gal Mishne
dParams.normalization = 'markov';
dParams.t = 1;
dParams.verbose = 0;
dParams.plotResults = 0;
if exist('configParams','var') && isfield(configParams,'patchDim')
dParams.maxInd = round(configParams.patchDim^2/4);
else
dParams.maxInd = 4;
end
if exist('configParams','var')
configParams = setParams(dParams, configParams);
else
configParams = setParams(dParams,[]);
end
D = sum(K,2)+eps;
if strcmp(configParams.normalization, 'lb') % laplace-beltrami
one_over_D = spdiags(1./D,0,size(K,1),size(K,2));
K = one_over_D*K*one_over_D;
D = sum(K,2);
elseif strcmp(configParams.normalization, 'fp') % fokker-planck
one_over_D_sqrt = spdiags(1./sqrt(D),0,size(K,1),size(K,2));
K = one_over_D_sqrt*K*one_over_D_sqrt;
D = sum(K,2);
end
%% calculate eigen decomposition
one_over_D_sqrt = spdiags(sqrt(1./D),0,size(K,1),size(K,2));
% using symmetric matrix for calculation
Ms = one_over_D_sqrt * K * one_over_D_sqrt;
Ms = 0.5*(Ms + Ms');
% if ~issparse(Ms) && sum(Ms(:)==0)/numel(Ms)>0.75
% Ms(Ms<1e-10) = 0;
% Ms = sparse(Ms);
% end
if configParams.verbose
disp('Calculating Eigen values and vectors');
end
options.disp = 0;
options.isreal = true;
options.issym = true;
% calculating first configParams.maxInd eigenvalues and vectors
if issparse(Ms)
[v,lambda] = eigs(Ms,configParams.maxInd,'lm',options);
Lambda = diag(lambda);
[Lambda,I] = sort(Lambda,'descend'); %eigs doesn't return the values sorted
v = v(:,I);
else
[v,lambda] = eig(Ms);
[lambda,I] = sort(diag(lambda),'descend'); %eigs doesn't return the values sorted
Lambda = lambda(1:configParams.maxInd);
v = v(:,I(1:configParams.maxInd));
end
v = v./ repmat(sqrt(sum(v.^2)),size(v,1),1);
Psi = one_over_D_sqrt * v;
%Psi = Psi./ repmat(sqrt(sum(Psi.^2)),size(Psi,1),1);
inds = 2:length(Lambda); % disregarding first trivial eigenvalue
clear one_over_D_sqrt
% diffusion map for t=1
diffusion_map = (Psi./ repmat(sqrt(sum(Psi.^2)),size(Psi,1),1) .* ...
repmat(Lambda'.^ configParams.t,size(Psi,1),1));
diffusion_map = diffusion_map(:,inds)';
if nargout >= 5
D_mat = spdiags(D,0,size(K,1),size(K,2));
Phi = D_mat * Psi;
end
if nargout == 6
one_over_D = spdiags(1./D,0,size(K,1),size(K,2));
K_rw = one_over_D*K;
end
% plotting results
if configParams.plotResults
figure;
plot(Lambda);
title('\lambda');
ylim([0 1])
figure;
scatter(1:size(Psi,1),diffusion_map(1,:))
hold all
scatter(1:size(Psi,1),diffusion_map(2,:))
scatter(1:size(Psi,1),diffusion_map(3,:))
title('Diffusion Map Coordinates');
figure(101);
scatter3(diffusion_map(1,:),diffusion_map(2,:),diffusion_map(3,:))
title('Diffusion Map');
end