code: def _obs_vs_pred_dropdown_plot(
      data: PlotData,
      rel: bool,
      show_context: bool = False,
      xlabel: str = "Actual Outcome",
      ylabel: str = "Predicted Outcome",
      autoset_axis_limits: bool = True,
  ) -> go.Figure:
      """Plot a dropdown plot of observed vs. predicted values from a model.
  
      Args:
          data: a name tuple storing observed and predicted data
              from a model.
          rel: if True, plot metrics relative to the status quo.
          show_context: Show context on hover.
          xlabel: Label for x-axis.
          ylabel: Label for y-axis.
          autoset_axis_limits: Automatically try to set the limit for each axis to focus
              on the region of interest.
      """
      traces = []
      metric_dropdown = []
      layout_axis_range = []
      if rel and data.status_quo_name is not None:
          if show_context:
              raise ValueError(
                  "This plot does not support both context and relativization at "
                  "the same time."
              )
          status_quo_arm = data.in_sample[data.status_quo_name]
      else:
          status_quo_arm = None
  
      for i, metric in enumerate(data.metrics):
          y_raw, se_raw, y_hat, se_hat = _error_scatter_data(
              list(data.in_sample.values()),
              y_axis_var=PlotMetric(metric, pred=True, rel=rel),
              x_axis_var=PlotMetric(metric, pred=False, rel=rel),
              status_quo_arm=status_quo_arm,
          )
          se_raw = (
              [0.0 if np.isnan(se) else se for se in se_raw]
              if se_raw is not None
              else [0.0] * len(y_raw)
          )
  
          min_, max_ = _get_min_max_with_errors(
              y_raw, y_hat, se_raw, se_hat
          )
          if autoset_axis_limits:
              y_raw_np = np.array(y_raw)
              # TODO: replace interpolation->method once it becomes standard.
              q1 = np.nanpercentile(
                  y_raw_np, q=25, interpolation="lower"
              ).min()
              q3 = np.nanpercentile(
                  y_raw_np, q=75, interpolation="higher"
              ).max()
              y_lower = q1 - 1.5 * (q3 - q1)
              y_upper = q3 + 1.5 * (q3 - q1)
              y_raw_np = y_raw_np.clip(y_lower, y_upper).tolist()
              min_robust, max_robust = _get_min_max_with_errors(
                  y_raw_np, y_hat, se_raw, se_hat
              )
              y_padding = 0.05 * (max_robust - min_robust)
              # Use the min/max of the limits
              layout_axis_range.append(
                  [
                      max(min_robust, min_) - y_padding,
                      min(max_robust, max_) + y_padding,
                  ]
              )
              traces.append(
                  _diagonal_trace(
                      min(min_robust, min_) - y_padding,
                      max(max_robust, max_) + y_padding,
                      visible=(i == 0),
                  )
              )
          else:
              layout_axis_range.append(None)
              traces.append(
                  _diagonal_trace(min_, max_, visible=(i == 0))
              )
  
          traces.append(
              _error_scatter_trace(
                  arms=list(data.in_sample.values()),
                  hoverinfo="text",
                  show_arm_details_on_hover=True,
                  show_CI=True,
                  show_context=show_context,
                  status_quo_arm=status_quo_arm,
                  visible=(i == 0),
                  x_axis_label=xlabel,
                  x_axis_var=PlotMetric(metric, pred=False, rel=rel),
                  y_axis_label=ylabel,
                  y_axis_var=PlotMetric(metric, pred=True, rel=rel),
              )
          )
  
          # only the first two traces are visible (corresponding to first outcome
          # in dropdown)
          is_visible = [False] * (len(data.metrics) * 2)
          is_visible[2 * i] = True
          is_visible[2 * i + 1] = True
  
          # on dropdown change, restyle
          metric_dropdown.append(
              {
                  "args": [
                      {"visible": is_visible},
                      {
                          "xaxis.range": layout_axis_range[-1],
                          "yaxis.range": layout_axis_range[-1],
                      },
                  ],
                  "label": metric,
                  "method": "update",
              }
          )
  
      updatemenus = [
          {
              "x": 0,
              "y": 1.125,
              "yanchor": "top",
              "xanchor": "left",
              "buttons": metric_dropdown,
          },
          {
              "buttons": [
                  {
                      "args": [
                          {
                              "error_x.width": 4,
                              "error_x.thickness": 2,
                              "error_y.width": 4,
                              "error_y.thickness": 2,
                          }
                      ],
                      "label": "Yes",
                      "method": "restyle",
                  },
                  {
                      "args": [
                          {
                              "error_x.width": 0,
                              "error_x.thickness": 0,
                              "error_y.width": 0,
                              "error_y.thickness": 0,
                          }
                      ],
                      "label": "No",
                      "method": "restyle",
                  },
              ],
              "x": 1.125,
              "xanchor": "left",
              "y": 0.8,
              "yanchor": "middle",
          },
      ]
  
      layout = go.Layout(
          annotations=[
              {
                  "showarrow": False,
                  "text": "Show CI",
                  "x": 1.125,
                  "xanchor": "left",
                  "xref": "paper",
                  "y": 0.9,
                  "yanchor": "middle",
                  "yref": "paper",
              }
          ],
          xaxis={
              "range": layout_axis_range[0],
              "title": xlabel,
              "zeroline": False,
              "mirror": True,
              "linecolor": "black",
              "linewidth": 0.5,
          },
          yaxis={
              "range": layout_axis_range[0],
              "title": ylabel,
              "zeroline": False,
              "mirror": True,
              "linecolor": "black",
              "linewidth": 0.5,
          },
          showlegend=False,
          hovermode="closest",
          updatemenus=updatemenus,
          width=530,
          height=500,
      )
  
      return go.Figure(data=traces, layout=layout)
  
imports: from copy import deepcopy
  from typing import Any, Dict, List, Optional, Tuple
  import numpy
  import plotly.graph_objs
  from ax.core.batch_trial import BatchTrial
  from ax.core.data import Data
  from ax.core.experiment import Experiment
  from ax.core.multi_type_experiment import MultiTypeExperiment
  from ax.core.observation import Observation
  from ax.modelbridge.cross_validation import CVResult
  from ax.modelbridge.transforms.convert_metric_names import convert_mt_observations
  from ax.plot.base import AxPlotConfig, AxPlotTypes, PlotData, PlotInSampleArm, PlotMetric, Z
  from ax.plot.helper import compose_annotation
  from ax.plot.scatter import _error_scatter_data, _error_scatter_trace
  from ax.utils.common.typeutils import not_none
  from plotly import subplots
label_desc: Use image node_id 3 for calling a global function with example usage: _obs_vs_pred_dropdown_plot(data, rel, show_context, xlabel, ylabel, autoset_axis_limits) and returns: go