//  [python]
def online_reconstruct(self, all_features, A_aug_matrix, skip_connections=None):
        h = self.config['history']

        # Compute A
        bs, n, m = all_features.shape
        reco_vectors = torch.zeros((bs, n, m), dtype=all_features.dtype, device=all_features.device)
        # Define Y_his
        Y_his = all_features[:, :, :self.n_points_A]  # Y_his has n_points_A columns, indexed from 0 to n_points_A - 1
        # Define Y_h and Yh from Y_his
        Y_h, Yh = build_shifted_matrices(Y=Y_his, h=h)
        # Verify that Y_h and Yh are correct
        # Between two row blocks of Y_h, the columns should be shifted.  OK
        reco_vectors[:, :, :self.n_points_A] = Y_his
        rho = 1 / self.config['lam_prox']
        # Compute P_b_inv for this Y_h and Yh
        P = Y_h @ Y_h.transpose(1, 2) + rho * batch_eye(n=h * n, bs=1, device=all_features.device)
        L = torch.cholesky(P)
        P_inv = torch.cholesky_solve(batch_eye(n=h * n, bs=1, device=all_features.device), L)

        # Compute A_prox with history
        A_prox = A_aug_matrix
        # Build history vector
        history_vector = torch.zeros((bs, n * h, 1), dtype=all_features.dtype, device=all_features.device)
        for r in range(h):
            history_vector[:, r * n:(r + 1) * n, :] = Y_his[:, :, - h + r].view((-1, n, 1))
        next_pred = A_prox @ history_vector

        reco_vectors[:, :, self.n_points_A] = next_pred.reshape((-1, n))
        if not self.config['online_update_horizon']:
            for i in range(self.n_points_A + 1, m):
                Y_his = all_features[:, :, :i]
                y1 = torch.zeros((bs, h * n, 1), dtype=all_features.dtype, device=all_features.device)
                for r in range(h):
                    y1[:, r * n:(r + 1) * n, :] = Y_his[:, :, i + r - h - 1].reshape((-1, n, 1))
                y2 = Y_his[:, :, i - 1].view((-1, n, 1))
                A_prox, P_inv = self.ddmd.update(A_start=A_prox, Y1=Y_h, Y2=Yh, y1=y1, y2=y2, P_inv_start=P_inv, h=h)
                Y_his = all_features[:, :, :i]
                # Build history vector
                history_vector = torch.zeros((bs, n * h, 1), dtype=all_features.dtype, device=all_features.device)
                for r in range(h):
                    history_vector[:, r * n:(r + 1) * n, :] = Y_his[:, :, - h + r].reshape((-1, n, 1))
                Y_h, Yh = build_shifted_matrices(Y=Y_his, h=h)
                reco_vectors[:, :, i] = (A_prox @ history_vector).reshape((-1, n))
        else:
            # Up until self.config['online_update_horizon'], update matrix and predict only next frame
            for i in range(self.n_points_A + 1, self.n_points_A + self.config['online_update_horizon']):
                Y_his = all_features[:, :, :i]
                y1 = torch.zeros((bs, h * n, 1), dtype=all_features.dtype, device=all_features.device)
                for r in range(h):
                    y1[:, r * n:(r + 1) * n, :] = Y_his[:, :, i + r - h - 1].reshape((-1, n, 1))
                y2 = Y_his[:, :, i - 1].view((-1, n, 1))
                A_prox, P_inv = self.ddmd.update(A_start=A_prox, Y1=Y_h, Y2=Yh, y1=y1, y2=y2, P_inv_start=P_inv, h=h)
                Y_his = all_features[:, :, :i]
                # Build history vector
                history_vector = torch.zeros((bs, n * h, 1), dtype=all_features.dtype, device=all_features.device)
                for r in range(h):
                    history_vector[:, r * n:(r + 1) * n, :] = Y_his[:, :, - h + r].reshape((-1, n, 1))
                Y_h, Yh = build_shifted_matrices(Y=Y_his, h=h)
                reco_vectors[:, :, i] = (A_prox @ history_vector).reshape((-1, n))
            # From self.config['online_update_horizon'], do recursive prediction without update, with the last obtained A
            for i in range(self.n_points_A + self.config['online_update_horizon'], m):
                history_vector = torch.zeros((bs, h * self.n_reduced, 1), dtype=all_features.dtype,
                                             device=all_features.device)
                for t in range(h):
                    history_vector[:, t * self.n_reduced:(t + 1) * self.n_reduced, :] = reco_vectors[:, :, i -h + t].view(
                        (bs, self.n_reduced, 1))
                reco_vectors[:, :, i] = (
                    torch.bmm(A_prox, history_vector).view((bs, self.n_reduced)))



        all_features_dict = dict()
        if self.config['dtype'] == 'float':
            all_features_dict['latent'] = reco_vectors.transpose(1, 2).float()  # of shape (bs, m, self.n_reduced)
        else:
            all_features_dict['latent'] = reco_vectors.transpose(1, 2)
        #import pdb;pdb.set_trace()
        x_reco = self.decode(all_features_dict)
        reco = dict()
        reco['features'] = all_features_dict['latent']  # of shape (bs, m, self.n_reduced) Advanced features
        reco['A_matrix'] = A_prox
        reco['x'] = x_reco
        return reco