コード例 #1
0
ファイル: fPCA.py プロジェクト: jdtuck/fdasrsf_python
def jointfPCAd(qn, vec, C, m, mu_psi):
    (M,N) = qn.shape
    g = np.vstack((qn, C*vec))

    mu_q = qn.mean(axis=1)
    mu_g = g.mean(axis=1)

    K = np.cov(g)
    U, s, V = svd(K)

    a = np.zeros((N,m))
    for i in range(0,N):
        for j in range(0,m):
            tmp = (g[:,i]-mu_g)
            a[i,j] = dot(tmp.T, U[:,j])

    qhat = np.tile(mu_q, (N,1))
    qhat = qhat.T
    qhat = qhat + dot(U[0:M,0:m],a.T)

    vechat = dot(U[M:,0:m], a.T/C)
    psihat = np.zeros((M-1,N))
    gamhat = np.zeros((M-1,N))
    for ii in range(0,N):
        psihat[:,ii] = geo.exp_map(mu_psi,vechat[:,ii])
        gam_tmp = cumtrapz(psihat[:,ii]*psihat[:,ii], np.linspace(0,1,M-1), initial=0)
        gamhat[:,ii] = (gam_tmp - gam_tmp.min()) / (gam_tmp.max() - gam_tmp.min())
    
    U = U[:,0:m]
    s = s[0:m]

    return qhat, gamhat, a, U, s, mu_g
コード例 #2
0
def jfpca_sub(mu_psi, vechat):
    M = mu_psi.shape[0]
    psihat = geo.exp_map(mu_psi, vechat)
    gam_tmp = cumtrapz(psihat * psihat, np.linspace(0, 1, M), initial=0)
    gamhat = (gam_tmp - gam_tmp.min()) / (gam_tmp.max() - gam_tmp.min())

    return gamhat
コード例 #3
0
def jointfPCAd(qn, vec, C, m, mu_psi):
    (M,N) = qn.shape
    g = np.vstack((qn, C*vec))

    mu_q = qn.mean(axis=1)
    mu_g = g.mean(axis=1)

    K = np.cov(g)
    U, s, V = svd(K)

    a = np.zeros((N,m))
    for i in range(0,N):
        for j in range(0,m):
            tmp = (g[:,i]-mu_g)
            a[i,j] = dot(tmp.T, U[:,j])

    qhat = np.tile(mu_q, (N,1))
    qhat = qhat.T
    qhat = qhat + dot(U[0:M,0:m],a.T)

    vechat = dot(U[M:,0:m], a.T/C)
    psihat = np.zeros((M-1,N))
    gamhat = np.zeros((M-1,N))
    for ii in range(0,N):
        psihat[:,ii] = geo.exp_map(mu_psi,vechat[:,ii])
        gam_tmp = cumtrapz(psihat[:,ii]*psihat[:,ii], np.linspace(0,1,M-1), initial=0)
        gamhat[:,ii] = (gam_tmp - gam_tmp.min()) / (gam_tmp.max() - gam_tmp.min())

    U = U[:,0:m]
    s = s[0:m]

    return qhat, gamhat, a, U, s, mu_g, g, K
コード例 #4
0
def SqrtMean(gam):
    """
    calculates the srsf of warping functions with corresponding shooting vectors

    :param gam: numpy ndarray of shape (M,N) of M warping functions
                with N samples

    :rtype: 2 numpy ndarray and vector
    :return mu: Karcher mean psi function
    :return gam_mu: vector of dim N which is the Karcher mean warping function
    :return psi: numpy ndarray of shape (M,N) of M SRSF of the warping functions
    :return vec: numpy ndarray of shape (M,N) of M shooting vectors

    """

    (T,n) = gam.shape
    time = linspace(0,1,T)
    binsize = mean(diff(time))
    psi = zeros((T, n))
    for k in range(0, n):
        psi[:, k] = sqrt(gradient(gam[:, k],binsize))

    # Find Direction
    mnpsi = psi.mean(axis=1)
    a = mnpsi.repeat(n)
    d1 = a.reshape(T, n)
    d = (psi - d1) ** 2
    dqq = sqrt(d.sum(axis=0))
    min_ind = dqq.argmin()
    mu = psi[:, min_ind]
    maxiter = 501
    tt = 1
    lvm = zeros(maxiter)
    vec = zeros((T, n))
    stp = .3
    itr = 0

    for i in range(0,n):
        out, theta = geo.inv_exp_map(mu,psi[:,i])
        vec[:,i] = out

    vbar = vec.mean(axis=1)
    lvm[itr] = geo.L2norm(vbar)

    while (lvm[itr] > 0.00000001) and (itr<maxiter):
        mu = geo.exp_map(mu, stp*vbar)
        itr += 1
        for i in range(0,n):
            out, theta = geo.inv_exp_map(mu,psi[:,i])
            vec[:,i] = out
        
        vbar = vec.mean(axis=1)
        lvm[itr] = geo.L2norm(vbar)
    

    gam_mu = cumtrapz(mu*mu, time, initial=0)
    gam_mu = (gam_mu - gam_mu.min()) / (gam_mu.max() - gam_mu.min())

    return mu, gam_mu, psi, vec
