class_docstr: Convert trial to one or more task parameters.
  
  How trial is mapped to parameter is specified with a map like
  {parameter_name: {trial_index: level name}}.
  For example,
  {"trial_param1": {0: "level1", 1: "level1", 2: "level2"},}
  will create choice parameters "trial_param1" with is_task=True.
  Observations with trial 0 or 1 will have "trial_param1" set to "level1",
  and those with trial 2 will have "trial_param1" set to "level2". Multiple
  parameter names and mappings can be specified in this dict.
  
  The trial level mapping can be specified in config["trial_level_map"]. If
  not specified, defaults to a parameter with a level for every trial index.
  
  For the reverse transform, if there are multiple mappings in the transform
  the trial will not be set.
  
  The created parameter will be given a target value that will default to the
  lowest trial index in the mapping, or can be provided in config["target_trial"].
  
  Will raise if trial not specified for every point in the training data.
  
  Transform is done in-place.
code: def __init__(
      self,
      search_space: Optional[SearchSpace] = None,
      observations: Optional[List[Observation]] = None,
      modelbridge: Optional[
          "modelbridge_module.base.ModelBridge"
      ] = None,
      config: Optional[TConfig] = None,
  ) -> None:
      assert (
          observations is not None
      ), "TrialAsTask requires observations"
      # Identify values of trial.
      trials = {obs.features.trial_index for obs in observations}
      if isinstance(search_space, RobustSearchSpace):
          raise UnsupportedError(
              "TrialAsTask transform is not supported for RobustSearchSpace."
          )
      if None in trials:
          raise ValueError(
              "Unable to use trial as task since not all observations have "
              "trial specified."
          )
      # Get trial level map
      if config is not None and "trial_level_map" in config:
          # pyre-ignore [9]
          trial_level_map: Dict[
              str, Dict[Union[int, str], Union[int, str]]
          ] = config["trial_level_map"]
          # Validate
          self.trial_level_map: Dict[
              str, Dict[int, Union[int, str]]
          ] = {}
          for _p_name, level_dict in trial_level_map.items():
              # cast trial index as an integer
              int_keyed_level_dict = {
                  int(trial_index): v
                  for trial_index, v in level_dict.items()
              }
              self.trial_level_map[_p_name] = int_keyed_level_dict
              # Check that trials match those in data
              level_map = set(int_keyed_level_dict.keys())
              if not trials.issubset(level_map):
                  raise ValueError(
                      f"Not all trials in data ({trials}) contained "
                      f"in trial level map for {_p_name} ({level_map})"
                  )
      else:
          # Set TRIAL_PARAM for each trial to the corresponding trial_index.
          # pyre-fixme[6]: Expected `Union[bytes, str, typing.SupportsInt]` for
          #  1st param but got `Optional[np.int64]`.
          self.trial_level_map = {
              TRIAL_PARAM: {int(b): str(b) for b in trials}
          }
      if len(self.trial_level_map) == 1:
          level_dict = next(iter(self.trial_level_map.values()))
          self.inverse_map: Optional[Dict[Union[int, str], int]] = {
              v: k for k, v in level_dict.items()
          }
      else:
          self.inverse_map = None
      # Compute target values
      self.target_values: Dict[str, Union[int, str]] = {}
      for p_name, trial_map in self.trial_level_map.items():
          if config is not None and "target_trial" in config:
              target_trial = int(
                  config["target_trial"]
              )  # pyre-ignore [6]
          else:
              target_trial = min(trial_map.keys())
              logger.debug(
                  f"Setting target value for {p_name} to {target_trial}"
              )
          self.target_values[p_name] = trial_map[target_trial]
  
file_path: Ax/ax/modelbridge/transforms/trial_as_task.py
imports: from logging import Logger
  from typing import Dict, List, Optional, TYPE_CHECKING, Union
  from ax.core.observation import Observation, ObservationFeatures
  from ax.core.parameter import ChoiceParameter, ParameterType
  from ax.core.search_space import RobustSearchSpace, SearchSpace
  from ax.exceptions.core import UnsupportedError
  from ax.modelbridge.transforms.base import Transform
  from ax.models.types import TConfig
  from ax.utils.common.logger import get_logger
label_desc: Use image node_id 1 to create a new TrialAsTask object from inherited base classes: Transform with example: obj = TrialAsTask(search_space, observations, modelbridge, config)