docstr: Update marginal and joint distributions and the joint gradient.
  
  The distributions are updated according to the static and transformed
  images. The transformed image is precisely the moving image after
  transforming it by the transform defined by the `params` parameters.
  
  The gradient of the joint PDF is computed only if update_gradient
  is True.
  
  Parameters
  ----------
  params : array, shape (n,)
      the parameter vector of the transform currently used by the metric
      (the transform name is provided when self.setup is called), n is
      the number of parameters of the transform
  update_gradient : Boolean, optional
      if True, the gradient of the joint PDF will also be computed,
      otherwise, only the marginal and joint PDFs will be computed.
      The default is True.
docstr_tok: ["Update","marginal","and","joint","distributions","and","the","joint","gradient",".","The","distributions","are","updated","according","to","the","static","and","transformed","images",".","The","transformed","image","is","precisely","the","moving","image","after","transforming","it","by","the","transform","defined","by","the","`","params","`","parameters",".","The","gradient","of","the","joint","PDF","is","computed","only","if","update_gradient","is","True",".","Parameters","--","--","--","--","--","params",":","array",",","shape","(","n",",",")","the","parameter","vector","of","the","transform","currently","used","by","the","metric","(","the","transform","name","is","provided","when","self.setup","is","called",")",",","n","is","the","number","of","parameters","of","the","transform","update_gradient",":","Boolean",",","optional","if","True",",","the","gradient","of","the","joint","PDF","will","also","be","computed",",","otherwise",",","only","the","marginal","and","joint","PDFs","will","be","computed",".","The","default","is","True","."]
code: def _update_mutual_information(self, params, update_gradient=True):
      r"""Update marginal and joint distributions and the joint gradient.
  
      The distributions are updated according to the static and transformed
      images. The transformed image is precisely the moving image after
      transforming it by the transform defined by the `params` parameters.
  
      The gradient of the joint PDF is computed only if update_gradient
      is True.
  
      Parameters
      ----------
      params : array, shape (n,)
          the parameter vector of the transform currently used by the metric
          (the transform name is provided when self.setup is called), n is
          the number of parameters of the transform
      update_gradient : Boolean, optional
          if True, the gradient of the joint PDF will also be computed,
          otherwise, only the marginal and joint PDFs will be computed.
          The default is True.
  
      """
      # Get the matrix associated with the `params` parameter vector
      current_affine = self.transform.param_to_matrix(params)
      # Get the static-to-prealigned matrix (only needed for the MI gradient)
      static2prealigned = self.static_grid2world
      if self.starting_affine is not None:
          current_affine = current_affine.dot(self.starting_affine)
          static2prealigned = self.starting_affine.dot(
              static2prealigned
          )
      self.affine_map.set_affine(current_affine)
  
      # Update the histogram with the current joint intensities
      (
          static_values,
          moving_values,
          static_mask_values,
          moving_mask_values,
      ) = self._update_histogram()
  
      H = self.histogram  # Shortcut to `self.histogram`
      grad = None  # Buffer to write the MI gradient into (if needed)
      if update_gradient:
          grad = self.metric_grad
          # Compute the gradient of the joint PDF w.r.t. parameters
          if self.sampling_proportion is None:  # Dense case
              # Compute the gradient of moving img. at physical points
              # associated with the >>static image's grid<< cells
              # The image gradient must be eval. at current moved points
              grid_to_world = current_affine.dot(self.static_grid2world)
              mgrad, inside = vf.gradient(
                  self.moving,
                  self.moving_world2grid,
                  self.moving_spacing,
                  self.static.shape,
                  grid_to_world,
              )
              # The Jacobian must be evaluated at the pre-aligned points
              H.update_gradient_dense(
                  params,
                  self.transform,
                  static_values,
                  moving_values,
                  static2prealigned,
                  mgrad,
                  static_mask_values,
                  moving_mask_values,
              )
          else:  # Sparse case
              # Compute the gradient of moving at the sampling points
              # which are already given in physical space coordinates
              pts = current_affine.dot(self.samples.T).T  # Moved points
              mgrad, inside = vf.sparse_gradient(
                  self.moving,
                  self.moving_world2grid,
                  self.moving_spacing,
                  pts,
              )
              # The Jacobian must be evaluated at the pre-aligned points
              pts = self.samples_prealigned[..., : self.dim]
              H.update_gradient_sparse(
                  params,
                  self.transform,
                  static_values,
                  moving_values,
                  pts,
                  mgrad,
              )
  
      # Call the cythonized MI computation with self.histogram fields
      self.metric_val = compute_parzen_mi(
          H.joint, H.joint_grad, H.smarginal, H.mmarginal, grad
      )
  
imports: from warnings import warn
  import numpy
  import numpy.linalg
  import scipy.ndimage
  from dipy.core.optimize import Optimizer
  from dipy.core.interpolation import interpolate_scalar_2d, interpolate_scalar_3d
  from dipy.align import vector_fields
  from dipy.align import VerbosityLevels
  from dipy.align.parzenhist import ParzenJointHistogram, sample_domain_regular, compute_parzen_mi
  from dipy.align.imwarp import get_direction_and_spacings, ScaleSpace
  from dipy.align.scalespace import IsotropicScaleSpace
  from dipy.utils.deprecator import deprecated_params
label_desc: Use image node_id 4 for calling the MutualInformationMetric obj's underlying member method code with example usage: obj._update_mutual_information(params, update_gradient) without return types