class_docstr: Metric representing (partial) learning curves of ML model training jobs.
docstr: Fetch multiple metrics data for an experiment.
code: def bulk_fetch_experiment_data(
      self,
      experiment: Experiment,
      metrics: Iterable[Metric],
      trials: Optional[Iterable[BaseTrial]] = None,
      **kwargs: Any,
  ) -> Dict[int, Dict[str, MetricFetchResult]]:
      """Fetch multiple metrics data for an experiment."""
      trials = list(
          experiment.trials.values() if trials is None else trials
      )
      trials = [
          trial for trial in trials if trial.status.expecting_data
      ]
      if any(isinstance(trial, BatchTrial) for trial in trials):
          raise UnsupportedError(
              f"Only (non-batch) Trials are supported by {self.__class__.__name__}"
          )
      metrics = list(metrics)
      if any(
          not isinstance(metric, AbstractCurveMetric)
          for metric in metrics
      ):
          raise UnsupportedError(
              "Only metrics that subclass AbstractCurveMetric are supported by "
              + self.__class__.__name__
          )
      try:
          trial_idx_to_id = self.get_ids_from_trials(trials=trials)
          if len(trial_idx_to_id) == 0:
              logger.debug(
                  "Could not get ids from trials. Returning MetricFetchE."
              )
              return {
                  trial.index: {
                      metric.name: Err(
                          value=MetricFetchE(
                              message=(
                                  f"Could not get ids from trials: {trials}"
                              ),
                              exception=None,
                          )
                      )
                      for metric in metrics
                  }
                  for trial in (trials if trials is not None else [])
              }
  
          curve_names = set.union(
              *(m.curve_names for m in metrics)  # pyre-ignore[16]
          )
          all_curve_series = self.get_curves_from_ids(
              ids=trial_idx_to_id.values(),
              names=curve_names,
          )
  
          if all(
              id_ not in all_curve_series
              for id_ in trial_idx_to_id.values()
          ):
              logger.debug(
                  "Could not get curves from ids. Returning Errs."
              )
              return {
                  trial.index: {
                      metric.name: Err(
                          value=MetricFetchE(
                              message=(
                                  f"Could not get curves from ids: {trial_idx_to_id}"
                              ),
                              exception=None,
                          )
                      )
                      for metric in metrics
                  }
                  for trial in (trials if trials is not None else [])
              }
  
          df = self.get_df_from_curve_series(
              experiment=experiment,
              all_curve_series=all_curve_series,
              metrics=metrics,
              trial_idx_to_id=trial_idx_to_id,
          )
  
          if df is None:
              return {
                  trial.index: {
                      metric.name: Err(
                          value=MetricFetchE(
                              message=(
                                  "DataFrame from curve series is empty"
                              ),
                              exception=None,
                          )
                      )
                      for metric in metrics
                  }
                  for trial in (trials if trials is not None else [])
              }
  
          return {
              trial.index: {
                  metric.name: Ok(
                      value=MapData(
                          df=(
                              df.loc[
                                  (df["metric_name"] == metric.name)
                                  & (df["trial_index"] == trial.index)
                              ]
                          ),
                          map_key_infos=[self.map_key_info],
                      )
                  )
                  for metric in metrics
              }
              for trial in (trials if trials is not None else [])
          }
      except Exception as e:
          return {
              trial.index: {
                  metric.name: Err(
                      value=MetricFetchE(
                          message=f"Failed to fetch {self}", exception=e
                      )
                  )
                  for metric in metrics
              }
              for trial in (trials if trials is not None else [])
          }
  
imports: from __future__ import annotations
  from abc import ABC, abstractmethod
  from logging import Logger
  from typing import Any, Dict, Iterable, Optional, Set, Union
  import numpy
  import pandas
  from ax.core.base_trial import BaseTrial
  from ax.core.batch_trial import BatchTrial
  from ax.core.experiment import Experiment
  from ax.core.map_data import MapData, MapKeyInfo
  from ax.core.map_metric import MapMetric
  from ax.core.metric import Metric, MetricFetchE, MetricFetchResult
  from ax.core.trial import Trial
  from ax.early_stopping.utils import align_partial_results
  from ax.exceptions.core import UnsupportedError
  from ax.utils.common.logger import get_logger
  from ax.utils.common.result import Err, Ok
  from ax.utils.common.typeutils import checked_cast
label_desc: Use image node_id 8 for calling the AbstractCurveMetric obj's underlying member method code with example usage: obj.bulk_fetch_experiment_data(experiment, metrics, trials) and returns: unknown, unknown, unknown, unknown, unknown