code: def _extract_t_indices(self, X, X2=None, dL_dK=None):
          
  
          # TODO: some fast checking here to see if this needs recomputing?
          self._t = X[:, 0]
          if not X.shape[1] == 2:
              raise ValueError('Input matrix for ode1 covariance should have two columns, one containing times, the other output indices')
          self._index = np.asarray(X[:, 1],dtype=np.int)
          # Sort indices so that outputs are in blocks for computational
          # convenience.
          self._order = self._index.argsort()
          self._index = self._index[self._order]
          self._t = self._t[self._order]
          self._rorder = self._order.argsort() # rorder is for reversing the order
          
          if X2 is None:
              self._t2 = None
              self._index2 = None
              self._order2 = self._order
              self._rorder2 = self._rorder
          else:
              if not X2.shape[1] == 2:
                  raise ValueError('Input matrix for ode1 covariance should have two columns, one containing times, the other output indices')
              self._t2 = X2[:, 0]
              self._index2 = np.asarray(X2[:, 1],dtype=np.int)
              self._order2 = self._index2.argsort()
              self._index2 = self._index2[self._order2]
              self._t2 = self._t2[self._order2]
              self._rorder2 = self._order2.argsort() # rorder2 is for reversing order
  
          if dL_dK is not None:
              self._dL_dK = dL_dK[self._order, :]
              self._dL_dK = self._dL_dK[:, self._order2]
docs: Extract times and output indices from the input matrix X. Times are ordered according to their index for convenience of computation, this ordering is stored in self._order and self.order2. These orderings are then mapped back to the original ordering (in X) using self._rorder and self._rorder2.