コード例 #5
0
def SqrtMean(gam):
    """
    calculates the srsf of warping functions with corresponding shooting vectors

    :param gam: numpy ndarray of shape (M,N) of M warping functions
                with N samples

    :rtype: 2 numpy ndarray and vector
    :return mu: Karcher mean psi function
    :return gam_mu: vector of dim N which is the Karcher mean warping function
    :return psi: numpy ndarray of shape (M,N) of M SRSF of the warping functions
    :return vec: numpy ndarray of shape (M,N) of M shooting vectors

    """

    (T,n) = gam.shape
    time = linspace(0,1,T)
    binsize = mean(diff(time))
    psi = zeros((T, n))
    for k in range(0, n):
        psi[:, k] = sqrt(gradient(gam[:, k],binsize))

    # Find Direction
    mnpsi = psi.mean(axis=1)
    a = mnpsi.repeat(n)
    d1 = a.reshape(T, n)
    d = (psi - d1) ** 2
    dqq = sqrt(d.sum(axis=0))
    min_ind = dqq.argmin()
    mu = psi[:, min_ind]
    maxiter = 501
    tt = 1
    lvm = zeros(maxiter)
    vec = zeros((T, n))
    stp = .3
    itr = 0

    for i in range(0,n):
        out, theta = geo.inv_exp_map(mu,psi[:,i])
        vec[:,i] = out

    vbar = vec.mean(axis=1)
    lvm[itr] = geo.L2norm(vbar)

    while (lvm[itr] > 0.00000001) and (itr<maxiter):
        mu = geo.exp_map(mu, stp*vbar)
        itr += 1
        for i in range(0,n):
            out, theta = geo.inv_exp_map(mu,psi[:,i])
            vec[:,i] = out

        vbar = vec.mean(axis=1)
        lvm[itr] = geo.L2norm(vbar)


    gam_mu = cumtrapz(mu*mu, time, initial=0)
    gam_mu = (gam_mu - gam_mu.min()) / (gam_mu.max() - gam_mu.min())

    return mu, gam_mu, psi, vec
コード例 #6
0
def SqrtMedian(gam):
    """
    calculates the median srsf of warping functions with corresponding shooting vectors

    :param gam: numpy ndarray of shape (M,N) of M warping functions
                with N samples

    :rtype: 2 numpy ndarray and vector
    :return gam_median: Karcher median warping function
    :return psi_meidan: vector of dim N which is the Karcher median srsf function
    :return psi: numpy ndarray of shape (M,N) of M SRSF of the warping functions
    :return vec: numpy ndarray of shape (M,N) of M shooting vectors

    """

    (T, n) = gam.shape
    time = linspace(0, 1, T)

    # Initialization
    psi_median = ones(T)
    r = 1
    stp = 0.3
    maxiter = 501
    vbar_norm = zeros(maxiter + 1)

    # compute psi function
    binsize = mean(diff(time))
    psi = zeros((T, n))
    v = zeros((T, n))
    vtil = zeros((T, n))
    d = zeros(n)
    dtil = zeros(n)
    for k in range(0, n):
        psi[:, k] = sqrt(gradient(gam[:, k], binsize))
        v[:, k], d[k] = geo.inv_exp_map(psi_median, psi[:, k])
        vtil[:, k] = v[:, k] / d[k]
        dtil[k] = 1 / d[k]

    vbar = vtil.sum(axis=1) * dtil.sum()**(-1)
    vbar_norm[r] = geo.L2norm(vbar)

    # compute phase median by iterative algorithm
    while (vbar_norm[r] > 0.00000001) and (r < maxiter):
        psi_median = geo.exp_map(psi_median, stp * vbar)
        r += 1
        for k in range(0, n):
            v[:, k], tmp = geo.inv_exp_map(psi_median, psi[:, k])
            d[k] = arccos(geo.inner_product(psi_median, psi[:, k]))
            vtil[:, k] = v[:, k] / d[k]
            dtil[k] = 1 / d[k]

        vbar = vtil.sum(axis=1) * dtil.sum()**(-1)
        vbar_norm[r] = geo.L2norm(vbar)

    vec = v
    gam_median = cumtrapz(psi_median**2, time, initial=0.0)

    return gam_median, psi_median, psi, vec
