code: def interact_pareto_frontier(
      frontier_list: List[ParetoFrontierResults],
      CI_level: float = DEFAULT_CI_LEVEL,
      show_parameterization_on_hover: bool = True,
      label_dict: Optional[Dict[str, str]] = None,
  ) -> AxPlotConfig:
      """Plot a pareto frontier from a list of objects
  
      Args:
          frontier_list: List of ParetoFrontierResults objects to be plotted.
          CI_level: CI level for error bars.
          show_parameterization_on_hover: Show parameterization on hover.
          label_dict: Map from metric name to shortened alias to use on plot.
      """
      if not frontier_list:
          raise ValueError(
              "Must receive a non-empty list of pareto frontiers to plot."
          )
      label_dict_use = {k: k for k in frontier_list[0].means}
      if label_dict is not None:
          label_dict_use.update(label_dict)
  
      traces = []
      shapes = []
      for frontier in frontier_list:
          config = plot_pareto_frontier(
              frontier=frontier,
              CI_level=CI_level,
              show_parameterization_on_hover=show_parameterization_on_hover,
          )
          traces.append(config.data["data"][0])
          shapes.append(config.data["layout"].get("shapes", []))
  
      for i, trace in enumerate(traces):
          if i == 0:  # Only the first trace is initially set to visible
              trace["visible"] = True
          else:  # All other plot traces are not visible initially
              trace["visible"] = False
  
      # TODO (jej): replace dropdown with two dropdowns, one for x one for y.
      dropdown = []
      for i, frontier in enumerate(frontier_list):
          trace_cnt = 1
          # Only one plot trace is visible at a given time.
          visible = [False] * (len(frontier_list) * trace_cnt)
          for j in range(i * trace_cnt, (i + 1) * trace_cnt):
              visible[j] = True
          rel_y = (
              frontier.primary_metric not in frontier.absolute_metrics
          )
          rel_x = (
              frontier.secondary_metric not in frontier.absolute_metrics
          )
          primary_metric = label_dict_use[frontier.primary_metric]
          secondary_metric = label_dict_use[frontier.secondary_metric]
          dropdown.append(
              {
                  "method": "update",
                  "args": [
                      {"visible": visible, "method": "restyle"},
                      {
                          "yaxis.title": primary_metric,
                          "xaxis.title": secondary_metric,
                          "yaxis.ticksuffix": "%" if rel_y else "",
                          "xaxis.ticksuffix": "%" if rel_x else "",
                          "shapes": shapes[i],
                      },
                  ],
                  "label": f"{primary_metric}<br>vs {secondary_metric}",
              }
          )
  
      # Set initial layout arguments.
      initial_frontier = frontier_list[0]
      rel_x = (
          initial_frontier.secondary_metric
          not in initial_frontier.absolute_metrics
      )
      rel_y = (
          initial_frontier.primary_metric
          not in initial_frontier.absolute_metrics
      )
      secondary_metric = label_dict_use[
          initial_frontier.secondary_metric
      ]
      primary_metric = label_dict_use[initial_frontier.primary_metric]
  
      layout = go.Layout(
          title="Pareto Frontier",
          xaxis={
              "title": secondary_metric,
              "ticksuffix": "%" if rel_x else "",
              "zeroline": True,
          },
          yaxis={
              "title": primary_metric,
              "ticksuffix": "%" if rel_y else "",
              "zeroline": True,
          },
          updatemenus=[
              {
                  "buttons": dropdown,
                  "x": 0.075,
                  "xanchor": "left",
                  "y": 1.1,
                  "yanchor": "middle",
              }
          ],
          hovermode="closest",
          legend={"orientation": "h"},
          width=750,
          height=500,
          margin=go.layout.Margin(
              pad=4, l=225, b=75, t=75
          ),  # noqa E741
          shapes=shapes[0],
      )
  
      fig = go.Figure(data=traces, layout=layout)
      return AxPlotConfig(data=fig, plot_type=AxPlotTypes.GENERIC)
  
imports: import warnings
  from typing import Dict, Iterable, List, Optional, Tuple, Union
  import numpy
  import pandas
  import plotly.graph_objs
  from ax.core.experiment import Experiment
  from ax.core.objective import MultiObjective
  from ax.core.optimization_config import MultiObjectiveOptimizationConfig, OptimizationConfig
  from ax.core.outcome_constraint import ObjectiveThreshold
  from ax.exceptions.core import UserInputError
  from ax.plot.base import AxPlotConfig, AxPlotTypes, CI_OPACITY, DECIMALS
  from ax.plot.color import COLORS, DISCRETE_COLOR_SCALE, rgba
  from ax.plot.helper import _format_CI, _format_dict, extend_range
  from ax.plot.pareto_utils import ParetoFrontierResults
  from ax.service.utils.best_point_mixin import BestPointMixin
  from ax.utils.common.typeutils import checked_cast, not_none
  from plotly import express
  from scipy.stats import norm
label_desc: Use image node_id 9 for calling a global function with example usage: interact_pareto_frontier(frontier_list, CI_level, show_parameterization_on_hover, label_dict) and returns: AxPlotConfig