Esempio n. 1
0
def logistic_warp(alpha,
                  nu,
                  q,
                  y,
                  deltaO=.1,
                  deltag=.05,
                  max_itr=8000,
                  tol=1e-4,
                  display=0,
                  method=1):
    """
    calculates optimal warping for function logistic regression

    :param alpha: scalar
    :param nu: numpy ndarray of shape (M,N) of M functions with N samples
    :param q: numpy ndarray of shape (M,N) of M functions with N samples
    :param y: numpy ndarray of shape (1,N) of M functions with N samples
    responses

    :rtype: numpy array
    :return gamma: warping function

    """
    if method == 1:
        tau = 0
        # q, scale = cf.scale_curve(q)
        q = q / norm(q)
        # nu, scale = cf.scale_curve(nu)
        # alpha = alpha/scale

        gam_old, O_old = lw.oclogit_warp(
            np.ascontiguousarray(alpha), np.ascontiguousarray(nu),
            np.ascontiguousarray(q), np.ascontiguousarray(y, dtype=np.int32),
            max_itr, tol, deltaO, deltag, display)
    elif method == 2:
        betanu = cf.q_to_curve(nu)
        beta = cf.q_to_curve(q)
        T = beta.shape[1]
        if y == 1:
            beta1, O_old, tau = cf.find_rotation_and_seed_coord(betanu, beta)
            q = cf.curve_to_q(beta1)[0]
            gam_old = cf.optimum_reparam_curve(nu, q)
        elif y == -1:
            beta1, O_old, tau = cf.find_rotation_and_seed_coord(
                -1 * betanu, beta)
            q = cf.curve_to_q(beta1)[0]
            gam_old = cf.optimum_reparam_curve(-1 * nu, q)

    return (gam_old, O_old, tau)
def regression_warp(nu, beta, y, alpha):
    """
    calculates optimal warping for function linear regression

    :param nu: numpy ndarray of shape (M,N) of M functions with N samples
    :param beta: numpy ndarray of shape (M,N) of M functions with N samples
    :param y: numpy ndarray of shape (1,N) of M functions with N samples
    responses
    :param alpha: numpy scalar

    :rtype: numpy array
    :return gamma_new: warping function

    """
    T = beta.shape[1]
    betanu = cf.q_to_curve(nu)

    betaM, O_M, tauM = cf.find_rotation_and_seed_coord(betanu, beta)
    q = cf.curve_to_q(betaM)
    gam_M = cf.optimum_reparam_curve(nu, q)
    betaM = cf.group_action_by_gamma_coord(betaM, gam_M)
    qM = cf.curve_to_q(betaM)
    y_M = cf.innerprod_q2(qM, nu)

    betam, O_m, taum = cf.find_rotation_and_seed_coord(-1 * betanu, beta)
    q = cf.curve_to_q(betam)
    gam_m = cf.optimum_reparam_curve(-1 * nu, q)
    betam = cf.group_action_by_gamma_coord(betam, gam_m)
    qm = cf.curve_to_q(betam)
    y_m = cf.innerprod_q2(qm, nu)

    if y > alpha + y_M:
        O_hat = O_M
        gamma_new = gam_M
        tau = tauM
    elif y < alpha + y_m:
        O_hat = O_m
        gamma_new = gam_m
        tau = taum
    else:
        gamma_new, O_hat, tau = cf.curve_zero_crossing(y - alpha, beta, nu, y_M, y_m, gam_M,
                                                               gam_m)

    return(gamma_new, O_hat, tau)
