//  [python]
def _update_Us(self, Us, Xs, unfold_cores, n):

        T_hat = len(Xs)
        M = len(Us)
#        begin_idx = self._p + self._q

        H = self._get_H(Us, n)
        # orth in J3
        if self._Us_mode == 1:
            if n<M-1:
                As = []
                Bs = []
                for t in range(0, T_hat):
                    unfold_X = self._get_unfold_tensor(Xs[t], n)
                    As.append(torch.dot(torch.dot(unfold_X, H.T), torch.dot(unfold_X, H.T).T))
                    Bs.append(torch.dot(torch.dot(unfold_X, H.T), unfold_cores[t].T))
                a = sp.linalg.pinv(torch.sum(As, axis=0))
                b = torch.sum(Bs, axis=0)
                temp = torch.dot(a, b)
                Us[n] = temp / torch.linalg.norm(temp)
            else:
                Bs = []
                for t in range(0, T_hat):
                    unfold_X = self._get_unfold_tensor(Xs[t], n)
                    Bs.append(torch.dot(torch.dot(unfold_X, H.T), unfold_cores[t].T))
                b = torch.sum(Bs, axis=0)
                U_, S_, V_ = torch.svd(b)
                Us[n] = torch.mm(U_, V_.t())
        # orth in J1 J2
        elif self._Us_mode == 2:
            if n<M-1:
                Bs = []
                for t in range(0, T_hat):
                    unfold_X = self._get_unfold_tensor(Xs[t], n)
                    Bs.append(torch.dot(torch.dot(unfold_X, H.T), unfold_cores[t].T))
                b = torch.sum(Bs, axis=0)
                U_, S_, V_ = torch.svd(b)
                Us[n] = torch.mm(U_, V_.t())
            else:
                As = []
                Bs = []
                for t in range(0, T_hat):
                    unfold_X = self._get_unfold_tensor(Xs[t], n)
                    As.append(torch.dot(torch.dot(unfold_X, H.T), torch.dot(unfold_X, H.T).T))
                    Bs.append(torch.dot(torch.dot(unfold_X, H.T), unfold_cores[t].T))
                a = sp.linalg.pinv(torch.sum(As, axis=0))
                b = torch.sum(Bs, axis=0)
                temp = torch.dot(a, b)
                Us[n] = temp / torch.linalg.norm(temp)
        # no orth      
        elif self._Us_mode == 3:
            As = []
            Bs = []
            for t in range(0, T_hat):
                unfold_X = self._get_unfold_tensor(Xs[t], n)
                As.append(torch.dot(torch.dot(unfold_X, H.T), torch.dot(unfold_X, H.T).T))
                Bs.append(torch.dot(torch.dot(unfold_X, H.T), unfold_cores[t].T))
            a = sp.linalg.pinv(torch.sum(As, axis=0))
            b = torch.sum(Bs, axis=0)
            temp = torch.dot(a, b)
            Us[n] = temp / torch.linalg.norm(temp)
        # all orth
        elif self._Us_mode == 4:
            Bs = []
            for t in range(0, T_hat):
                unfold_X = self._get_unfold_tensor(Xs[t], n)
                # Bs.append(torch.matmul(torch.matmul(unfold_X, H.T), unfold_cores[t].T).cpu().detach().numpy())
                Bs.append(torch.matmul(torch.matmul(unfold_X, H.T), unfold_cores[t].T))
            b = torch.sum(torch.cat([torch.unsqueeze(i,0) for i in Bs], dim=0), dim=0)
            # Bs = torch.tensor(Bs)
            # b = torch.sum(Bs, axis=0)
            
            #b = b.replace(torch.inf, torch.nan).replace(-torch.inf, torch.nan).dropna()
            U_, S_, V_ = torch.svd(b)
            Us[n] = torch.mm(U_, V_.t())
        # only orth in J1
        elif self._Us_mode == 5:
            if n==0:
                Bs = []
                for t in range(0, T_hat):
                    unfold_X = self._get_unfold_tensor(Xs[t], n)
                    Bs.append(torch.dot(torch.dot(unfold_X, H.T), unfold_cores[t].T))
                b = torch.sum(Bs, axis=0)
                U_, S_, V_ = torch.svd(b)
                Us[n] = torch.mm(U_, V_.t())
            else:
                As = []
                Bs = []
                for t in range(0, T_hat):
                    unfold_X = self._get_unfold_tensor(Xs[t], n)
                    As.append(torch.dot(torch.dot(unfold_X, H.T), torch.dot(unfold_X, H.T).T))
                    Bs.append(torch.dot(torch.dot(unfold_X, H.T), unfold_cores[t].T))
                a = sp.linalg.pinv(torch.sum(As, axis=0))
                b = torch.sum(Bs, axis=0)
                temp = torch.dot(a, b)
                Us[n] = temp / torch.linalg.norm(temp)
        # only orth in J2
        elif self._Us_mode == 6:
            if n==1:
                Bs = []
                for t in range(0, T_hat):
                    unfold_X = self._get_unfold_tensor(Xs[t], n)
                    Bs.append(torch.dot(torch.dot(unfold_X, H.T), unfold_cores[t].T))
                b = torch.sum(Bs, axis=0)
                U_, S_, V_ = torch.svd(b)
                Us[n] = torch.mm(U_, V_.t())
            else:
                As = []
                Bs = []
                for t in range(0, T_hat):
                    unfold_X = self._get_unfold_tensor(Xs[t], n)
                    As.append(torch.dot(torch.dot(unfold_X, H.T), torch.dot(unfold_X, H.T).T))
                    Bs.append(torch.dot(torch.dot(unfold_X, H.T), unfold_cores[t].T))
                a = sp.linalg.pinv(torch.sum(As, axis=0))
                b = torch.sum(Bs, axis=0)
                temp = torch.dot(a, b)
                Us[n] = temp / torch.linalg.norm(temp)
        return Us