class_docstr: This class purpose is to find the best forecast from given k forecasts
  to act as baseline for anomaly detection.
  
  This class inherits its parameters and attributes from
  `~greykite.detection.detector.forecast_based.ForecastBasedDetector`
  and all methods apply here as well.
  
  The only addition is on top of the specified parameters to optimize over, this
  class also searches for the best forecast to use out of a number of forecasts
  passed. It achieves that simply by extending the parameter space, given in the input
  `param_iterable` to have one extra parameter: ``"forecast_id"``.
  
  Given that assumption, this class further implements the ``fit`` method fully
  and the user does not need to implement ``fit``.
  
  Therefore user only needs to implement the following:
  
      - ``add_features_one_df``: Note that the class uses this method to fully implement
          ``add_features`` because the class can assume that the same function can
          be used for all k forecasts.
      - ``calc_with_param``: the prediction logic, assuming the optimal param
          is determined.
  
  As an example see how the APE based method is implemented easily by inheriting
  from the current class:
  
      `~greykite.detection.detector.ape_based.APEDetector`
  
  
  Parameters
  ----------
  Solely inherited from
      `~greykite.detection.detector.forecast_based.ForecastBasedDetector`
  
  
  Attributes
  ----------
  Solely inherited from
      `~greykite.detection.detector.forecast_based.ForecastBasedDetector`
class_docstr_tok: ["This","class","purpose","is","to","find","the","best","forecast","from","given","k","forecasts","to","act","as","baseline","for","anomaly","detection",".","This","class","inherits","its","parameters","and","attributes","from","`","~greykite.detection.detector.forecast_based.ForecastBasedDetector","`","and","all","methods","apply","here","as","well",".","The","only","addition","is","on","top","of","the","specified","parameters","to","optimize","over",",","this","class","also","searches","for","the","best","forecast","to","use","out","of","a","number","of","forecasts","passed",".","It","achieves","that","simply","by","extending","the","parameter","space",",","given","in","the","input","`","param_iterable","`","to","have","one","extra","parameter",":","``","``","forecast_id","''","``",".","Given","that","assumption",",","this","class","further","implements","the","``","fit","``","method","fully","and","the","user","does","not","need","to","implement","``","fit","``",".","Therefore","user","only","needs","to","implement","the","following",":","-","``","add_features_one_df","``",":","Note","that","the","class","uses","this","method","to","fully","implement","``","add_features","``","because","the","class","can","assume","that","the","same","function","can","be","used","for","all","k","forecasts",".","-","``","calc_with_param","``",":","the","prediction","logic",",","assuming","the","optimal","param","is","determined",".","As","an","example","see","how","the","APE","based","method","is","implemented","easily","by","inheriting","from","the","current","class",":","`","~greykite.detection.detector.ape_based.APEDetector","`","Parameters","--","--","--","--","--","Solely","inherited","from","`","~greykite.detection.detector.forecast_based.ForecastBasedDetector","`","Attributes","--","--","--","--","--","Solely","inherited","from","`","~greykite.detection.detector.forecast_based.ForecastBasedDetector","`"]
docstr: Parameters
  ----------
  data : `~greykite.detection.detector.ForecastDetectorData`
      Object including the data.
  
  Returns
  -------
  result : None
      The fit will update ``self.fit_info`` and ``self.fitted_df``
docstr_tok: ["Parameters","--","--","--","--","--","data",":","`","~greykite.detection.detector.ForecastDetectorData","`","Object","including","the","data",".","Returns","--","--","--","-","result",":","None","The","fit","will","update","``","self.fit_info","``","and","``","self.fitted_df","``"]
code: def fit(self, data):
      """
      Parameters
      ----------
      data : `~greykite.detection.detector.ForecastDetectorData`
          Object including the data.
  
      Returns
      -------
      result : None
          The fit will update ``self.fit_info`` and ``self.fitted_df``
      """
      # Adds the forecast id possibilities to `param_iterable`
      # so that we can optimize over forecasts as well as
      # existing combinations of parameters given in `param_iterable`
      if data.forecast_dfs is not None:
          # First it creates the list of needed forecast ids
          # based on the length of the input `forecast_dfs`
          forecast_ids = list(range(len(data.forecast_dfs)))
          if self.param_iterable is None:
              # It creates a list of dictionaries of length one
              # each prescribing only the `forecast_id`
              param_iterable = [
                  {"forecast_id": x} for x in forecast_ids
              ]
          else:
              param_iterable = add_new_params_to_records(
                  new_params={"forecast_id": forecast_ids},
                  records=self.param_iterable,
              )
      else:
          param_iterable = self.param_iterable
  
      # Joins the forecast dfs with df
      # each joined df is a join between df and one element of
      # `forecast_dfs`
      # Prepares data
      self.prep_df_for_predict(data)
      # True labels might be needed for some objectives
      # therefore we extract them if available
      # If labels are not available, then `y_true` is set to be None
      data.y_true = None
      if self.is_anomaly_col is not None and data.y_true is None:
          data.y_true = data.df[self.is_anomaly_col]
  
      self.data = data
  
      optim_res = self.optimize_param(
          data=data, param_iterable=param_iterable
      )
  
      self.fit_info = {
          "param": optim_res["best_param"],
          "param_full": optim_res["best_param_full"],
          "obj_value": optim_res["best_obj_value"],
          "param_obj_list": optim_res["param_obj_list"],
          "best_calc_result": optim_res["best_calc_result"],
      }
  
      # Gets fitted values and final objective values
      self.fitted_df = self.predict(data)
  
imports: from greykite.detection.detector.ad_utils import add_new_params_to_records
  from greykite.detection.detector.forecast_based import ForecastBasedDetector
label_desc: Use image node_id 2 for calling the BestForecastDetector obj's underlying member method code with example usage: obj.fit(data) without return types