Esempio n. 3
0
def logistic_warp(alpha, nu, q, y, deltaO=.1, deltag=.05, max_itr=8000,
                  tol=1e-4, display=0, method=1):
    """
    calculates optimal warping for function logistic regression

    :param alpha: scalar
    :param nu: numpy ndarray of shape (M,N) of M functions with N samples
    :param q: numpy ndarray of shape (M,N) of M functions with N samples
    :param y: numpy ndarray of shape (1,N) of M functions with N samples
    responses

    :rtype: numpy array
    :return gamma: warping function

    """
    if method == 1:
        tau = 0
        # q, scale = cf.scale_curve(q)
        q = q/norm(q)
        # nu, scale = cf.scale_curve(nu)
        # alpha = alpha/scale

        gam_old, O_old = lw.oclogit_warp(np.ascontiguousarray(alpha),
                                         np.ascontiguousarray(nu),
                                         np.ascontiguousarray(q),
                                         np.ascontiguousarray(y, dtype=np.int32),
                                         max_itr, tol, deltaO, deltag, display)
    elif method == 2:
        betanu = cf.q_to_curve(nu)
        beta = cf.q_to_curve(q)
        T = beta.shape[1]
        if y == 1:
            beta1, O_old, tau = cf.find_rotation_and_seed_coord(betanu, beta)
            q = cf.curve_to_q(beta1)
            gam_old = cf.optimum_reparam_curve(nu, q)
        elif y == -1:
            beta1, O_old, tau = cf.find_rotation_and_seed_coord(-1 * betanu, beta)
            q = cf.curve_to_q(beta1)
            gam_old = cf.optimum_reparam_curve(-1 * nu, q)


    return (gam_old, O_old, tau)
Esempio n. 4
0
def oc_srvf_align(beta, mode='O'):
    """
    This claculates the mean of a set of curves and aligns them
    :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 betan: aligned curves
    :return qn: aligned srvf
    :return betamean: mean curve
    :return mu: mean srvf
    """
    n, T, N = beta.shape
    # find mean
    mu, betamean, v, q = curve_karcher_mean(beta, mode=mode)

    qn = zeros((n, T, N))
    betan = zeros((n, T, N))
    centroid2 = cf.calculatecentroid(betamean)
    betamean = betamean - tile(centroid2, [T, 1]).T
    q_mu = cf.curve_to_q(betamean)
    # align to mean
    for ii in range(0, N):
        beta1 = beta[:, :, ii]
        centroid1 = cf.calculatecentroid(beta1)
        beta1 = beta1 - tile(centroid1, [T, 1]).T

        # Iteratively optimize over SO(n) x Gamma
        for i in range(0, 1):
            # Optimize over SO(n)
            beta1, O_hat, tau = cf.find_rotation_and_seed_coord(betamean,
                                                                beta1)
            q1 = cf.curve_to_q(beta1)

            # Optimize over Gamma
            gam = cf.optimum_reparam_curve(q1, q_mu, 0.0)
            gamI = uf.invertGamma(gam)
            # Applying optimal re-parameterization to the second curve
            beta1 = cf.group_action_by_gamma_coord(beta1, gamI)

        # Optimize over SO(n)
        beta1, O_hat, tau = cf.find_rotation_and_seed_coord(betamean, beta1)
        qn[:, :, ii] = cf.curve_to_q(beta1)
        betan[:, :, ii] = beta1

    align_results = collections.namedtuple('align', ['betan', 'qn', 'betamean', 'mu'])
    out = align_results(betan, qn, betamean, q_mu)
    return out
Esempio n. 5
0
def oc_srvf_align(beta, mode='O'):
    """
    This claculates the mean of a set of curves and aligns them
    :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 betan: aligned curves
    :return qn: aligned srvf
    :return betamean: mean curve
    :return mu: mean srvf
    """
    n, T, N = beta.shape
    # find mean
    mu, betamean, v, q = curve_karcher_mean(beta, mode=mode)

    qn = zeros((n, T, N))
    betan = zeros((n, T, N))
    centroid2 = cf.calculatecentroid(betamean)
    betamean = betamean - tile(centroid2, [T, 1]).T
    q_mu = cf.curve_to_q(betamean)
    # align to mean
    for ii in range(0, N):
        beta1 = beta[:, :, ii]
        centroid1 = cf.calculatecentroid(beta1)
        beta1 = beta1 - tile(centroid1, [T, 1]).T

        # Iteratively optimize over SO(n) x Gamma
        for i in range(0, 1):
            # Optimize over SO(n)
            beta1, O_hat, tau = cf.find_rotation_and_seed_coord(betamean,
                                                                beta1)
            q1 = cf.curve_to_q(beta1)

            # Optimize over Gamma
            gam = cf.optimum_reparam_curve(q1, q_mu, 0.0)
            gamI = uf.invertGamma(gam)
            # Applying optimal re-parameterization to the second curve
            beta1 = cf.group_action_by_gamma_coord(beta1, gamI)

        # Optimize over SO(n)
        beta1, O_hat, tau = cf.find_rotation_and_seed_coord(betamean, beta1)
        qn[:, :, ii] = cf.curve_to_q(beta1)
        betan[:, :, ii] = beta1

    align_results = collections.namedtuple('align', ['betan', 'qn', 'betamean', 'mu'])
    out = align_results(betan, qn, betamean, q_mu)
    return out
