<SYSTEM_TASK:>
Solve the following problem using Python, implementing the functions described below, one line at a time
<END_TASK>
<USER_TASK:>
Description:
 def score(self, X, design, scan_onsets=None):
 """ Use the model and parameters estimated by fit function from some data of a participant to evaluate the log likelihood of some new data of the same participant. Design matrix of the same set of experimental conditions in the testing data should be provided, with each column corresponding to the same condition as that column in the design matrix of the training data. Unknown nuisance time series will be marginalized, assuming they follow the same spatial pattern as in the training data. The hypothetical response captured by the design matrix will be subtracted from data before the marginalization when evaluating the log likelihood. For null model, nothing will be subtracted before marginalization. There is a difference between the form of likelihood function used in fit() and score(). In fit(), the response amplitude beta to design matrix X and the modulation beta0 by nuisance regressor X0 are both marginalized, with X provided and X0 estimated from data. In score(), posterior estimation of beta and beta0 from the fitting step are assumed unchanged to testing data and X0 is marginalized. The logic underlying score() is to transfer as much as what we can learn from training data when calculating a likelihood score for testing data. If you z-scored your data during fit step, you should z-score them for score function as well. If you did not z-score in fitting, you should not z-score here either. 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() design : numpy array, shape=[time_points, conditions] Design matrix expressing the hypothetical response of the task conditions in data X. 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 ------- ll: float. The log likelihood of the new data based on the model and its parameters fit to the training data. ll_null: float. The log likelihood of the new data based on a null model which assumes the same as the full model for everything except for that there is no response to any of the task conditions. """


        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)
        ll = self._score(Y=X, design=design, beta=self.beta_,
                         scan_onsets=scan_onsets, beta0=self.beta0_,
                         rho_e=self.rho_, sigma_e=self.sigma_,
                         rho_X0=self._rho_X0_, sigma2_X0=self._sigma2_X0_)
        ll_null = self._score(Y=X, design=None, beta=None,
                              scan_onsets=scan_onsets, beta0=self.beta0_,
                              rho_e=self.rho_, sigma_e=self.sigma_,
                              rho_X0=self._rho_X0_,
                              sigma2_X0=self._sigma2_X0_)
        return ll, ll_null