code: def _prepare_data_XYX0(self, X, Y, X_base, X_res, D, F, run_TRs,
                             no_DC=False):
          
          X_DC = self._gen_X_DC(run_TRs)
          reg_sol = np.linalg.lstsq(X_DC, X)
          if np.any(np.isclose(reg_sol[1], 0)):
              raise ValueError('Your design matrix appears to have '
                               'included baseline time series.'
                               'Either remove them, or move them to'
                               ' nuisance regressors.')
          X_DC, X_base, idx_DC = self._merge_DC_to_base(X_DC, X_base,
                                                        no_DC)
          if X_res is None:
              X0 = X_base
          else:
              X0 = np.concatenate((X_base, X_res), axis=1)
          n_X0 = X0.shape[1]
          X0TX0, X0TDX0, X0TFX0 = self._make_templates(D, F, X0, X0)
          XTX0, XTDX0, XTFX0 = self._make_templates(D, F, X, X0)
          X0TY, X0TDY, X0TFY = self._make_templates(D, F, X0, Y)
  
          return X0TX0, X0TDX0, X0TFX0, XTX0, XTDX0, XTFX0, \
              X0TY, X0TDY, X0TFY, X0, X_base, n_X0, idx_DC
docs: Prepares different forms of products between design matrix X or
              data Y or nuisance regressors X0.
              These products are re-used a lot during fitting.
              So we pre-calculate them.
              no_DC means not inserting regressors for DC components
              into nuisance regressor.
              It will only take effect if X_base is not None.