Esempio n. 6
0
def align_sub(beta_mean, q_mu, beta1):
    # Iteratively optimize over SO(n) x Gamma
    for i in range(0, 1):
        # Optimize over SO(n)
        beta1, O_hat, tau = cf.find_rotation_and_seed_coord(beta_mean, beta1)
        q1 = cf.curve_to_q(beta1)

        # Optimize over Gamma
        gam = cf.optimum_reparam_curve(q1, q_mu, 0.0)
        gamI = uf.invertGamma(gam)
        # Applying optimal re-parameterization to the second curve
        beta1 = cf.group_action_by_gamma_coord(beta1, gamI)

    # Optimize over SO(n)
    beta1, O_hat, tau = cf.find_rotation_and_seed_coord(beta_mean, beta1)

    return (beta1, q1, gamI)
Esempio n. 7
0
def init_path_rand(beta1, beta_mid, beta2, T=100, k=5):
    r"""
    Initializes a path in :math:`\cal{C}`. beta1, beta_mid beta2 are already
    standardized curves. Creates a path from beta1 to beta_mid to beta2 in
    shape space, then projects to the closed shape manifold.

    :param beta1: numpy ndarray of shape (2,M) of M samples (first curve)
    :param betamid: numpy ndarray of shape (2,M) of M samples (mid curve)
    :param beta2: numpy ndarray of shape (2,M) of M samples (end curve)
    :param T: Number of samples of curve (Default = 100)
    :param k: number of samples along path (Default = 5)

    :rtype: numpy ndarray
    :return alpha: a path between two q-functions
    :return beta:  a path between two curves
    :return O: rotation matrix

    """
    alpha = zeros((2, T, k))
    beta = zeros((2, T, k))

    q1 = cf.curve_to_q(beta1)
    q_mid = cf.curve_to_q(beta_mid)

    # find optimal rotation of q2
    beta2, O1, tau1 = cf.find_rotation_and_seed_coord(beta1, beta2)
    q2 = cf.curve_to_q(beta2)

    # find the optimal coorespondence
    gam = cf.optimum_reparam_curve(q2, q1)
    gamI = uf.invertGamma(gam)

    # apply optimal reparametrization
    beta2n = cf.group_action_by_gamma_coord(beta2, gamI)

    # find optimal rotation of q2
    beta2n, O2, tau1 = 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)

    # Initialize a path as a geodesic through q1 --- q_mid --- q2
    theta1 = arccos(cf.innerprod_q2(q1, q_mid))
    theta2 = arccos(cf.innerprod_q2(q_mid, q2n))
    tmp = arange(2, int((k-1)/2)+1)
    t = zeros(tmp.size)
    alpha[:, :, 0] = q1
    beta[:, :, 0] = beta1

    i = 0
    for tau in range(2, int((k-1)/2)+1):
        t[i] = (tau-1.)/((k-1)/2.)
        qnew = (1/sin(theta1))*(sin((1-t[i])*theta1)*q1+sin(t[i]*theta1)*q_mid)
        alpha[:, :, tau-1] = cf.project_curve(qnew)
        x = cf.q_to_curve(alpha[:, :, tau-1])
        a = -1*cf.calculatecentroid(x)
        beta[:, :, tau-1] = x + tile(a, [T, 1]).T
        i += 1

    alpha[:, :, int((k-1)/2)] = q_mid
    beta[:, :, int((k-1)/2)] = beta_mid

    i = 0
    for tau in range(int((k-1)/2)+1, k-1):
        qnew = (1/sin(theta2))*(sin((1-t[i])*theta2)*q_mid
                                + sin(t[i]*theta2)*q2n)
        alpha[:, :, tau] = cf.project_curve(qnew)
        x = cf.q_to_curve(alpha[:, :, tau])
        a = -1*cf.calculatecentroid(x)
        beta[:, :, tau] = x + tile(a, [T, 1]).T
        i += 1

    alpha[:, :, k-1] = q2n
    beta[:, :, k-1] = beta2n

    return(alpha, beta, O)