コード例 #7
0
def SqrtMeanInverse(gam):
    """
    finds the inverse of the mean of the set of the diffeomorphisms gamma

    :param gam: numpy ndarray of shape (M,N) of M warping functions
                with N samples

    :rtype: vector
    :return gamI: inverse of gam


    """
    (T,n) = gam.shape
    time = linspace(0,1,T)
    binsize = mean(diff(time))
    psi = zeros((T, n))
    for k in range(0, n):
        psi[:, k] = sqrt(gradient(gam[:, k],binsize))

    # Find Direction
    mnpsi = psi.mean(axis=1)
    a = mnpsi.repeat(n)
    d1 = a.reshape(T, n)
    d = (psi - d1) ** 2
    dqq = sqrt(d.sum(axis=0))
    min_ind = dqq.argmin()
    mu = psi[:, min_ind]
    maxiter = 501
    tt = 1
    lvm = zeros(maxiter)
    vec = zeros((T, n))
    stp = .3
    itr = 0

    for i in range(0,n):
        out, theta = geo.inv_exp_map(mu,psi[:,i])
        vec[:,i] = out

    vbar = vec.mean(axis=1)
    lvm[itr] = geo.L2norm(vbar)

    while (lvm[itr] > 0.00000001) and (itr<maxiter):
        mu = geo.exp_map(mu, stp*vbar)
        itr += 1
        for i in range(0,n):
            out, theta = geo.inv_exp_map(mu,psi[:,i])
            vec[:,i] = out
        
        vbar = vec.mean(axis=1)
        lvm[itr] = geo.L2norm(vbar)
    

    gam_mu = cumtrapz(mu*mu, time, initial=0)
    gam_mu = (gam_mu - gam_mu.min()) / (gam_mu.max() - gam_mu.min())
    gamI = invertGamma(gam_mu)
    return gamI
コード例 #8
0
def SqrtMeanInverse(gam):
    """
    finds the inverse of the mean of the set of the diffeomorphisms gamma

    :param gam: numpy ndarray of shape (M,N) of M warping functions
                with N samples

    :rtype: vector
    :return gamI: inverse of gam


    """
    (T,n) = gam.shape
    time = linspace(0,1,T)
    binsize = mean(diff(time))
    psi = zeros((T, n))
    for k in range(0, n):
        psi[:, k] = sqrt(gradient(gam[:, k],binsize))

    # Find Direction
    mnpsi = psi.mean(axis=1)
    a = mnpsi.repeat(n)
    d1 = a.reshape(T, n)
    d = (psi - d1) ** 2
    dqq = sqrt(d.sum(axis=0))
    min_ind = dqq.argmin()
    mu = psi[:, min_ind]
    maxiter = 501
    tt = 1
    lvm = zeros(maxiter)
    vec = zeros((T, n))
    stp = .3
    itr = 0

    for i in range(0,n):
        out, theta = geo.inv_exp_map(mu,psi[:,i])
        vec[:,i] = out

    vbar = vec.mean(axis=1)
    lvm[itr] = geo.L2norm(vbar)

    while (lvm[itr] > 0.00000001) and (itr<maxiter):
        mu = geo.exp_map(mu, stp*vbar)
        itr += 1
        for i in range(0,n):
            out, theta = geo.inv_exp_map(mu,psi[:,i])
            vec[:,i] = out

        vbar = vec.mean(axis=1)
        lvm[itr] = geo.L2norm(vbar)


    gam_mu = cumtrapz(mu*mu, time, initial=0)
    gam_mu = (gam_mu - gam_mu.min()) / (gam_mu.max() - gam_mu.min())
    gamI = invertGamma(gam_mu)
    return gamI
