code: def _get_rotation_matrix(
      M_source,
      M_target,
      weights=None,
      metric="euclid",
      tol_step=1e-9,
      maxiter=10_000,
      maxiter_linesearch=32,
  ):
      r"""Calculate rotation matrix for the Riemannian Procustes Analysis.
  
      Get the rotation matrix Q that minimizes the loss function:
  
      .. math::
          L(Q) = \sum_i w_i delta^2(M_{target_i}, Q M_{source_i} Q^T)
  
      The solution can then be used to transform the data points from the source
      domain so that their class means are close to the those from the target
      domain. This manifold optimization problem was first defined in Eq(35) of
      [1]_. The optimization procedure follows the usual setup for optimization
      on manifolds as described in [2]_.
  
      Parameters
      ----------
      M_source : ndarray, shape (n_classes, n, n)
          Set with the means of the n_classes from the source domain.
      M_target : ndarray, shape (n_classes, n, n)
          Set with the means of the n_classes from the target domain.
      weights : None | array, shape (n_classes,), default=None
          Weights for each class. If None, then give the same weight for each
          class.
      metric : {'euclid', 'riemann'}, default='euclid'
          Which type of distance to minimize between the class means, either
          'euclid' for Euclidean distance or 'riemann' for the affine-invariant
          Riemannian distance between SPD matrices.
      tol_step : float, default 1e-9
          Stopping criterion based on the norm of the descent direction.
      maxiter : int, default=10_000
          Maximum number of iterations in the optimization procedure.
      maxiter_linesearch : int, default=32
          Maximum number of iterations in the line search procedure.
  
      Returns
      -------
      Q : ndarray, shape (n, n)
          Orthogonal matrix that minimizes the distance between the class means
          for the source and target domains.
  
      References
      ----------
      .. [1] `Riemannian Procrustes analysis: transfer
          learning for brain-computer interfaces
          <https://hal.archives-ouvertes.fr/hal-01971856>`_
          PLC Rodrigues et al, IEEE Transactions on Biomedical Engineering,
          vol. 66, no. 8, pp. 2390-2401, December, 2018
      .. [2] `An introduction to optimization on smooth manifolds
          <https://www.nicolasboumal.net/book/>`_
          N. Boumal. To appear with Cambridge University Press. June, 2022
  
      Notes
      -----
      .. versionadded:: 0.4
      """
  
      if M_source.shape[0] != M_target.shape[0]:
          raise ValueError(
              "The number of classes in each domain don't match"
          )
      if M_source.shape[1:] != M_target.shape[1:]:
          raise ValueError(
              "The number of channels in each domain don't match"
          )
  
      weights = check_weights(weights, len(M_source))
  
      # initialize the solution with an educated guess
      Q_ini = _warm_start(M_target, M_source, weights, metric=metric)
      if np.linalg.det(Q_ini) < 0:  # make sure it is a rotation
          Q_ini[[0, 1], :] = Q_ini[[1, 0], :]
  
      # run the optimization procedure on rotation matrices
      Q_posdet, F_posdet = _run_minimization(
          Q_ini,
          M_source,
          M_target,
          weights,
          metric,
          tol_step,
          maxiter,
          maxiter_linesearch,
      )
  
      # run the optimization procedure on reflection matrices
      Q_ini[[0, 1], :] = Q_ini[[1, 0], :]
      Q_negdet, F_negdet = _run_minimization(
          Q_ini,
          M_source,
          M_target,
          weights,
          metric,
          tol_step,
          maxiter,
          maxiter_linesearch,
      )
  
      # check which of the options yield a smaller loss value
      if F_posdet < F_negdet:
          return Q_posdet
      else:
          return Q_negdet
  
file_path: pyRiemann/pyriemann/transfer/_rotate.py
imports: import warnings
  import numpy
  from ..utils.distance import distance
  from ..utils.utils import check_weights
label_desc: Use image node_id 7 for calling a global function with example usage: _get_rotation_matrix(M_source, M_target, weights, metric, tol_step, maxiter, maxiter_linesearch) and returns: Q_posdet, Q_negdet