def __init__(self, beta, mode='O', N=200, scale=True): """ fdacurve Construct an instance of this class :param beta: (n,T,K) matrix defining n dimensional curve on T samples with K curves :param mode: Open ('O') or closed curve ('C') (default 'O') :param N: resample curve to N points :param scale: scale curve to length 1 (true/false) """ self.mode = mode self.scale = scale K = beta.shape[2] n = beta.shape[0] q = zeros((n, N, K)) beta1 = zeros((n, N, K)) cent1 = zeros((n, K)) for ii in range(0, K): beta1[:, :, ii] = cf.resamplecurve(beta[:, :, ii], N, mode) a = -cf.calculatecentroid(beta1[:, :, ii]) beta1[:, :, ii] += tile(a, (N, 1)).T q[:, :, ii] = cf.curve_to_q(beta1[:, :, ii], self.scale, self.mode) cent1[:, ii] = -a self.q = q self.beta = beta1 self.cent = cent1
def preproc_open_curve(beta, T=100): n, M, k = beta.shape q = np.zeros((n, T, k)) beta2 = np.zeros((n, T, k)) for i in range(0, k): beta1 = beta[:, :, i] beta1, scale = cf.scale_curve(beta1) beta1 = cf.resamplecurve(beta1, T) centroid1 = cf.calculatecentroid(beta1) beta1 = beta1 - np.tile(centroid1, [T, 1]).T beta2[:, :, i] = beta1 q[:, :, i] = cf.curve_to_q(beta1) return (q, beta2)
def curve_karcher_cov(betamean, beta, mode='O'): """ This claculates the mean of a set of curves :param betamean: numpy ndarray of shape (n, M) describing the mean curve :param beta: numpy ndarray of shape (n, M, N) describing N curves in R^M :param mode: Open ('O') or closed curve ('C') (default 'O') :rtype: tuple of numpy array :return K: Covariance Matrix """ n, T, N = beta.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] # Compute Karcher covariance of uniformly sampled mean betamean = cf.resamplecurve(betamean, T) mu = cf.curve_to_q(betamean) if mode == 1: mu = cf.project_curve(mu) basis = cf.find_basis_normal(mu) v = zeros((n, T, N)) for i in range(0, N): beta1 = beta[:, :, i] w, dist = cf.inverse_exp_coord(betamean, beta1) # Project to the tangent sapce of manifold to obtain v_i if mode == 0: v[:, :, i] = w else: v[:, :, i] = cf.project_tangent(w, mu, basis) K = zeros((2*T, 2*T)) for i in range(0, N): w = v[:, :, i] wtmp = w.reshape((T*n, 1), order='C') K = K + wtmp.dot(wtmp.T) K = K/(N-1) return(K)
def geod_sphere(beta1, beta2, k=5): """ This function calculates the geodesics between open curves beta1 and beta2 with k steps along path :param beta1: numpy ndarray of shape (2,M) of M samples :param beta2: numpy ndarray of shape (2,M) of M samples :param k: number of samples along path (Default = 5) :rtype: numpy ndarray :return dist: geodesic distance :return path: geodesic path :return O: rotation matrix """ lam = 0.0 elastic = 1 rotation = 1 returnpath = 1 n, T = beta1.shape beta1 = cf.resamplecurve(beta1, T) beta2 = cf.resamplecurve(beta2, T) centroid1 = cf.calculatecentroid(beta1) beta1 = beta1 - tile(centroid1, [T, 1]).T centroid2 = cf.calculatecentroid(beta2) beta2 = beta2 - tile(centroid2, [T, 1]).T q1 = cf.curve_to_q(beta1) if rotation: beta2, O1, tau = cf.find_rotation_and_seed_coord(beta1, beta2) q2 = cf.curve_to_q(beta2) else: O1 = eye(2) q2 = cf.curve_to_q(beta2) if elastic: # Find the optimal coorespondence gam = cf.optimum_reparam_curve(q2, q1, lam) gamI = uf.invertGamma(gam) # Applying optimal re-parameterization to the second curve beta2n = cf.group_action_by_gamma_coord(beta2, gamI) q2n = cf.curve_to_q(beta2n) if rotation: beta2n, O2, tau = cf.find_rotation_and_seed_coord(beta1, beta2n) centroid2 = cf.calculatecentroid(beta2n) beta2n = beta2n - tile(centroid2, [T, 1]).T q2n = cf.curve_to_q(beta2n) O = O1.dot(O2) else: q2n = q2 O = O1 # Forming geodesic between the registered curves dist = arccos(cf.innerprod_q2(q1, q2n)) if returnpath: PsiQ = zeros((n, T, k)) PsiX = zeros((n, T, k)) for tau in range(0, k): s = dist * tau / (k - 1.) PsiQ[:, :, tau] = (sin(dist-s)*q1+sin(s)*q2n)/sin(dist) PsiX[:, :, tau] = cf.q_to_curve(PsiQ[:, :, tau]) path = PsiQ else: path = 0 return(dist, path, O)
def geod_sphere(beta1, beta2, k=5): """ This function caluclates the geodecis between open curves beta1 and beta2 with k steps along path :param beta1: numpy ndarray of shape (2,M) of M samples :param beta2: numpy ndarray of shape (2,M) of M samples :param k: number of samples along path (Default = 5) :rtype: numpy ndarray :return dist: geodesic distance :return path: geodesic path :return O: rotation matrix """ lam = 0.0 elastic = 1 rotation = 1 returnpath = 1 n, T = beta1.shape beta1 = cf.resamplecurve(beta1, T) beta2 = cf.resamplecurve(beta2, T) centroid1 = cf.calculatecentroid(beta1) beta1 = beta1 - tile(centroid1, [T, 1]).T centroid2 = cf.calculatecentroid(beta2) beta2 = beta2 - tile(centroid2, [T, 1]).T q1 = cf.curve_to_q(beta1) if rotation: beta2, O1, tau = cf.find_rotation_and_seed_coord(beta1, beta2) q2 = cf.curve_to_q(beta2) else: O1 = eye(2) q2 = cf.curve_to_q(beta2) if elastic: # Find the optimal coorespondence gam = cf.optimum_reparam_curve(q2, q1, lam) gamI = uf.invertGamma(gam) # Applying optimal re-parameterization to the second curve beta2n = cf.group_action_by_gamma_coord(beta2, gamI) q2n = cf.curve_to_q(beta2n) if rotation: beta2n, O2, tau = cf.find_rotation_and_seed_coord(beta1, beta2n) centroid2 = cf.calculatecentroid(beta2n) beta2n = beta2n - tile(centroid2, [T, 1]).T q2n = cf.curve_to_q(beta2n) O = O1.dot(O2) else: q2n = q2 O = O1 # Forming geodesic between the registered curves dist = arccos(cf.innerprod_q2(q1, q2n)) if returnpath: PsiQ = zeros((n, T, k)) PsiX = zeros((n, T, k)) for tau in range(0, k): s = dist * tau / (k - 1.0) PsiQ[:, :, tau] = (sin(dist - s) * q1 + sin(s) * q2n) / sin(dist) PsiX[:, :, tau] = cf.q_to_curve(PsiQ[:, :, tau]) path = PsiQ else: path = 0 return (dist, path, O)
def predict(self, newdata=None): """ This function performs prediction on regression model on new data if available or current stored data in object Usage: obj.predict() obj.predict(newdata) :param newdata: dict containing new data for prediction (needs the keys below, if None predicts on training data) :type newdata: dict :param beta: (n, M,N) matrix of curves :param y: truth if available """ T = self.warp_data.beta_mean.shape[1] if newdata != None: beta = newdata['beta'] y = newdata['y'] n = beta.shape[2] beta1 = np.zeros(beta.shape) q = np.zeros(beta.shape) for ii in range(0,n): if (beta.shape[1] != T): beta1[:,:,ii] = cf.resamplecurve(beta[:,:,ii],T) else: beta1[:,:,ii] = beta[:,:,ii] a = -cf.calculatecentroid(beta1[:,:,ii]) beta1[:,:,ii] += np.tile(a, (T,1)).T q[:,:,ii] = cf.curve_to_q(beta1[:,:,ii])[0] mu = self.warp_data.q_mean v = np.zeros(q.shape) for ii in range(0,n): qn_t, R, gamI = cf.find_rotation_and_seed_unique(mu, q[:,:,ii], 0, self.rotation) qn_t = qn_t / np.sqrt(cf.innerprod_q2(qn_t,qn_t)) q1dotq2 = cf.innerprod_q2(mu,qn_t) if (q1dotq2 > 1): q1dotq2 = 1 d = np.arccos(q1dotq2) u = qn_t - q1dotq2*mu normu = np.sqrt(cf.innerprod_q2(u,u)) if (normu>1e-4): v[:,:,ii] = u*np.arccos(q1dotq2)/normu else: v[:,:,ii] = np.zeros(qn_t.shape) Utmp = self.warp_data.U.T no = self.warp_data.U.shape[1] VM = np.mean(self.warp_data.v,2) VM = VM.flatten() x = np.zeros((no,n)) for i in range(0,n): tmp = v[:,:,i] tmpv1 = tmp.flatten() x[:,i] = Utmp.dot((tmpv1- VM)) self.y_pred = np.zeros(n) for ii in range(0,n): self.y_pred[ii] = self.alpha + np.dot(x[:,ii],self.b) if y is None: self.SSE = np.nan else: self.SSE = np.sum((y-self.y_pred)**2) else: n = self.warp_data.coef.shape[1] self.y_pred = np.zeros(n) for ii in range(0,n): self.y_pred[ii] = self.alpha + np.dot(self.warp_data.coef[:,ii],self.b) self.SSE = np.sum((self.y-self.y_pred)**2) return