code: def _get_post_pred_probs_and_weights(
      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, Optional[float], Optional[np.ndarray]]:
      """Return the posterior predicted probabilities of each example given a specified quality method.
  
      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 ``(N,)`` with the consensus labels aggregated from all annotators.
      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 : 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 : float
          float 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
  
      """
      valid_methods = [
          "crowdlab",
          "agreement",
      ]
  
      # setting dummy variables for model and annotator weights that will be returned
      # only relevant for quality_method == crowdlab, return None for all other methods
      return_model_weight = None
      return_annotator_weight = None
  
      if quality_method == "crowdlab":
          num_classes = get_num_classes(pred_probs=prior_pred_probs)
  
          # 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]
          prior_pred_probs_subset = prior_pred_probs[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_error = np.mean(
              np.argmax(prior_pred_probs_subset, axis=1)
              != consensus_label_subset
          )
          model_weight = 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.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[i, true_label]]
                      + [
                          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
  
      elif quality_method == "agreement":
          num_classes = get_num_classes(pred_probs=prior_pred_probs)
          label_counts = np.full(
              (len(labels_multiannotator), num_classes), np.NaN
          )
          for i, labels in enumerate(labels_multiannotator):
              label_counts[i, :] = value_counts(
                  labels[~np.isnan(labels)], num_classes=num_classes
              )
  
          post_pred_probs = label_counts / num_annotations.reshape(
              -1, 1
          )
  
      else:
          raise ValueError(
              f"""
              {quality_method} is not a valid quality method!
              Please choose a valid quality_method: {valid_methods}
              """
          )
  
      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 12 for calling a global function with example usage: _get_post_pred_probs_and_weights(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