class_docstr: A term that is compiled to a HSGP term in PyMC
  
  This instance contains information of a bambi.HSGPTerm and knows how to build the distributions
  in PyMC that represent the HSGP latent approximation.
  
  Parameters
  ----------
  term : bambi.terms.HSGPTerm
      An object representing a Bambi hsgp term.
class_docstr_tok: ["A","term","that","is","compiled","to","a","HSGP","term","in","PyMC","This","instance","contains","information","of","a","bambi.HSGPTerm","and","knows","how","to","build","the","distributions","in","PyMC","that","represent","the","HSGP","latent","approximation",".","Parameters","--","--","--","--","--","term",":","bambi.terms.HSGPTerm","An","object","representing","a","Bambi","hsgp","term","."]
code: def build(self, bmb_model):
      # Get the name of the term
      label = self.name
  
      # Get the covariance functions (it's possibly more than one)
      covariance_functions = self.get_covariance_functions()
  
      # Get dimension name for the response
      response_name = get_aliased_name(
          bmb_model.response_component.response_term
      )
  
      # Prepare dims
      coeff_dims = (f"{label}_weights_dim",)
      contribution_dims = (f"{response_name}_obs",)
  
      # Data may be scaled so the maximum Euclidean distance between two points is 1
      if self.term.scale_predictors:
          data = self.term.data_centered / self.term.maximum_distance
      else:
          data = self.term.data_centered
  
      # Build HSGP and store it in the term.
      if self.term.by_levels is not None:
          coeff_dims = coeff_dims + (f"{label}_by",)
          phi_list, sqrt_psd_list = [], []
          self.term.hsgp = {}
          # Because of the filter in the loop, it will be as if the observations were sorted
          # using the values of the 'by' variable.
          # This approach helps especially when there are many groups, which causes many zeros
          # with other approaches (until PyMC and us have better support for sparse matrices)
          indexes_to_unsort = self.term.by.argsort(
              kind="mergesort"
          ).argsort(kind="mergesort")
          for i, level in enumerate(self.term.by_levels):
              cov_func = covariance_functions[i]
              # Notes:
              # 'm' doesn't change by group
              # We need to use list() in 'm' and 'L' because arrays are not instance of Sequence
              hsgp = pm.gp.HSGP(
                  m=list(self.term.m),
                  L=list(self.term.L[i]),
                  drop_first=self.term.drop_first,
                  cov_func=cov_func,
              )
              # Notice we pass all the values, for all the groups.
              # Then we only keep the ones for the corresponding group.
              phi, sqrt_psd = hsgp.prior_linearized(
                  data[self.term.by == i]
              )
              sqrt_psd_list.append(sqrt_psd)
              phi_list.append(phi.eval())
  
              # Store it for later usage
              self.term.hsgp[level] = hsgp
          sqrt_psd = pt.stack(sqrt_psd_list, axis=1)
      else:
          (cov_func,) = covariance_functions
          self.term.hsgp = pm.gp.HSGP(
              m=list(self.term.m),
              L=list(self.term.L[0]),
              drop_first=self.term.drop_first,
              cov_func=cov_func,
          )
          # Get prior components
          phi, sqrt_psd = self.term.hsgp.prior_linearized(data)
          phi = phi.eval()
  
      # Build weights coefficient
      if self.term.centered:
          coeffs = pm.Normal(
              f"{label}_weights", sigma=sqrt_psd, dims=coeff_dims
          )
      else:
          coeffs_raw = pm.Normal(
              f"{label}_weights_raw", dims=coeff_dims
          )
          coeffs = pm.Deterministic(
              f"{label}_weights", coeffs_raw * sqrt_psd, dims=coeff_dims
          )
  
      # Build deterministic for the HSGP contribution
      # If there are groups, we do as many dot products as groups
      if self.term.by_levels is not None:
          contribution_list = []
          for i in range(len(self.term.by_levels)):
              contribution_list.append(phi_list[i] @ coeffs[:, i])
          # We need to unsort the contributions so they match the original data
          contribution = pt.concatenate(contribution_list)[
              indexes_to_unsort
          ]
      # If there are no groups, it's a single dot product
      else:
          contribution = pt.dot(
              phi, coeffs
          )  # "@" operator is not working as expected
  
      output = pm.Deterministic(
          label, contribution, dims=contribution_dims
      )
      return output
  
imports: import inspect
  import numpy
  import pymc
  import pytensor.tensor
  from bambi.backend.utils import get_distribution_from_likelihood, get_distribution_from_prior, get_linkinv, has_hyperprior, make_weighted_distribution, GP_KERNELS
  from bambi.families.multivariate import MultivariateFamily, Multinomial, DirichletMultinomial
  from bambi.families.univariate import Categorical
  from bambi.priors import Prior
  from bambi.utils import get_aliased_name
label_desc: Use image node_id 2 for calling the HSGPTerm obj's underlying member method code with example usage: obj.build(bmb_model) and returns: output