Esempio n. 8
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)
Esempio n. 9
0
def init_path_rand(beta1, beta_mid, beta2, T=100, k=5):
    """
    Initializes a path in \cal{C}. beta1, beta_mid beta2 are already
    standardized curves. Creates a path from beta1 to beta_mid to beta2 in
    shape space, then projects to the closed shape manifold.

    :param beta1: numpy ndarray of shape (2,M) of M samples (first curve)
    :param betamid: numpy ndarray of shape (2,M) of M samples (mid curve)
    :param beta2: numpy ndarray of shape (2,M) of M samples (end curve)
    :param T: Number of samples of curve (Default = 100)
    :param k: number of samples along path (Default = 5)

    :rtype: numpy ndarray
    :return alpha: a path between two q-functions
    :return beta:  a path between two curves
    :return O: rotation matrix

    """
    alpha = zeros((2, T, k))
    beta = zeros((2, T, k))

    q1 = cf.curve_to_q(beta1)
    q_mid = cf.curve_to_q(beta_mid)

    # find optimal rotation of q2
    beta2, O1, tau1 = cf.find_rotation_and_seed_coord(beta1, beta2)
    q2 = cf.curve_to_q(beta2)

    # find the optimal coorespondence
    gam = cf.optimum_reparam_curve(q2, q1)
    gamI = uf.invertGamma(gam)

    # apply optimal reparametrization
    beta2n = cf.group_action_by_gamma_coord(beta2, gamI)

    # find optimal rotation of q2
    beta2n, O2, tau1 = 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)

    # Initialize a path as a geodesic through q1 --- q_mid --- q2
    theta1 = arccos(cf.innerprod_q2(q1, q_mid))
    theta2 = arccos(cf.innerprod_q2(q_mid, q2n))
    tmp = arange(2, int((k - 1) / 2) + 1)
    t = zeros(tmp.size)
    alpha[:, :, 0] = q1
    beta[:, :, 0] = beta1

    i = 0
    for tau in range(2, int((k - 1) / 2) + 1):
        t[i] = (tau - 1.0) / ((k - 1) / 2.0)
        qnew = (1 / sin(theta1)) * (sin((1 - t[i]) * theta1) * q1 + sin(t[i] * theta1) * q_mid)
        alpha[:, :, tau - 1] = cf.project_curve(qnew)
        x = cf.q_to_curve(alpha[:, :, tau - 1])
        a = -1 * cf.calculatecentroid(x)
        beta[:, :, tau - 1] = x + tile(a, [T, 1]).T
        i += 1

    alpha[:, :, int((k - 1) / 2)] = q_mid
    beta[:, :, int((k - 1) / 2)] = beta_mid

    i = 0
    for tau in range(int((k - 1) / 2) + 1, k - 1):
        qnew = (1 / sin(theta2)) * (sin((1 - t[i]) * theta2) * q_mid + sin(t[i] * theta2) * q2n)
        alpha[:, :, tau] = cf.project_curve(qnew)
        x = cf.q_to_curve(alpha[:, :, tau])
        a = -1 * cf.calculatecentroid(x)
        beta[:, :, tau] = x + tile(a, [T, 1]).T
        i += 1

    alpha[:, :, k - 1] = q2n
    beta[:, :, k - 1] = beta2n

    return (alpha, beta, O)
Esempio n. 10
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)