docstr: Find the minimum of the provided metric.
  
  Parameters
  ----------
  static : streamlines
      Reference or fixed set of streamlines.
  moving : streamlines
      Moving set of streamlines.
  mat : array
      Transformation (4, 4) matrix to start the registration. ``mat``
      is applied to moving. Default value None which means that initial
      transformation will be generated by shifting the centers of moving
      and static sets of streamlines to the origin.
  
  Returns
  -------
  map : StreamlineRegistrationMap
docstr_tok: ["Find","the","minimum","of","the","provided","metric",".","Parameters","--","--","--","--","--","static",":","streamlines","Reference","or","fixed","set","of","streamlines",".","moving",":","streamlines","Moving","set","of","streamlines",".","mat",":","array","Transformation","(","4",",","4",")","matrix","to","start","the","registration",".","``","mat","``","is","applied","to","moving",".","Default","value","None","which","means","that","initial","transformation","will","be","generated","by","shifting","the","centers","of","moving","and","static","sets","of","streamlines","to","the","origin",".","Returns","--","--","--","-","map",":","StreamlineRegistrationMap"]
code: def optimize(self, static, moving, mat=None):
      """Find the minimum of the provided metric.
  
      Parameters
      ----------
      static : streamlines
          Reference or fixed set of streamlines.
      moving : streamlines
          Moving set of streamlines.
      mat : array
          Transformation (4, 4) matrix to start the registration. ``mat``
          is applied to moving. Default value None which means that initial
          transformation will be generated by shifting the centers of moving
          and static sets of streamlines to the origin.
  
      Returns
      -------
      map : StreamlineRegistrationMap
  
      """
      msg = "need to have the same number of points. Use "
      msg += "set_number_of_points from dipy.tracking.streamline"
  
      if not np.all(
          np.array(list(map(len, static))) == static[0].shape[0]
      ):
          raise ValueError("Static streamlines " + msg)
  
      if not np.all(
          np.array(list(map(len, moving))) == moving[0].shape[0]
      ):
          raise ValueError("Moving streamlines " + msg)
  
      if not np.all(
          np.array(list(map(len, moving))) == static[0].shape[0]
      ):
          raise ValueError("Static and moving streamlines " + msg)
  
      if mat is None:
          static_centered, static_shift = center_streamlines(static)
          moving_centered, moving_shift = center_streamlines(moving)
          static_mat = compose_matrix44(
              [
                  static_shift[0],
                  static_shift[1],
                  static_shift[2],
                  0,
                  0,
                  0,
              ]
          )
  
          moving_mat = compose_matrix44(
              [
                  -moving_shift[0],
                  -moving_shift[1],
                  -moving_shift[2],
                  0,
                  0,
                  0,
              ]
          )
      else:
          static_centered = static
          moving_centered = transform_streamlines(moving, mat)
          static_mat = np.eye(4)
          moving_mat = mat
  
      self.metric.setup(static_centered, moving_centered)
  
      distance = self.metric.distance
  
      if self.method == "Powell":
          if self.options is None:
              self.options = {
                  "xtol": 1e-6,
                  "ftol": 1e-6,
                  "maxiter": 1e6,
              }
  
          opt = Optimizer(
              distance,
              self.x0.tolist(),
              method=self.method,
              options=self.options,
              evolution=self.evolution,
          )
  
      if self.method == "L-BFGS-B":
          if self.options is None:
              self.options = {
                  "maxcor": 10,
                  "ftol": 1e-7,
                  "gtol": 1e-5,
                  "eps": 1e-8,
                  "maxiter": 100,
              }
  
          opt = Optimizer(
              distance,
              self.x0.tolist(),
              method=self.method,
              bounds=self.bounds,
              options=self.options,
              evolution=self.evolution,
          )
      if self.verbose:
          opt.print_summary()
  
      opt_mat = compose_matrix44(opt.xopt)
  
      mat = compose_transformations(moving_mat, opt_mat, static_mat)
  
      mat_history = []
  
      if opt.evolution is not None:
          for vecs in opt.evolution:
              mat_history.append(
                  compose_transformations(
                      moving_mat, compose_matrix44(vecs), static_mat
                  )
              )
  
      # If we are running halfway streamline linear registration (for
      # groupwise registration or atlasing) the registration map is different
      if isinstance(self.metric, JointBundleMinDistanceMetric):
          srm = JointStreamlineRegistrationMap(
              opt.xopt, opt.fopt, mat_history, opt.nfev, opt.nit
          )
      else:
          srm = StreamlineRegistrationMap(
              mat, opt.xopt, opt.fopt, mat_history, opt.nfev, opt.nit
          )
  
      del opt
      return srm
  
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 2 for calling the StreamlineLinearRegistration obj's underlying member method code with example usage: obj.optimize(static, moving, mat) and returns: srm