class_docstr: A model bridge for using torch-based models.
  
  Specifies an interface that is implemented by TorchModel. In particular,
  model should have methods fit, predict, and gen. See TorchModel for the
  API for each of these methods.
  
  Requires that all parameters have been transformed to RangeParameters
  or FixedParameters with float type and no log scale.
  
  This class converts Ax parameter types to torch tensors before passing
  them to the model.
class_docstr_tok: ["A","model","bridge","for","using","torch-based","models",".","Specifies","an","interface","that","is","implemented","by","TorchModel",".","In","particular",",","model","should","have","methods","fit",",","predict",",","and","gen.","See","TorchModel","for","the","API","for","each","of","these","methods",".","Requires","that","all","parameters","have","been","transformed","to","RangeParameters","or","FixedParameters","with","float","type","and","no","log","scale",".","This","class","converts","Ax","parameter","types","to","torch","tensors","before","passing","them","to","the","model","."]
docstr: Converts observations to a dictionary of `Dataset` containers and (optional)
  candidate metadata.
  
  Args:
      observation_data: A list of `ObservationData` from which to extract
          mean `Y` and variance `Yvar` observations. Must correspond 1:1 to
          the `observation_features`.
      observation_features: A list of `ObservationFeatures` from which to extract
          parameter values. Must correspond 1:1 to the `observation_data`.
      outcomes: The names of the outcomes to extract observations for.
      parameters: The names of the parameters to extract. Any observation features
          that are not included in `parameters` will be ignored.
      search_space_digest: An optional `SearchSpaceDigest` containing information
          about the search space. This is used to convert datasets into a
          `MultiTaskDataset` where applicable.
  
  Returns:
      - A list of `Dataset` objects. The datsets will be for the set of outcomes
          specified in `outcomes`, not necessarily in that order. Some outcomes
          will be grouped into a single dataset if there are contextual datasets.
      - A list of outcomes in the order that they appear in the datasets,
          accounting for reordering made necessary by contextual datasets.
      - An optional list of lists of candidate metadata. Each inner list
          corresponds to one outcome. Each element in the inner list corresponds
          to one observation.
docstr_tok: ["Converts","observations","to","a","dictionary","of","`","Dataset","`","containers","and","(","optional",")","candidate","metadata",".","Args",":","observation_data",":","A","list","of","`","ObservationData","`","from","which","to","extract","mean","`","Y","`","and","variance","`","Yvar","`","observations",".","Must","correspond","1:1","to","the","`","observation_features","`",".","observation_features",":","A","list","of","`","ObservationFeatures","`","from","which","to","extract","parameter","values",".","Must","correspond","1:1","to","the","`","observation_data","`",".","outcomes",":","The","names","of","the","outcomes","to","extract","observations","for",".","parameters",":","The","names","of","the","parameters","to","extract",".","Any","observation","features","that","are","not","included","in","`","parameters","`","will","be","ignored",".","search_space_digest",":","An","optional","`","SearchSpaceDigest","`","containing","information","about","the","search","space",".","This","is","used","to","convert","datasets","into","a","`","MultiTaskDataset","`","where","applicable",".","Returns",":","-","A","list","of","`","Dataset","`","objects",".","The","datsets","will","be","for","the","set","of","outcomes","specified","in","`","outcomes","`",",","not","necessarily","in","that","order",".","Some","outcomes","will","be","grouped","into","a","single","dataset","if","there","are","contextual","datasets",".","-","A","list","of","outcomes","in","the","order","that","they","appear","in","the","datasets",",","accounting","for","reordering","made","necessary","by","contextual","datasets",".","-","An","optional","list","of","lists","of","candidate","metadata",".","Each","inner","list","corresponds","to","one","outcome",".","Each","element","in","the","inner","list","corresponds","to","one","observation","."]
code: def _convert_observations(
      self,
      observation_data: List[ObservationData],
      observation_features: List[ObservationFeatures],
      outcomes: List[str],
      parameters: List[str],
      search_space_digest: Optional[SearchSpaceDigest],
  ) -> Tuple[
      List[SupervisedDataset],
      List[str],
      Optional[List[List[TCandidateMetadata]]],
  ]:
      """Converts observations to a dictionary of `Dataset` containers and (optional)
      candidate metadata.
  
      Args:
          observation_data: A list of `ObservationData` from which to extract
              mean `Y` and variance `Yvar` observations. Must correspond 1:1 to
              the `observation_features`.
          observation_features: A list of `ObservationFeatures` from which to extract
              parameter values. Must correspond 1:1 to the `observation_data`.
          outcomes: The names of the outcomes to extract observations for.
          parameters: The names of the parameters to extract. Any observation features
              that are not included in `parameters` will be ignored.
          search_space_digest: An optional `SearchSpaceDigest` containing information
              about the search space. This is used to convert datasets into a
              `MultiTaskDataset` where applicable.
  
      Returns:
          - A list of `Dataset` objects. The datsets will be for the set of outcomes
              specified in `outcomes`, not necessarily in that order. Some outcomes
              will be grouped into a single dataset if there are contextual datasets.
          - A list of outcomes in the order that they appear in the datasets,
              accounting for reordering made necessary by contextual datasets.
          - An optional list of lists of candidate metadata. Each inner list
              corresponds to one outcome. Each element in the inner list corresponds
              to one observation.
      """
      (
          Xs,
          Ys,
          Yvars,
          candidate_metadata_dict,
          any_candidate_metadata_is_not_none,
      ) = self._extract_observation_data(
          observation_data, observation_features, parameters
      )
  
      datasets: List[SupervisedDataset] = []
      candidate_metadata = []
      for outcome in outcomes:
          if outcome not in Xs:
              raise ValueError(f"Outcome `{outcome}` was not observed.")
          X = torch.stack(Xs[outcome], dim=0)
          Y = torch.tensor(
              Ys[outcome], dtype=self.dtype, device=self.device
          ).unsqueeze(-1)
          Yvar = torch.tensor(
              Yvars[outcome], dtype=self.dtype, device=self.device
          ).unsqueeze(-1)
          if Yvar.isnan().all():
              Yvar = None
          else:
              Yvar = Yvar.clamp_min(1e-6)
          dataset = SupervisedDataset(
              X=X,
              Y=Y,
              Yvar=Yvar,
              feature_names=parameters,
              outcome_names=[outcome],
          )
          datasets.append(dataset)
          candidate_metadata.append(candidate_metadata_dict[outcome])
      # If the search space digest specifies a task feature,
      # convert the datasets into MultiTaskDataset.
      if search_space_digest is not None and (
          task_features := search_space_digest.task_features
      ):
          if len(task_features) > 1:
              raise UnsupportedError(
                  "Multiple task features are not supported."
              )
          target_task_value = search_space_digest.target_values[
              task_features[0]
          ]
          # Both the MTGP and the MTDataset expect integer valued task features.
          # Check that they're indeed integers.
          task_choices = search_space_digest.discrete_choices[
              task_features[0]
          ]
          if any(int(t) != t for t in task_choices):
              raise ValueError(
                  "The values of the task feature must be integers. "
                  "This is often accomplished using a TaskEncode transform. "
                  "Check that the model is using the correct set of transforms. "
                  f"Got {task_choices=}."
              )
          datasets = [
              MultiTaskDataset.from_joint_dataset(
                  dataset=dataset,
                  task_feature_index=task_features[0],
                  target_task_value=int(target_task_value),
              )
              for dataset in datasets
          ]
      # Check if there is a `parameter_decomposition` experiment property to
      # decide whether it is a contextual experiment.
      if (
          self._experiment_properties.get(
              "parameter_decomposition", None
          )
          is not None
      ):
          # Convert to a list of ContextualDateset for contextual experiments.
          # pyre-ignore [9]: ContextualDataset is a subclass of SupervisedDataset.
          datasets = process_contextual_datasets(
              datasets=datasets,
              outcomes=outcomes,
              parameter_decomposition=self._experiment_properties[
                  "parameter_decomposition"
              ],
              metric_decomposition=self._experiment_properties.get(
                  "metric_decomposition", None
              ),
          )
  
      # Get the order of outcomes
      ordered_outcomes = []
      for d in datasets:
          ordered_outcomes.extend(d.outcome_names)
      # Re-order candidate metadata
      if any_candidate_metadata_is_not_none:
          ordered_metadata = []
          for outcome in ordered_outcomes:
              ordered_metadata.append(
                  candidate_metadata[outcomes.index(outcome)]
              )
      else:
          ordered_metadata = None
  
      return datasets, ordered_outcomes, ordered_metadata
  
