docstr: Linear registration of 2 sets of streamlines [Garyfallidis15]_.
  
  Parameters
  ----------
  metric : StreamlineDistanceMetric,
      If None and fast is False then the BMD distance is used. If fast
      is True then a faster implementation of BMD is used. Otherwise,
      use the given distance metric.
  
  x0 : array or int or str
      Initial parametrization for the optimization.
  
      If 1D array with:
          a) 6 elements then only rigid registration is performed with
          the 3 first elements for translation and 3 for rotation.
          b) 7 elements also isotropic scaling is performed (similarity).
          c) 12 elements then translation, rotation (in degrees),
          scaling and shearing is performed (affine).
  
          Here is an example of x0 with 12 elements:
          ``x0=np.array([0, 10, 0, 40, 0, 0, 2., 1.5, 1, 0.1, -0.5, 0])``
  
          This has translation (0, 10, 0), rotation (40, 0, 0) in
          degrees, scaling (2., 1.5, 1) and shearing (0.1, -0.5, 0).
  
      If int:
          a) 6
              ``x0 = np.array([0, 0, 0, 0, 0, 0])``
          b) 7
              ``x0 = np.array([0, 0, 0, 0, 0, 0, 1.])``
          c) 12
              ``x0 = np.array([0, 0, 0, 0, 0, 0, 1., 1., 1, 0, 0, 0])``
  
      If str:
          a) "rigid"
              ``x0 = np.array([0, 0, 0, 0, 0, 0])``
          b) "similarity"
              ``x0 = np.array([0, 0, 0, 0, 0, 0, 1.])``
          c) "affine"
              ``x0 = np.array([0, 0, 0, 0, 0, 0, 1., 1., 1, 0, 0, 0])``
  
  method : str,
      'L_BFGS_B' or 'Powell' optimizers can be used. Default is
      'L_BFGS_B'.
  
  bounds : list of tuples or None,
      If method == 'L_BFGS_B' then we can use bounded optimization.
      For example for the six parameters of rigid rotation we can set
      the bounds = [(-30, 30), (-30, 30), (-30, 30),
                    (-45, 45), (-45, 45), (-45, 45)]
      That means that we have set the bounds for the three translations
      and three rotation axes (in degrees).
  
  verbose : bool, optional.
      If True, if True then information about the optimization is shown.
      Default: False.
  
  options : None or dict,
      Extra options to be used with the selected method.
  
  evolution : boolean
      If True save the transformation for each iteration of the
      optimizer. Default is False. Supported only with Scipy >= 0.11.
  
  num_threads : int, optional
      Number of threads to be used for OpenMP parallelization. If None
      (default) the value of OMP_NUM_THREADS environment variable is used
      if it is set, otherwise all available threads are used. If < 0 the
      maximal number of threads minus |num_threads + 1| is used (enter -1
      to use as many threads as possible). 0 raises an error. Only
      metrics using OpenMP will use this variable.
  
  References
  ----------
  .. [Garyfallidis15] Garyfallidis et al. "Robust and efficient linear
     registration of white-matter fascicles in the space of streamlines",
     NeuroImage, 117, 124--140, 2015
  
  .. [Garyfallidis14] Garyfallidis et al., "Direct native-space fiber
     bundle alignment for group comparisons", ISMRM, 2014.
  
  .. [Garyfallidis17] Garyfallidis et al. Recognition of white matter
     bundles using local and global streamline-based
     registration and clustering, Neuroimage, 2017.
