-
Notifications
You must be signed in to change notification settings - Fork 5
/
mdscale_robust.m
39 lines (38 loc) · 1.54 KB
/
mdscale_robust.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
% call mdscale as usual, but handle ColocatedPoints error by adding fake
% dissimilarities to data, and NoSolution error by multiplying
% dissimilarities by a scalar. Same inputs/outputs as mdscale.
% [y,stress,disparities] = mdscale_robust(rdm,varargin);
function [y,stress,disparities] = mdscale_robust(rdm,varargin);
try
[y,stress,disparities] = mdscale(rdm,varargin{:});
catch err
if strcmp(err.identifier,'stats:mdscale:ColocatedPoints')
warning('shifting min dissimilarities to avoid colocated points');
offd = ~logical(eye(size(rdm,1)));
m = min(rdm(offd));
% first try constant offset
target = (rdm==m) & offd;
rdm(target) = m + .2;
try
[y,stress,disparities] = mdscale(rdm,varargin{:});
catch err2
if strcmp(err2.identifier,'stats:mdscale:ColocatedPoints')
% next try half-way to next dissimilarity
% next smallest dissimilarity
nextm = min(rdm(~target & rdm>m));
rdm(target) = (m+nextm) / 2;
[y,stress,disparities] = mdscale(rdm,varargin{:});
else
rethrow(err2);
end
end
elseif strcmp(err.identifier,'stats:mdscale:NoSolution')
% try just multiplying by a scalar. Matlab's mdscale has a dumb
% threshold setting at line 567 or so which seems to depend on the
% scale of the input data
rdm = rdm * 100;
[y,stress,disparities] = mdscale(rdm,varargin{:});
else
rethrow(err);
end
end