imports: from __future__ import annotations
  from collections import defaultdict
  from copy import deepcopy
  from logging import Logger
  from typing import Any, Callable, Dict, List, Optional, Set, Tuple, Type, Union
  import numpy
  import torch
  from ax.core.arm import Arm
  from ax.core.data import Data
  from ax.core.experiment import Experiment
  from ax.core.generator_run import extract_arm_predictions
  from ax.core.metric import Metric
  from ax.core.observation import Observation, ObservationData, ObservationFeatures, separate_observations
  from ax.core.optimization_config import MultiObjectiveOptimizationConfig, OptimizationConfig
  from ax.core.outcome_constraint import ComparisonOp, ObjectiveThreshold, ScalarizedOutcomeConstraint
  from ax.core.search_space import SearchSpace
  from ax.core.types import TCandidateMetadata, TModelPredictArm
  from ax.exceptions.core import DataRequiredError, UnsupportedError
  from ax.modelbridge.base import gen_arms, GenResults, ModelBridge
  from ax.modelbridge.modelbridge_utils import array_to_observation_data, extract_objective_thresholds, extract_objective_weights, extract_outcome_constraints, extract_parameter_constraints, extract_risk_measure, extract_search_space_digest, get_fixed_features, observation_data_to_array, observation_features_to_array, parse_observation_features, pending_observations_as_array_list, process_contextual_datasets, SearchSpaceDigest, transform_callback, validate_and_apply_final_transform
  from ax.modelbridge.transforms.base import Transform
  from ax.modelbridge.transforms.cast import Cast
  from ax.models.torch.botorch_modular.model import BoTorchModel
  from ax.models.torch.botorch_moo import MultiObjectiveBotorchModel
  from ax.models.torch.botorch_moo_defaults import infer_objective_thresholds
  from ax.models.torch_base import TorchModel, TorchOptConfig
  from ax.models.types import TConfig
  from ax.utils.common.logger import get_logger
  from ax.utils.common.typeutils import not_none
  from botorch.utils.datasets import MultiTaskDataset, SupervisedDataset
  from torch import Tensor
label_desc: Use image node_id 8 for calling the TorchModelBridge obj's underlying member method code with example usage: obj._convert_observations(observation_data, observation_features, outcomes, parameters, search_space_digest) and returns: datasets,  ordered_outcomes,  ordered_metadata