code: def get_label_quality_multiannotator_ensemble(
      labels_multiannotator: Union[pd.DataFrame, np.ndarray],
      pred_probs: np.ndarray,
      *,
      calibrate_probs: bool = False,
      return_detailed_quality: bool = True,
      return_annotator_stats: bool = True,
      return_weights: bool = False,
      verbose: bool = True,
      label_quality_score_kwargs: dict = {},
  ) -> Dict[str, Any]:
      """Returns label quality scores for each example and for each annotator, based on predictions from an ensemble of models.
  
      This function is similar to `~cleanlab.multiannotator.get_label_quality_multiannotator` but for settings where
      you have trained an ensemble of multiple classifier models rather than a single model.
  
      Parameters
      ----------
      labels_multiannotator : pd.DataFrame or np.ndarray
          Multiannotator labels in the same format expected by `~cleanlab.multiannotator.get_label_quality_multiannotator`.
      pred_probs : 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>`.
      calibrate_probs : bool, default = False
          Boolean value as expected by `~cleanlab.multiannotator.get_label_quality_multiannotator`.
      return_detailed_quality: bool, default = True
          Boolean value as expected by `~cleanlab.multiannotator.get_label_quality_multiannotator`.
      return_annotator_stats : bool, default = True
          Boolean value as expected by `~cleanlab.multiannotator.get_label_quality_multiannotator`.
      return_weights : bool, default = False
          Boolean value as expected by `~cleanlab.multiannotator.get_label_quality_multiannotator`.
      verbose : bool, default = True
          Boolean value as expected by `~cleanlab.multiannotator.get_label_quality_multiannotator`.
      label_quality_score_kwargs : dict, optional
          Keyword arguments in the same format expected by `~cleanlab.multiannotator.get_label_quality_multiannotator`.
  
      Returns
      -------
      labels_info : dict
          Dictionary containing up to 5 pandas DataFrame with keys as below:
  
          ``label_quality`` : pandas.DataFrame
              Similar to output as `~cleanlab.multiannotator.get_label_quality_multiannotator`.
  
          ``detailed_label_quality`` : pandas.DataFrame
              Similar to output as `~cleanlab.multiannotator.get_label_quality_multiannotator`.
  
          ``annotator_stats`` : pandas.DataFrame
              Similar to output as `~cleanlab.multiannotator.get_label_quality_multiannotator`.
  
          ``model_weight`` : np.ndarray
              Only returned if `return_weights=True`.
              An array of shape ``(P,)`` where is the number of models in the ensemble, specifying the weight of each classifier model in weighted averages used to estimate label quality.
              These weigthts is an estimate of how trustworthy the model is relative the annotators.
              An array of shape ``(P,)`` where is the number of models in the ensemble, specifying the model weight used in weighted averages.
  
          ``annotator_weight`` : np.ndarray
              Only returned if `return_weights=True`.
              Similar to output as `~cleanlab.multiannotator.get_label_quality_multiannotator`.
  
      See Also
      --------
      get_label_quality_multiannotator
      """
      if isinstance(labels_multiannotator, pd.DataFrame):
          annotator_ids = labels_multiannotator.columns
          index_col = labels_multiannotator.index
          labels_multiannotator = (
              labels_multiannotator.replace({pd.NA: np.NaN})
              .astype(float)
              .to_numpy()
          )
      elif isinstance(labels_multiannotator, np.ndarray):
          annotator_ids = None
          index_col = None
      else:
          raise ValueError(
              "labels_multiannotator must be either a NumPy array or Pandas DataFrame."
          )
  
      assert_valid_inputs_multiannotator(
          labels_multiannotator,
          pred_probs,
          ensemble=True,
          annotator_ids=annotator_ids,
      )
  
      # Count number of non-NaN values for each example
      num_annotations = np.sum(~np.isnan(labels_multiannotator), axis=1)
  
      # temp scale pred_probs
      if calibrate_probs:
          for i in range(len(pred_probs)):
              curr_pred_probs = pred_probs[i]
              optimal_temp = find_best_temp_scaler(
                  labels_multiannotator, curr_pred_probs
              )
              pred_probs[i] = temp_scale_pred_probs(
                  curr_pred_probs, optimal_temp
              )
  
      label_quality = pd.DataFrame(
          {"num_annotations": num_annotations}, index=index_col
      )
  
      # get majority vote stats
      avg_pred_probs = np.mean(pred_probs, axis=0)
      majority_vote_label = get_majority_vote_label(
          labels_multiannotator=labels_multiannotator,
          pred_probs=avg_pred_probs,
          verbose=False,
      )
      (
          MV_annotator_agreement,
          MV_consensus_quality_score,
          MV_post_pred_probs,
          MV_model_weight,
          MV_annotator_weight,
      ) = _get_consensus_stats(
          labels_multiannotator=labels_multiannotator,
          pred_probs=pred_probs,
          num_annotations=num_annotations,
          consensus_label=majority_vote_label,
          verbose=verbose,
          ensemble=True,
          **label_quality_score_kwargs,
      )
  
      # get crowdlab stats
      consensus_label = np.full(len(majority_vote_label), np.nan)
      for i in range(len(consensus_label)):
          max_pred_probs_ind = np.where(
              MV_post_pred_probs[i] == np.max(MV_post_pred_probs[i])
          )[0]
          if len(max_pred_probs_ind) == 1:
              consensus_label[i] = max_pred_probs_ind[0]
          else:
              consensus_label[i] = majority_vote_label[i]
      consensus_label = consensus_label.astype(
          int
      )  # convert all label types to int
  
      (
          annotator_agreement,
          consensus_quality_score,
          post_pred_probs,
          model_weight,
          annotator_weight,
      ) = _get_consensus_stats(
          labels_multiannotator=labels_multiannotator,
          pred_probs=pred_probs,
          num_annotations=num_annotations,
          consensus_label=consensus_label,
          verbose=verbose,
          ensemble=True,
          **label_quality_score_kwargs,
      )
  
      if verbose:
          # check if any classes no longer appear in the set of consensus labels
          check_consensus_label_classes(
              labels_multiannotator=labels_multiannotator,
              consensus_label=consensus_label,
              consensus_method="crowdlab",
          )
  
      (
          label_quality["consensus_label"],
          label_quality["consensus_quality_score"],
          label_quality["annotator_agreement"],
      ) = (
          consensus_label,
          consensus_quality_score,
          annotator_agreement,
      )
  
      label_quality = label_quality.reindex(
          columns=[
              "consensus_label",
              "consensus_quality_score",
              "annotator_agreement",
              "num_annotations",
          ]
      )
  
      # default variable for _get_annotator_stats
      detailed_label_quality = None
  
      if return_detailed_quality:
          # Compute the label quality scores for each annotators' labels
          detailed_label_quality = np.apply_along_axis(
              _get_annotator_label_quality_score,
              axis=0,
              arr=labels_multiannotator,
              pred_probs=post_pred_probs,
              label_quality_score_kwargs=label_quality_score_kwargs,
          )
          detailed_label_quality_df = pd.DataFrame(
              detailed_label_quality,
              index=index_col,
              columns=annotator_ids,
          ).add_prefix("quality_annotator_")
  
      if return_annotator_stats:
          annotator_stats = _get_annotator_stats(
              labels_multiannotator=labels_multiannotator,
              pred_probs=post_pred_probs,
              consensus_label=consensus_label,
              num_annotations=num_annotations,
              annotator_agreement=annotator_agreement,
              model_weight=np.mean(
                  model_weight
              ),  # use average model weight when scoring annotators
              annotator_weight=annotator_weight,
              consensus_quality_score=consensus_quality_score,
              detailed_label_quality=detailed_label_quality,
              annotator_ids=annotator_ids,
          )
  
      labels_info = {
          "label_quality": label_quality,
      }
  
      if return_detailed_quality:
          labels_info[
              "detailed_label_quality"
          ] = detailed_label_quality_df
      if return_annotator_stats:
          labels_info["annotator_stats"] = annotator_stats
      if return_weights:
          labels_info["model_weight"] = model_weight
          labels_info["annotator_weight"] = annotator_weight
  
      return labels_info
  
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 2 for calling a global function with example usage: get_label_quality_multiannotator_ensemble(labels_multiannotator, pred_probs) and returns: labels_info