class_docstr: Distributional model components
  
  Parameters
  ----------
  design : formulae.DesignMatrices
      The object with all the required design matrices and information about the model terms.
  priors : dict
      A dictionary where keys are term names and values are their priors.
  response_name : str
      The name of the response or target. If ``response_kind`` is ``"data"``, it's the name of
      the response variable. If ``response_kind`` is ``"param"`` it's the name of the parameter.
      An example of the first could be "Reaction" and an example of the latter could be "sigma"
      or "kappa".
  response_kind : str
      Specifies whether the distributional component models the response (``"data"``) or an
      auxiliary parameter (``"param"``). When ``"data"`` this is actually modeling the "parent"
      parameter of the family.
  spec : bambi.Model
      The Bambi model
code: def predict_common(
      self,
      posterior,
      data,
      in_sample,
      to_stack_dims,
      design_matrix_dims,
      hsgp_dict,
  ):
      x_offsets = []
      linear_predictor = 0
      response_dim = design_matrix_dims[0]
  
      if in_sample:
          X = self.design.common.design_matrix
      else:
          X = self.design.common.evaluate_new_data(data).design_matrix
  
      # Add offset columns to their own design matrix and remove then from common matrix
      for term in self.offset_terms:
          term_slice = self.design.common.slices[term]
          x_offsets.append(X[:, term_slice])
          X = np.delete(X, term_slice, axis=1)
  
      # Add HSGP components contribution to the linear predictor
      for term_name, term in self.hsgp_terms.items():
          # Extract data for the HSGP component from the design matrix
          term_slice = self.design.common.slices[term_name]
          x_slice = X[:, term_slice]
          X = np.delete(X, term_slice, axis=1)
          term_aliased_name = get_aliased_name(term)
          hsgp_to_stack_dims = (f"{term_aliased_name}_weights_dim",)
  
          # Data may be scaled so the maximum Euclidean distance between two points is 1
          if term.scale_predictors:
              maximum_distance = term.maximum_distance
          else:
              maximum_distance = 1
  
          # NOTE:
          # The approach here differs from the one in the PyMC implementation.
          # Here we have a single dot product with many zeros, while there we have many
          # smaller dot products.
          # It is subject to change here, but I don't want to mess up dims and coords.
          if term.by_levels is not None:
              by_values = x_slice[:, -1].astype(int)
              x_slice = x_slice[:, :-1]
              x_slice_centered = (
                  x_slice.data - term.mean[by_values]
              ) / maximum_distance
              phi_list = []
              for i, level in enumerate(term.by_levels):
                  phi = (
                      term.hsgp[level]
                      .prior_linearized(x_slice_centered)[0]
                      .eval()
                  )
                  phi[by_values != i] = 0
                  phi_list.append(phi)
              phi = np.column_stack(phi_list)
              hsgp_to_stack_dims = (
                  f"{term_aliased_name}_by",
              ) + hsgp_to_stack_dims
          else:
              x_slice_centered = (
                  x_slice - term.mean
              ) / maximum_distance
              phi = term.hsgp.prior_linearized(x_slice_centered)[
                  0
              ].eval()
  
          # Convert 'phi' to xarray.DataArray for easier math operations
          # Notice the extra '_' in the dim name for the weights
          phi = xr.DataArray(
              phi,
              dims=(response_dim, f"{term_aliased_name}__weights_dim"),
          )
          weights = posterior[f"{term_aliased_name}_weights"]
          weights = weights.stack(
              {f"{term_aliased_name}__weights_dim": hsgp_to_stack_dims}
          )
  
          # Compute contribution and add it to the linear predictor
          hsgp_contribution = xr.dot(phi, weights)
  
          # Store the contribution so it can be added later to the posterior Dataset
          hsgp_dict[term_name] = hsgp_contribution
  
          # Add contribution to the linear predictor
          linear_predictor += hsgp_contribution
  
      if self.common_terms or self.intercept_term:
          # Create DataArray
          X_terms = [
              get_aliased_name(term)
              for term in self.common_terms.values()
          ]
          if self.intercept_term:
              X_terms.insert(0, get_aliased_name(self.intercept_term))
          b = posterior[X_terms].to_stacked_array(
              "__variables__", to_stack_dims
          )
  
          # Add contribution due to the common terms
          X = xr.DataArray(X, dims=design_matrix_dims)
          linear_predictor += xr.dot(X, b)
  
      # If model contains offsets, add them directly to the linear predictor
      if x_offsets:
          linear_predictor += np.column_stack(x_offsets).sum(axis=1)[
              :, np.newaxis, np.newaxis
          ]
  
      return linear_predictor
  
imports: import formulae
  import numpy
  import xarray
  from bambi.defaults import get_default_prior
  from bambi.families import univariate, multivariate
  from bambi.priors import Prior
  from bambi.terms import CommonTerm, GroupSpecificTerm, HSGPTerm, OffsetTerm, ResponseTerm
  from bambi.utils import get_aliased_name, is_hsgp_term
label_desc: Use image node_id 9 for calling the DistributionalComponent obj's underlying member method code with example usage: obj.predict_common(posterior, data, in_sample, to_stack_dims, design_matrix_dims, hsgp_dict) and returns: linear_predictor