code: def make_classification_transfer(
      n_matrices,
      class_sep=3.0,
      class_disp=1.0,
      domain_sep=5.0,
      theta=0.0,
      stretch=1.0,
      random_state=None,
      class_names=[1, 2],
  ):
      """Generate source and target toy datasets for transfer learning examples.
  
      Generate a dataset with 2x2 SPD matrices drawn from two Riemannian Gaussian
      distributions. The distributions have the same class dispersions and the
      distance between their centers of mass is an input parameter. We can
      stretch the target dataset and control a rotation matrix that maps the
      source to the target domains. This function is useful for testing
      classification or clustering methods on transfer learning applications.
  
      Parameters
      ----------
      n_matrices : int, default=100
          How many 2x2 matrices to generate for each class on each domain.
      class_sep : float, default=3.0
          Distance between the centers of the two classes.
      class_disp : float, default=1.0
          Dispersion of the data points to be sampled on each class.
      domain_sep : float, default=5.0
          Distance between the global means of each source and target datasets.
      theta : float, default=0.0
          Angle of the 2x2 rotation matrix from source to target dataset.
      stretch : float, default=1.0
          Factor to stretch the data points in target dataset. Note that when it
          is != 1.0 the class dispersions in target domain will be different than
          those in source domain (fixed at class_disp).
      random_state : None | int | RandomState instance, default=None
          Pass an int for reproducible output across multiple function calls.
      class_names : list, default=[1, 2]
          Names of classes.
  
      Returns
      -------
      X_enc : ndarray, shape (4*n_matrices, 2, 2)
          Set of SPD matrices.
      y_enc : ndarray, shape (4*n_matrices,)
          Extended labels for each data point.
  
      Notes
      -----
      .. versionadded:: 0.4
      """
  
      rs = check_random_state(random_state)
      seeds = rs.randint(100, size=4)
  
      # the examples considered here are always for 2x2 matrices
      n_dim = 2
      if len(class_names) != n_dim:
          raise ValueError("class_names must contain 2 elements")
  
      # create a source dataset with two classes and global mean at identity
      M1_source = np.eye(n_dim)  # first class mean at Identity at first
      X1_source = sample_gaussian_spd(
          n_matrices=n_matrices,
          mean=M1_source,
          sigma=class_disp,
          random_state=seeds[0],
      )
      y1_source = [class_names[0]] * n_matrices
      Pv = rs.randn(n_dim, n_dim)  # create random tangent vector
      Pv = (Pv + Pv.T) / 2  # symmetrize
      Pv /= np.linalg.norm(Pv)  # normalize
      P = expm(Pv)  # take it back to the SPD manifold
      M2_source = powm(
          P, alpha=class_sep
      )  # control distance to identity
      X2_source = sample_gaussian_spd(
          n_matrices=n_matrices,
          mean=M2_source,
          sigma=class_disp,
          random_state=seeds[1],
      )
      y2_source = [class_names[1]] * n_matrices
      X_source = np.concatenate([X1_source, X2_source])
      M_source = mean_riemann(X_source)
      M_source_invsqrt = invsqrtm(M_source)
      # center the dataset to Identity
      X_source = M_source_invsqrt @ X_source @ M_source_invsqrt
      y_source = np.concatenate([y1_source, y2_source])
  
      # create target dataset based on the source dataset
      X1_target = sample_gaussian_spd(
          n_matrices=n_matrices,
          mean=M1_source,
          sigma=class_disp,
          random_state=seeds[2],
      )
      X2_target = sample_gaussian_spd(
          n_matrices=n_matrices,
          mean=M2_source,
          sigma=class_disp,
          random_state=seeds[3],
      )
      X_target = np.concatenate([X1_target, X2_target])
      M_target = mean_riemann(X_target)
      M_target_invsqrt = invsqrtm(M_target)
      # center the dataset to Identity
      X_target = M_target_invsqrt @ X_target @ M_target_invsqrt
      y_target = np.copy(y_source)
  
      # stretch the data points in target domain if needed
      if stretch != 1.0:
          X_target = powm(X_target, alpha=stretch)
  
      # move the points in X_target with a random matrix A = P * Q
  
      # create SPD matrix for the translation between domains
      Pv = rs.randn(n_dim, n_dim)  # create random tangent vector
      Pv = (Pv + Pv.T) / 2  # symmetrize
      Pv /= np.linalg.norm(Pv)  # normalize
      P = expm(Pv)  # take it to the manifold
      P = powm(P, alpha=domain_sep)  # control distance to identity
      P = sqrtm(P)  # transport matrix
  
      # create orthogonal matrix for the rotation part
      Q = np.array(
          [
              [np.cos(theta), -np.sin(theta)],
              [np.sin(theta), np.cos(theta)],
          ]
      )
  
      # transform the data points from the target domain
      A = P @ Q
      X_target = A @ X_target @ A.T
  
      # create array specifying the domain for each epoch
      domains = np.array(
          len(X_source) * ["source_domain"]
          + len(X_target) * ["target_domain"]
      )
  
      # encode the labels and domains together
      X = np.concatenate([X_source, X_target])
      y = np.concatenate([y_source, y_target])
      X_enc, y_enc = encode_domains(X, y, domains)
  
      return X_enc, y_enc
  
file_path: pyRiemann/pyriemann/datasets/simulated.py
imports: import numpy
  from sklearn.utils.validation import check_random_state
  from ..utils.mean import mean_riemann
  from ..utils.distance import distance_riemann
  from ..utils.base import invsqrtm, powm, sqrtm, expm
  from .sampling import generate_random_spd_matrix, sample_gaussian_spd
  from ..transfer import encode_domains
  from ..utils import deprecated
label_desc: Use image node_id 6 for calling a global function with example usage: make_classification_transfer(n_matrices, class_sep, class_disp, domain_sep, theta, stretch, random_state, class_names) and returns: X_enc,  y_enc