コード例 #9
0
def rgam(N, sigma, num, mu_gam=None):
    """
    Generates random warping functions

    :param N: length of warping function
    :param sigma: variance of warping functions
    :param num: number of warping functions
    :param mu_gam mean warping function (default identity)
    :return: gam: numpy ndarray of warping functions

    """
    gam = zeros((N, num))

    time = linspace(0, 1, N)
    binsize = diff(time)
    binsize = binsize.mean()
    if mu_gam is None:
        mu = sqrt(gradient(time,binsize))
    else:
        mu = sqrt(gradient(mu_gam,binsize))

    omega = (2 * pi)
    for k in range(0, num):
        alpha_i = rn.normal(scale=sigma)
        v = alpha_i * ones(N)
        cnt = 1
        for l in range(2, 4):
            alpha_i = rn.normal(scale=sigma)
            
            #odd
            if l % 2 != 0:
                v = v + alpha_i * sqrt(2) * cos(cnt * omega * time)
                cnt += 1

            #even
            if l % 2 == 0:
                v = v + alpha_i * sqrt(2) * sin(cnt * omega * time)

        psi = geo.exp_map(mu.ravel(),v.ravel())
        gam0 = cumtrapz(psi*psi, time, initial=0)
        gam[:, k] = (gam0 - gam0.min()) / (gam0.max() - gam0.min())

    return gam
コード例 #10
0
def jointfPCAd(qn, vec, C, m, mu_psi, parallel, cores):
    (M, N) = qn.shape
    g = np.vstack((qn, C * vec))

    mu_q = qn.mean(axis=1)
    mu_g = g.mean(axis=1)

    K = np.cov(g)
    U, s, V = svd(K)

    a = np.zeros((N, m))
    for i in range(0, N):
        for j in range(0, m):
            tmp = (g[:, i] - mu_g)
            a[i, j] = np.dot(tmp.T, U[:, j])

    qhat = np.tile(mu_q, (N, 1))
    qhat = qhat.T
    qhat = qhat + np.dot(U[0:M, 0:m], a.T)

    vechat = np.dot(U[M:, 0:m], a.T / C)
    psihat = np.zeros((M - 1, N))
    gamhat = np.zeros((M - 1, N))
    if parallel:
        out = Parallel(n_jobs=cores)(delayed(jfpca_sub)(mu_psi, vechat[:, n])
                                     for n in range(N))
        gamhat = np.array(out)
        gamhat = gamhat.transpose()
    else:
        for ii in range(0, N):
            psihat[:, ii] = geo.exp_map(mu_psi, vechat[:, ii])
            gam_tmp = cumtrapz(psihat[:, ii] * psihat[:, ii],
                               np.linspace(0, 1, M - 1),
                               initial=0)
            gamhat[:, ii] = (gam_tmp - gam_tmp.min()) / (gam_tmp.max() -
                                                         gam_tmp.min())

    U = U[:, 0:m]
    s = s[0:m]

    return qhat, gamhat, a, U, s, mu_g, g, K
コード例 #11
0
    def joint_gauss_model(self, n=1, no=3):
        """
        This function models the functional data using a joint Gaussian model
        extracted from the principal components of the srsfs

        :param n: number of random samples
        :param no: number of principal components (default = 3)
        :type n: integer
        :type no: integer
        """

        # Parameters
        fn = self.fn
        time = self.time
        qn = self.qn
        gam = self.gam

        M = time.size

        # Perform PCA
        jfpca = fpca.fdajpca(self)
        jfpca.calc_fpca(no=no)
        s = jfpca.latent
        U = jfpca.U
        C = jfpca.C
        mu_psi = jfpca.mu_psi

        # compute mean and covariance
        mq_new = qn.mean(axis=1)
        mididx = jfpca.id
        m_new = np.sign(fn[mididx, :]) * np.sqrt(np.abs(fn[mididx, :]))
        mqn = np.append(mq_new, m_new.mean())

        # generate random samples
        vals = np.random.multivariate_normal(np.zeros(s.shape), np.diag(s), n)

        tmp = np.matmul(U, np.transpose(vals))
        qhat = np.tile(mqn.T, (n, 1)).T + tmp[0:M + 1, :]
        tmp = np.matmul(U, np.transpose(vals) / C)
        vechat = tmp[(M + 1):, :]
        psihat = np.zeros((M, n))
        gamhat = np.zeros((M, n))
        for ii in range(n):
            psihat[:, ii] = geo.exp_map(mu_psi, vechat[:, ii])
            gam_tmp = cumtrapz(psihat[:, ii]**2,
                               np.linspace(0, 1, M),
                               initial=0.0)
            gamhat[:, ii] = (gam_tmp - gam_tmp.min()) / (gam_tmp.max() -
                                                         gam_tmp.min())

        ft = np.zeros((M, n))
        fhat = np.zeros((M, n))
        for ii in range(n):
            fhat[:, ii] = uf.cumtrapzmid(
                time, qhat[0:M, ii] * np.fabs(qhat[0:M, ii]),
                np.sign(qhat[M, ii]) * (qhat[M, ii] * qhat[M, ii]), mididx)
            ft[:, ii] = uf.warp_f_gamma(np.linspace(0, 1, M), fhat[:, ii],
                                        gamhat[:, ii])

        self.rsamps = True
        self.fs = fhat
        self.gams = gamhat
        self.ft = ft
        self.qs = qhat[0:M, :]

        return
