Source code for pyseer.cmdscale

# Copyright 2017 Marco Galardini and John Lees

'''Function to perform classical MDS'''

from .utils import set_env
# avoid numpy taking up more than one thread
with set_env(MKL_NUM_THREADS='1',
             NUMEXPR_NUM_THREADS='1',
             OMP_NUM_THREADS='1'):
    import numpy as np


# thanks to Francis Song for this function
# source: http://www.nervouscomputer.com/hfs/cmdscale-in-python/
[docs] def cmdscale(D): """Classical multidimensional scaling (MDS) Args: D (numpy.array) Symmetric distance matrix (n, n) Returns: Y (numpy.array) Configuration matrix (n, p). Each column represents a dimension. Only the p dimensions corresponding to positive eigenvalues of B are returned. Note that each dimension is only determined up to an overall sign, corresponding to a reflection. e (numpy.array) Eigenvalues of B (n, 1) """ # Number of points n = len(D) # Centering matrix H = np.eye(n) - np.ones((n, n))/n # YY^T B = -H.dot(D**2).dot(H)/2 # Diagonalize evals, evecs = np.linalg.eigh(B) # Sort by eigenvalue in descending order idx = np.argsort(evals)[::-1] evals = evals[idx] evecs = evecs[:, idx] # Compute the coordinates using positive-eigenvalued components only w, = np.where(evals > 0) L = np.diag(np.sqrt(evals[w])) V = evecs[:, w] Y = V.dot(L) return Y, evals[evals > 0]