code: def _get_post_pred_probs_and_weights_ensemble(
      labels_multiannotator: np.ndarray,
      consensus_label: np.ndarray,
      prior_pred_probs: np.ndarray,
      num_annotations: np.ndarray,
      annotator_agreement: np.ndarray,
      quality_method: str = "crowdlab",
      verbose: bool = True,
  ) -> Tuple[np.ndarray, Any, Any]:
      """Return the posterior predicted class probabilites of each example given a specified quality method and prior predicted class probabilities from an ensemble of multiple classifier models.
  
      Parameters
      ----------
      labels_multiannotator : np.ndarray
          2D numpy array of multiple given labels for each example with shape ``(N, M)``,
          where N is the number of examples and M is the number of annotators.
          For more details, labels in the same format expected by the `~cleanlab.multiannotator.get_label_quality_multiannotator`.
      consensus_label : np.ndarray
          An array of shape ``(P, N, K)`` where P is the number of models, consisting of predicted class probabilities from the ensemble models.
          Each set of predicted probabilities with shape ``(N, K)`` is in the same format expected by the :py:func:`get_label_quality_scores <cleanlab.rank.get_label_quality_scores>`.
      prior_pred_probs : np.ndarray
          An array of shape ``(N, K)`` of prior predicted probabilities, ``P(label=k|x)``, usually the out-of-sample predicted probability computed by a model.
          For details, predicted probabilities in the same format expected by the `~cleanlab.multiannotator.get_label_quality_multiannotator`.
      num_annotations : np.ndarray
          An array of shape ``(N,)`` with the number of annotators that have labeled each example.
      annotator_agreement : np.ndarray
          An array of shape ``(N,)`` with the fraction of annotators that agree with each consensus label.
      quality_method : str, default = "crowdlab" (Options: ["crowdlab", "agreement"])
          Specifies the method used to calculate the quality of the consensus label.
          For valid quality methods, view `~cleanlab.multiannotator.get_label_quality_multiannotator`
      verbose : bool, default = True
          Certain warnings and notes will be printed if ``verbose`` is set to ``True``.
  
      Returns
      -------
      post_pred_probs : np.ndarray
          An array of shape ``(N, K)`` with the posterior predicted probabilities.
  
      model_weight : np.ndarray
          An array of shape ``(P,)`` where P is the number of models in this ensemble, specifying the model weight used in weighted averages,
          ``None`` if model weight is not used to compute quality scores
  
      annotator_weight : np.ndarray
          An array of shape ``(M,)`` where M is the number of annotators, specifying the annotator weights used in weighted averages,
          ``None`` if annotator weights are not used to compute quality scores
  
      """
  
      num_classes = get_num_classes(pred_probs=prior_pred_probs[0])
  
      # likelihood that any annotator will or will not annotate the consensus label for any example
      consensus_likelihood = np.mean(
          annotator_agreement[num_annotations != 1]
      )
      non_consensus_likelihood = (1 - consensus_likelihood) / (
          num_classes - 1
      )
  
      # subsetting the dataset to only includes examples with more than one annotation
      mask = num_annotations != 1
      consensus_label_subset = consensus_label[mask]
  
      # compute most likely class error
      most_likely_class_error = np.clip(
          np.mean(
              consensus_label_subset
              != np.argmax(
                  np.bincount(
                      consensus_label_subset, minlength=num_classes
                  )
              )
          ),
          a_min=CLIPPING_LOWER_BOUND,
          a_max=None,
      )
  
      # compute adjusted annotator agreement (used as annotator weights)
      annotator_agreement_with_annotators = (
          _get_annotator_agreement_with_annotators(
              labels_multiannotator, num_annotations, verbose
          )
      )
      annotator_error = 1 - annotator_agreement_with_annotators
      adjusted_annotator_agreement = np.clip(
          1 - (annotator_error / most_likely_class_error),
          a_min=CLIPPING_LOWER_BOUND,
          a_max=None,
      )
  
      # compute model weight
      model_weight = np.full(prior_pred_probs.shape[0], np.nan)
      for idx in range(prior_pred_probs.shape[0]):
          prior_pred_probs_subset = prior_pred_probs[idx][mask]
  
          model_error = np.mean(
              np.argmax(prior_pred_probs_subset, axis=1)
              != consensus_label_subset
          )
          model_weight[idx] = np.max(
              [
                  (1 - (model_error / most_likely_class_error)),
                  CLIPPING_LOWER_BOUND,
              ]
          ) * np.sqrt(np.mean(num_annotations))
  
      # compute weighted average
      post_pred_probs = np.full(prior_pred_probs[0].shape, np.nan)
      for i, labels in enumerate(labels_multiannotator):
          labels_mask = ~np.isnan(labels)
          labels_subset = labels[labels_mask]
          post_pred_probs[i] = [
              np.average(
                  [
                      prior_pred_probs[ind][i, true_label]
                      for ind in range(prior_pred_probs.shape[0])
                  ]
                  + [
                      consensus_likelihood
                      if annotator_label == true_label
                      else non_consensus_likelihood
                      for annotator_label in labels_subset
                  ],
                  weights=np.concatenate(
                      (
                          model_weight,
                          adjusted_annotator_agreement[labels_mask],
                      )
                  ),
              )
              for true_label in range(num_classes)
          ]
  
      return_model_weight = model_weight
      return_annotator_weight = adjusted_annotator_agreement
  
      return (
          post_pred_probs,
          return_model_weight,
          return_annotator_weight,
      )
  
imports: import warnings
  import numpy
  import pandas
  from typing import List, Dict, Any, Union, Tuple, Optional
  from cleanlab.rank import get_label_quality_scores
  from cleanlab.internal.util import get_num_classes, value_counts
  from cleanlab.internal.constants import CLIPPING_LOWER_BOUND
  from cleanlab.internal.multiannotator_utils import assert_valid_inputs_multiannotator, assert_valid_pred_probs, check_consensus_label_classes, find_best_temp_scaler, temp_scale_pred_probs
label_desc: Use image node_id 13 for calling a global function with example usage: _get_post_pred_probs_and_weights_ensemble(labels_multiannotator, consensus_label, prior_pred_probs, num_annotations, annotator_agreement, quality_method, verbose) and returns: post_pred_probs,  return_model_weight,  return_annotator_weight