コード例 #12
0
ファイル: fPCA.py プロジェクト: jdtuck/fdasrsf_python
def jointfPCA(fn, time, qn, q0, gam, no=2, showplot=True):
    """
    This function calculates joint functional principal component analysis
    on aligned data

    :param fn: numpy ndarray of shape (M,N) of N aligned functions with M
               samples
    :param time: vector of size N describing the sample points
    :param qn: numpy ndarray of shape (M,N) of N aligned SRSF with M samples
    :param no: number of components to extract (default = 2)
    :param showplot: Shows plots of results using matplotlib (default = T)
    :type showplot: bool
    :type no: int

    :rtype: tuple of numpy ndarray
    :return q_pca: srsf principal directions
    :return f_pca: functional principal directions
    :return latent: latent values
    :return coef: coefficients
    :return U: eigenvectors

    """
    coef = np.arange(-1., 2.)
    Nstd = coef.shape[0]

    # set up for fPCA in q-space
    mq_new = qn.mean(axis=1)
    M = time.shape[0]
    mididx = int(np.round(M / 2))
    m_new = np.sign(fn[mididx, :]) * np.sqrt(np.abs(fn[mididx, :]))
    mqn = np.append(mq_new, m_new.mean())
    qn2 = np.vstack((qn, m_new))

    # calculate vector space of warping functions
    mu_psi, gam_mu, psi, vec = uf.SqrtMean(gam)

    # joint fPCA
    C = fminbound(find_C,0,1e4,(qn2,vec,q0,no,mu_psi))
    qhat, gamhat, a, U, s, mu_g = jointfPCAd(qn2, vec, C, no, mu_psi)

    # geodesic paths
    q_pca = np.ndarray(shape=(M, Nstd, no), dtype=float)
    f_pca = np.ndarray(shape=(M, Nstd, no), dtype=float)
    
    for k in range(0, no):
        for l in range(0, Nstd):
            qhat = mqn + dot(U[0:(M+1),k],coef[l]*np.sqrt(s[k]))
            vechat = dot(U[(M+1):,k],(coef[l]*np.sqrt(s[k]))/C)
            psihat = geo.exp_map(mu_psi,vechat)
            gamhat = cumtrapz(psihat*psihat,np.linspace(0,1,M),initial=0)
            gamhat = (gamhat - gamhat.min()) / (gamhat.max() - gamhat.min())
            if (sum(vechat)==0):
                gamhat = np.linspace(0,1,M)
            
            fhat = uf.cumtrapzmid(time, qhat[0:M]*np.fabs(qhat[0:M]), np.sign(qhat[M])*(qhat[M]*qhat[M]), mididx)
            f_pca[:,l,k] = uf.warp_f_gamma(np.linspace(0,1,M), fhat, gamhat)
            q_pca[:,l,k] = uf.warp_q_gamma(np.linspace(0,1,M), qhat[0:M], gamhat)

    jfpca_results = collections.namedtuple('jfpca', ['q_pca', 'f_pca', 'latent', 'coef', 'U'])
    jfpca = jfpca_results(q_pca, f_pca, s, a, U)

    if showplot:
        CBcdict = {
            'Bl': (0, 0, 0),
            'Or': (.9, .6, 0),
            'SB': (.35, .7, .9),
            'bG': (0, .6, .5),
            'Ye': (.95, .9, .25),
            'Bu': (0, .45, .7),
            'Ve': (.8, .4, 0),
            'rP': (.8, .6, .7),
        }
        cl = sorted(CBcdict.keys())
        fig, ax = plt.subplots(2, no)
        for k in range(0, no):
            axt = ax[0, k]
            for l in range(0, Nstd):
                axt.plot(time, q_pca[0:M, l, k], color=CBcdict[cl[l]])

            axt.set_title('q domain: PD %d' % (k + 1))
            axt = ax[1, k]
            for l in range(0, Nstd):
                axt.plot(time, f_pca[:, l, k], color=CBcdict[cl[l]])

            axt.set_title('f domain: PD %d' % (k + 1))
        fig.set_tight_layout(True)

        cumm_coef = 100 * np.cumsum(s) / sum(s)
        idx = np.arange(0, s.shape[0]) + 1
        plot.f_plot(idx, cumm_coef, "Coefficient Cumulative Percentage")
        plt.xlabel("Percentage")
        plt.ylabel("Index")
        plt.show()

    return jfpca