docstr_tok: ["Linear","registration","of","2","sets","of","streamlines","[","Garyfallidis15","]","_.","Parameters","--","--","--","--","--","metric",":","StreamlineDistanceMetric",",","If","None","and","fast","is","False","then","the","BMD","distance","is","used",".","If","fast","is","True","then","a","faster","implementation","of","BMD","is","used",".","Otherwise",",","use","the","given","distance","metric",".","x0",":","array","or","int","or","str","Initial","parametrization","for","the","optimization",".","If","1D","array","with",":","a",")","6","elements","then","only","rigid","registration","is","performed","with","the","3","first","elements","for","translation","and","3","for","rotation",".","b",")","7","elements","also","isotropic","scaling","is","performed","(","similarity",")",".","c",")","12","elements","then","translation",",","rotation","(","in","degrees",")",",","scaling","and","shearing","is","performed","(","affine",")",".","Here","is","an","example","of","x0","with","12","elements",":","``","x0=np.array","(","[","0",",","10",",","0",",","40",",","0",",","0",",","2.",",","1.5",",","1",",","0.1",",","-0.5",",","0","]",")","``","This","has","translation","(","0",",","10",",","0",")",",","rotation","(","40",",","0",",","0",")","in","degrees",",","scaling","(","2.",",","1.5",",","1",")","and","shearing","(","0.1",",","-0.5",",","0",")",".","If","int",":","a",")","6","``","x0","=","np.array","(","[","0",",","0",",","0",",","0",",","0",",","0","]",")","``","b",")","7","``","x0","=","np.array","(","[","0",",","0",",","0",",","0",",","0",",","0",",","1",".","]",")","``","c",")","12","``","x0","=","np.array","(","[","0",",","0",",","0",",","0",",","0",",","0",",","1.",",","1.",",","1",",","0",",","0",",","0","]",")","``","If","str",":","a",")","``","rigid","''","``","x0","=","np.array","(","[","0",",","0",",","0",",","0",",","0",",","0","]",")","``","b",")","``","similarity","''","``","x0","=","np.array","(","[","0",",","0",",","0",",","0",",","0",",","0",",","1",".","]",")","``","c",")","``","affine","''","``","x0","=","np.array","(","[","0",",","0",",","0",",","0",",","0",",","0",",","1.",",","1.",",","1",",","0",",","0",",","0","]",")","``","method",":","str",",","'L_BFGS_B","'","or","'Powell","'","optimizers","can","be","used",".","Default","is","'L_BFGS_B","'",".","bounds",":","list","of","tuples","or","None",",","If","method","==","'L_BFGS_B","'","then","we","can","use","bounded","optimization",".","For","example","for","the","six","parameters","of","rigid","rotation","we","can","set","the","bounds","=","[","(","-30",",","30",")",",","(","-30",",","30",")",",","(","-30",",","30",")",",","(","-45",",","45",")",",","(","-45",",","45",")",",","(","-45",",","45",")","]","That","means","that","we","have","set","the","bounds","for","the","three","translations","and","three","rotation","axes","(","in","degrees",")",".","verbose",":","bool",",","optional",".","If","True",",","if","True","then","information","about","the","optimization","is","shown",".","Default",":","False",".","options",":","None","or","dict",",","Extra","options","to","be","used","with","the","selected","method",".","evolution",":","boolean","If","True","save","the","transformation","for","each","iteration","of","the","optimizer",".","Default","is","False",".","Supported","only","with","Scipy",">","=","0.11.","num_threads",":","int",",","optional","Number","of","threads","to","be","used","for","OpenMP","parallelization",".","If","None","(","default",")","the","value","of","OMP_NUM_THREADS","environment","variable","is","used","if","it","is","set",",","otherwise","all","available","threads","are","used",".","If","<","0","the","maximal","number","of","threads","minus","|num_threads","+","1|","is","used","(","enter","-1","to","use","as","many","threads","as","possible",")",".","0","raises","an","error",".","Only","metrics","using","OpenMP","will","use","this","variable",".","References","--","--","--","--","--","..","[","Garyfallidis15","]","Garyfallidis","et","al",".","``","Robust","and","efficient","linear","registration","of","white-matter","fascicles","in","the","space","of","streamlines","''",",","NeuroImage",",","117",",","124","--","140",",","2015","..","[","Garyfallidis14","]","Garyfallidis","et","al.",",","``","Direct","native-space","fiber","bundle","alignment","for","group","comparisons","''",",","ISMRM",",","2014",".","..","[","Garyfallidis17","]","Garyfallidis","et","al",".","Recognition","of","white","matter","bundles","using","local","and","global","streamline-based","registration","and","clustering",",","Neuroimage",",","2017","."]
code: def __init__(
      self,
      metric=None,
      x0="rigid",
      method="L-BFGS-B",
      bounds=None,
      verbose=False,
      options=None,
      evolution=False,
      num_threads=None,
  ):
      r"""Linear registration of 2 sets of streamlines [Garyfallidis15]_.
  
      Parameters
      ----------
      metric : StreamlineDistanceMetric,
          If None and fast is False then the BMD distance is used. If fast
          is True then a faster implementation of BMD is used. Otherwise,
          use the given distance metric.
  
      x0 : array or int or str
          Initial parametrization for the optimization.
  
          If 1D array with:
              a) 6 elements then only rigid registration is performed with
              the 3 first elements for translation and 3 for rotation.
              b) 7 elements also isotropic scaling is performed (similarity).
              c) 12 elements then translation, rotation (in degrees),
              scaling and shearing is performed (affine).
  
              Here is an example of x0 with 12 elements:
              ``x0=np.array([0, 10, 0, 40, 0, 0, 2., 1.5, 1, 0.1, -0.5, 0])``
  
              This has translation (0, 10, 0), rotation (40, 0, 0) in
              degrees, scaling (2., 1.5, 1) and shearing (0.1, -0.5, 0).
  
          If int:
              a) 6
                  ``x0 = np.array([0, 0, 0, 0, 0, 0])``
              b) 7
                  ``x0 = np.array([0, 0, 0, 0, 0, 0, 1.])``
              c) 12
                  ``x0 = np.array([0, 0, 0, 0, 0, 0, 1., 1., 1, 0, 0, 0])``
  
          If str:
              a) "rigid"
                  ``x0 = np.array([0, 0, 0, 0, 0, 0])``
              b) "similarity"
                  ``x0 = np.array([0, 0, 0, 0, 0, 0, 1.])``
              c) "affine"
                  ``x0 = np.array([0, 0, 0, 0, 0, 0, 1., 1., 1, 0, 0, 0])``
  
      method : str,
          'L_BFGS_B' or 'Powell' optimizers can be used. Default is
          'L_BFGS_B'.
  
      bounds : list of tuples or None,
          If method == 'L_BFGS_B' then we can use bounded optimization.
          For example for the six parameters of rigid rotation we can set
          the bounds = [(-30, 30), (-30, 30), (-30, 30),
                        (-45, 45), (-45, 45), (-45, 45)]
          That means that we have set the bounds for the three translations
          and three rotation axes (in degrees).
  
      verbose : bool, optional.
          If True, if True then information about the optimization is shown.
          Default: False.
  
      options : None or dict,
          Extra options to be used with the selected method.
  
      evolution : boolean
          If True save the transformation for each iteration of the
          optimizer. Default is False. Supported only with Scipy >= 0.11.
  
      num_threads : int, optional
          Number of threads to be used for OpenMP parallelization. If None
          (default) the value of OMP_NUM_THREADS environment variable is used
          if it is set, otherwise all available threads are used. If < 0 the
          maximal number of threads minus |num_threads + 1| is used (enter -1
          to use as many threads as possible). 0 raises an error. Only
          metrics using OpenMP will use this variable.
  
      References
      ----------
      .. [Garyfallidis15] Garyfallidis et al. "Robust and efficient linear
         registration of white-matter fascicles in the space of streamlines",
         NeuroImage, 117, 124--140, 2015
  
      .. [Garyfallidis14] Garyfallidis et al., "Direct native-space fiber
         bundle alignment for group comparisons", ISMRM, 2014.
  
      .. [Garyfallidis17] Garyfallidis et al. Recognition of white matter
         bundles using local and global streamline-based
         registration and clustering, Neuroimage, 2017.
  
      """
      self.x0 = self._set_x0(x0)
      self.metric = metric
  
      if self.metric is None:
          self.metric = BundleMinDistanceMetric(num_threads=num_threads)
  
      self.verbose = verbose
      self.method = method
      if self.method not in ["Powell", "L-BFGS-B"]:
          raise ValueError("Only Powell and L-BFGS-B can be used")
      self.bounds = bounds
      self.options = options
      self.evolution = evolution
  
imports: import logging
  import abc
  from itertools import combinations
  import numpy
  from dipy.core.optimize import Optimizer
  from dipy.align.bundlemin import _bundle_minimum_distance, _bundle_minimum_distance_asymmetric, distance_matrix_mdf
  from dipy.tracking.streamline import transform_streamlines, unlist_streamlines, center_streamlines, set_number_of_points, select_random_set_of_streamlines, length, Streamlines
  from dipy.segment.clustering import qbx_and_merge
  from dipy.core.geometry import compose_transformations, compose_matrix, decompose_matrix
  from time import time
label_desc: Use image node_id 1 to create a new StreamlineLinearRegistration object  with example: obj = StreamlineLinearRegistration(metric, x0, method, bounds, verbose, options, evolution, num_threads)