class_docstr: Map Y values to percentiles based on their empirical CDF.
class_docstr_tok: ["Map","Y","values","to","percentiles","based","on","their","empirical","CDF","."]
docstr: Map observation data to empirical CDF quantiles in place.
docstr_tok: ["Map","observation","data","to","empirical","CDF","quantiles","in","place","."]
code: def _transform_observation_data(
      self,
      observation_data: List[ObservationData],
  ) -> List[ObservationData]:
      """Map observation data to empirical CDF quantiles in place."""
      # TODO (jej): Transform covariances.
      if self.winsorize:
          winsorization_rates = {}
          for metric_name, vals in self.percentiles.items():
              n = len(vals)
              # Calculate winsorization rate based on number of observations
              # using formula from [Salinas, Shen, Perrone 2020]
              # https://arxiv.org/abs/1909.13595
              winsorization_rates[metric_name] = (
                  1.0
                  / (
                      4
                      * math.pow(n, 0.25)
                      * math.pow(math.pi * math.log(n), 0.5)
                  )
                  if n > 1
                  else 0.25
              )
      else:
          winsorization_rates = {
              metric_name: 0 for metric_name in self.percentiles.keys()
          }
      for obsd in observation_data:
          for idx, metric_name in enumerate(obsd.metric_names):
              if metric_name not in self.percentiles:
                  raise ValueError(
                      f"Cannot map value to percentile"
                      f" for unknown metric {metric_name}"
                  )
              # apply map function
              percentile = self._map(obsd.means[idx], metric_name)
              # apply winsorization. If winsorization_rate is 0, has no effect.
              metric_wr = winsorization_rates[metric_name]
              percentile = max(metric_wr, percentile)
              percentile = min((1 - metric_wr), percentile)
              obsd.means[idx] = percentile
              obsd.covariance.fill(float("nan"))
      return observation_data
  
file_path: Ax/ax/modelbridge/transforms/percentile_y.py
imports: import math
  from logging import Logger
  from typing import List, Optional, TYPE_CHECKING
  from ax.core.observation import Observation, ObservationData
  from ax.core.search_space import SearchSpace
  from ax.exceptions.core import DataRequiredError
  from ax.modelbridge.transforms.base import Transform
  from ax.modelbridge.transforms.utils import get_data
  from ax.models.types import TConfig
  from ax.utils.common.logger import get_logger
  from ax.utils.common.typeutils import checked_cast
  from scipy import stats
label_desc: Use image node_id 2 for calling the PercentileY obj's underlying member method code with example usage: obj._transform_observation_data(observation_data) and returns: observation_data