コード例 #13
0
    def calc_fpca(self,
                  no=3,
                  stds=np.arange(-1., 2.),
                  id=None,
                  parallel=False,
                  cores=-1):
        """
        This function calculates joint functional principal component analysis
        on aligned data

        :param no: number of components to extract (default = 3)
        :param id: point to use for f(0) (default = midpoint)
        :param stds: number of standard deviations along gedoesic to compute (default = -1,0,1)
        :param parallel: run in parallel (default = F)
        :param cores: number of cores for parallel (default = -1 (all))
        :type no: int
        :type id: int
        :type parallel: bool
        :type cores: int

        :rtype: fdajpca object of numpy ndarray
        :return q_pca: srsf principal directions
        :return f_pca: functional principal directions
        :return latent: latent values
        :return coef: coefficients
        :return U: eigenvectors

        """
        fn = self.warp_data.fn
        time = self.warp_data.time
        qn = self.warp_data.qn
        q0 = self.warp_data.q0
        gam = self.warp_data.gam

        M = time.shape[0]
        if id is None:
            mididx = int(np.round(M / 2))
        else:
            mididx = id

        Nstd = stds.shape[0]

        # set up for fPCA in q-space
        mq_new = qn.mean(axis=1)
        m_new = np.sign(fn[mididx, :]) * np.sqrt(np.abs(fn[mididx, :]))
        mqn = np.append(mq_new, m_new.mean())
        qn2 = np.vstack((qn, m_new))

        # calculate vector space of warping functions
        mu_psi, gam_mu, psi, vec = uf.SqrtMean(gam, parallel, cores)

        # joint fPCA
        C = fminbound(find_C, 0, 1e4,
                      (qn2, vec, q0, no, mu_psi, parallel, cores))
        qhat, gamhat, a, U, s, mu_g, g, cov = jointfPCAd(
            qn2, vec, C, no, mu_psi, parallel, cores)

        # geodesic paths
        q_pca = np.ndarray(shape=(M, Nstd, no), dtype=float)
        f_pca = np.ndarray(shape=(M, Nstd, no), dtype=float)

        for k in range(0, no):
            for l in range(0, Nstd):
                qhat = mqn + np.dot(U[0:(M + 1), k], stds[l] * np.sqrt(s[k]))
                vechat = np.dot(U[(M + 1):, k], (stds[l] * np.sqrt(s[k])) / C)
                psihat = geo.exp_map(mu_psi, vechat)
                gamhat = cumtrapz(psihat * psihat,
                                  np.linspace(0, 1, M),
                                  initial=0)
                gamhat = (gamhat - gamhat.min()) / (gamhat.max() -
                                                    gamhat.min())
                if (sum(vechat) == 0):
                    gamhat = np.linspace(0, 1, M)

                fhat = uf.cumtrapzmid(time, qhat[0:M] * np.fabs(qhat[0:M]),
                                      np.sign(qhat[M]) * (qhat[M] * qhat[M]),
                                      mididx)
                f_pca[:, l, k] = uf.warp_f_gamma(np.linspace(0, 1, M), fhat,
                                                 gamhat)
                q_pca[:, l, k] = uf.warp_q_gamma(np.linspace(0, 1, M),
                                                 qhat[0:M], gamhat)

        self.q_pca = q_pca
        self.f_pca = f_pca
        self.latent = s[0:no]
        self.coef = a
        self.U = U[:, 0:no]
        self.mu_psi = mu_psi
        self.mu_g = mu_g
        self.id = mididx
        self.C = C
        self.time = time
        self.g = g
        self.cov = cov
        self.no = no
        self.stds = stds

        return