def cov_integral(alpha, alphadot, basis, T=100, k=5): """ Calculates covariance along path alpha :param alpha: numpy ndarray of shape (2,M) of M samples (first curve) :param alphadot: numpy ndarray of shape (2,M) of M samples :param basis: list numpy ndarray of shape (2,M) of M samples :param T: Number of samples of curve (Default = 100) :param k: number of samples along path (Default = 5) :rtype: numpy ndarray :return u: covariance """ u = zeros((2, T, k)) for tau in range(1, k): w = u[:, :, tau-1] q1 = alpha[:, :, tau-1] q2 = alpha[:, :, tau] b = basis[tau] wbar = cf.parallel_translate(w, q1, q2, b) u[:, :, tau] = (1./(k-1))*alphadot[:, :, tau]+wbar return(u)
def back_parallel_transport(u1, alpha, basis, T=100, k=5): """ backwards parallel translates q1 and q2 along manifold :param u1: numpy ndarray of shape (2,M) of M samples :param alpha: numpy ndarray of shape (2,M) of M samples :param basis: list numpy ndarray of shape (2,M) of M samples :param T: Number of samples of curve (Default = 100) :param k: number of samples along path (Default = 5) :rtype: numpy ndarray :return utilde: translated vector """ utilde = zeros((2, T, k)) utilde[:, :, k-1] = u1 for tau in arange(k-2, -1, -1): w = utilde[:, :, tau+1] q1 = alpha[:, :, tau+1] q2 = alpha[:, :, tau] b = basis[tau] utilde[:, :, tau] = cf.parallel_translate(w, q1, q2, b) return(utilde)
def back_parallel_transport(u1, alpha, basis, T=100, k=5): """ backwards parallel translates q1 and q2 along manifold :param u1: numpy ndarray of shape (2,M) of M samples :param alpha: numpy ndarray of shape (2,M) of M samples :param basis: list numpy ndarray of shape (2,M) of M samples :param T: Number of samples of curve (Default = 100) :param k: number of samples along path (Default = 5) :rtype: numpy ndarray :return utilde: translated vector """ utilde = zeros((2, T, k)) utilde[:, :, k - 1] = u1 for tau in arange(k - 2, -1, -1): w = utilde[:, :, tau + 1] q1 = alpha[:, :, tau + 1] q2 = alpha[:, :, tau] b = basis[tau] utilde[:, :, tau] = cf.parallel_translate(w, q1, q2, b) return utilde
def cov_integral(alpha, alphadot, basis, T=100, k=5): """ Calculates covariance along path alpha :param alpha: numpy ndarray of shape (2,M) of M samples (first curve) :param alphadot: numpy ndarray of shape (2,M) of M samples :param basis: list numpy ndarray of shape (2,M) of M samples :param T: Number of samples of curve (Default = 100) :param k: number of samples along path (Default = 5) :rtype: numpy ndarray :return u: covariance """ u = zeros((2, T, k)) for tau in range(1, k): w = u[:, :, tau - 1] q1 = alpha[:, :, tau - 1] q2 = alpha[:, :, tau] b = basis[tau] wbar = cf.parallel_translate(w, q1, q2, b) u[:, :, tau] = (1.0 / (k - 1)) * alphadot[:, :, tau] + wbar return u
def sample_shapes(mu, K, mode='O', no=3, numSamp=10): """ Computes sample shapes from mean and covariance :param betamean: numpy ndarray of shape (n, M) describing the mean curve :param mu: numpy ndarray of shape (n, M) describing the mean srvf :param K: numpy ndarray of shape (M, M) describing the covariance :param mode: Open ('O') or closed curve ('C') (default 'O') :param no: number of direction (default 3) :param numSamp: number of samples (default 10) :rtype: tuple of numpy array :return samples: sample shapes """ n, T = mu.shape modes = ['O', 'C'] mode = [i for i, x in enumerate(modes) if x == mode] if len(mode) == 0: mode = 0 else: mode = mode[0] U, s, V = svd(K) if mode == 0: N = 2 else: N = 10 epsilon = 1./(N-1) samples = empty(numSamp, dtype=object) for i in range(0, numSamp): v = zeros((2, T)) for m in range(0, no): v = v + randn()*sqrt(s[m])*vstack((U[0:T, m], U[T:2*T, m])) q1 = mu for j in range(0, N-1): normv = sqrt(cf.innerprod_q2(v, v)) if normv < 1e-4: q2 = mu else: q2 = cos(epsilon*normv)*q1+sin(epsilon*normv)*v/normv if mode == 1: q2 = cf.project_curve(q2) # Parallel translate tangent vector basis2 = cf.find_basis_normal(q2) v = cf.parallel_translate(v, q1, q2, basis2, mode) q1 = q2 samples[i] = cf.q_to_curve(q2) return(samples)
def sample_shapes(self, no=3, numSamp=10): """ Computes sample shapes from mean and covariance :param no: number of direction (default 3) :param numSamp: number of samples (default 10) """ n, T = self.q_mean.shape modes = ['O', 'C'] mode = [i for i, x in enumerate(modes) if x == self.mode] if len(mode) == 0: mode = 0 else: mode = mode[0] U, s, V = svd(self.C) if mode == 0: N = 2 else: N = 10 epsilon = 1. / (N - 1) samples = empty(numSamp, dtype=object) for i in range(0, numSamp): v = zeros((2, T)) for m in range(0, no): v = v + randn() * sqrt(s[m]) * vstack( (U[0:T, m], U[T:2 * T, m])) q1 = self.q_mean for j in range(0, N - 1): normv = sqrt(cf.innerprod_q2(v, v)) if normv < 1e-4: q2 = self.q_mean else: q2 = cos(epsilon * normv) * q1 + sin( epsilon * normv) * v / normv if mode == 1: q2 = cf.project_curve(q2) # Parallel translate tangent vector basis2 = cf.find_basis_normal(q2) v = cf.parallel_translate(v, q1, q2, basis2, mode) q1 = q2 samples[i] = cf.q_to_curve(q2) self.samples = samples return
def curve_principal_directions(betamean, mu, K, mode='O', no=3, N=5): """ Computes principal direction of variation specified by no. N is Number of shapes away from mean. Creates 2*N+1 shape sequence :param betamean: numpy ndarray of shape (n, M) describing the mean curve :param mu: numpy ndarray of shape (n, M) describing the mean srvf :param K: numpy ndarray of shape (M, M) describing the covariance :param mode: Open ('O') or closed curve ('C') (default 'O') :param no: number of direction (default 3) :param N: number of shapes (2*N+1) (default 5) :rtype: tuple of numpy array :return pd: principal directions """ n, T = betamean.shape modes = ['O', 'C'] mode = [i for i, x in enumerate(modes) if x == mode] if len(mode) == 0: mode = 0 else: mode = mode[0] U, s, V = svd(K) qarray = empty((no, 2*N+1), dtype=object) qarray1 = empty(N, dtype=object) qarray2 = empty(N, dtype=object) pd = empty((no, 2*N+1), dtype=object) pd1 = empty(N, dtype=object) pd2 = empty(N, dtype=object) for m in range(0, no): princDir = vstack((U[0:T, m], U[T:2*T, m])) v = sqrt(s[m]) * princDir q1 = mu epsilon = 2./N # Forward direction from mean for i in range(0, N): normv = sqrt(cf.innerprod_q2(v, v)) if normv < 1e-4: q2 = mu else: q2 = cos(epsilon*normv)*q1 + sin(epsilon*normv)*v/normv if mode == 1: q2 = cf.project_curve(q2) qarray1[i] = q2 p = cf.q_to_curve(q2) centroid1 = -1*cf.calculatecentroid(p) beta_scaled, scale = cf.scale_curve(p + tile(centroid1, [T, 1]).T) pd1[i] = beta_scaled # Parallel translate tangent vector basis2 = cf.find_basis_normal(q2) v = cf.parallel_translate(v, q1, q2, basis2, mode) q1 = q2 # Backward direction from mean v = -sqrt(s[m])*princDir q1 = mu for i in range(0, N): normv = sqrt(cf.innerprod_q2(v, v)) if normv < 1e-4: q2 = mu else: q2 = cos(epsilon*normv)*q1+sin(epsilon*normv)*v/normv if mode == 1: q2 = cf.project_curve(q2) qarray2[i] = q2 p = cf.q_to_curve(q2) centroid1 = -1*cf.calculatecentroid(p) beta_scaled, scale = cf.scale_curve(p + tile(centroid1, [T, 1]).T) pd2[i] = beta_scaled # Parallel translate tangent vector basis2 = cf.find_basis_normal(q2) v = cf.parallel_translate(v, q1, q2, basis2, mode) q1 = q2 for i in range(0, N): qarray[m, i] = qarray2[(N-1)-i] pd[m, i] = pd2[(N-1)-i] qarray[m, N] = mu centroid1 = -1*cf.calculatecentroid(betamean) beta_scaled, scale = cf.scale_curve(betamean + tile(centroid1, [T, 1]).T) pd[m, N] = beta_scaled for i in range(N+1, 2*N+1): qarray[m, i] = qarray1[i-(N+1)] pd[m, i] = pd1[i-(N+1)] return(pd)