Example #1
0
    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)
Example #3
0
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)
Example #4
0
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)
Example #5
0
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)
Example #6
0
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