code: def _get_scalarized_curve_metric_sub_df(
      dfs_mean: Dict[str, pd.DataFrame],
      dfs_sem: Dict[str, pd.DataFrame],
      metric: AbstractScalarizedCurveMetric,
      trial: Trial,
  ) -> pd.DataFrame:
      """Helper to construct sub-dfs for a ScalarizedCurveMetric.
  
      Args:
          df_mean: A mapping from Curve metric names to a dataframe
              containing the means of the respective metric. The progression
              indices are assumed to be aliged across metrics (e.g. as
              obtained via `align_partial_results`).
          df_sem: A mapping from Curve metric names to a dataframe
              containing the sems of the respective metric. If empty,
              assume the metrics are subject to noise of unknown magnitude.
          metric: The ScalarizedCurveMetric to perform the aggregation for.
          trial: The trial associated with the data in `df_mean` and `df_sem`.
  
      Returns:
          A dataframe with the scalarized mean and sem in `mean` and `sem`
          columns, respectively.
      """
      sub_df = metric.offset + sum(
          coeff * dfs_mean[metric]  # pyre-ignore [58]
          for metric, coeff in metric.coefficients.items()
      )
      sub_df = sub_df.rename(
          columns={trial.index: "mean"}
      )  # pyre-ignore [16]
      if dfs_sem:
          var_df = sum(
              (coeff * dfs_sem[metric]) ** 2  # pyre-ignore [58]
              for metric, coeff in metric.coefficients.items()
          )
          sem_df = var_df.apply(np.sqrt).rename(  # pyre-ignore [16]
              columns={trial.index: "sem"}
          )
          sub_df = pd.concat([sub_df, sem_df], axis=1)
      else:
          sub_df["sem"] = float("nan")
      sub_df = sub_df.reset_index()
      sub_df["trial_index"] = trial.index
      sub_df["arm_name"] = trial.arm.name  # pyre-ignore [16]
      sub_df["metric_name"] = metric.name
      # When scalarizing curves, sometimes the last progression will be different
      # across curves, even for the same trial. This dropna() will only keep the
      # progressions that are available for all curves.
      return sub_df.dropna(subset=["mean"])
  
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 4 for calling a global function with example usage: _get_scalarized_curve_metric_sub_df(dfs_mean, dfs_sem, metric, trial) and returns: sub_df