def transform(self, X, y=None, scan_onsets=None):
        """ Use the model to estimate the time course of response to
            each condition (ts), and the time course unrelated to task
            (ts0) which is spread across the brain.
            This is equivalent to "decoding" the design matrix and
            nuisance regressors from a new dataset different from the
            training dataset on which fit() was applied. An AR(1) smooth
            prior is imposed on the decoded ts and ts0 with the AR(1)
            parameters learnt from the corresponding time courses in the
            training data.
            Notice: if you set the rank to be lower than the number of
            experimental conditions (number of columns in the design
            matrix), the recovered task-related activity will have
            collinearity (the recovered time courses of some conditions
            can be linearly explained by the recovered time courses
            of other conditions).

        Parameters
        ----------
        X : numpy arrays, shape=[time_points, voxels]
            fMRI data of new data of the same subject. The voxels should
            match those used in the fit() function. If data are z-scored
            (recommended) when fitting the model, data should be z-scored
            as well when calling transform()
        y : not used (as it is unsupervised learning)
        scan_onsets : numpy array, shape=[number of runs].
            A list of indices corresponding to the onsets of
            scans in the data X. If not provided, data will be assumed
            to be acquired in a continuous scan.
        Returns
        -------
        ts : numpy arrays, shape = [time_points, condition]
            The estimated response to the task conditions which have the
            response amplitudes estimated during the fit step.
        ts0: numpy array, shape = [time_points, n_nureg]
            The estimated time course spread across the brain, with the
            loading weights estimated during the fit step.
        """

        assert X.ndim == 2 and X.shape[1] == self.beta_.shape[1], \
            'The shape of X is not consistent with the shape of data '\
            'used in the fitting step. They should have the same number '\
            'of voxels'
        assert scan_onsets is None or (scan_onsets.ndim == 1 and
                                       0 in scan_onsets), \
            'scan_onsets should either be None or an array of indices '\
            'If it is given, it should include at least 0'

        if scan_onsets is None:
            scan_onsets = np.array([0], dtype=int)
        else:
            scan_onsets = np.int32(scan_onsets)
        ts, ts0, log_p = self._transform(
            Y=X, scan_onsets=scan_onsets, beta=self.beta_,
            beta0=self.beta0_, rho_e=self.rho_, sigma_e=self.sigma_,
            rho_X=self._rho_design_, sigma2_X=self._sigma2_design_,
            rho_X0=self._rho_X0_, sigma2_X0=self._sigma2_X0_)
        return ts, ts0