class_docstr: Base class for a forecast-based anomaly detector.
docstr: Compare a model's forecast to a ground truth time series, in order to compute anomaly scores. By default, we
  compute a z-score if model uncertainty (``stderr``) is given, or the residuals if there is no model uncertainty.
  
  :param time_series: the ground truth time series.
  :param forecast: the model's forecasted values for the time series
  :param stderr: the standard errors of the model's forecast
  
  :return: Anomaly scores based on the difference between the ground truth values and the model's forecast.
docstr_tok: ["Compare","a","model","'s","forecast","to","a","ground","truth","time","series",",","in","order","to","compute","anomaly","scores",".","By","default",",","we","compute","a","z-score","if","model","uncertainty","(","``","stderr","``",")","is","given",",","or","the","residuals","if","there","is","no","model","uncertainty",".",":","param","time_series",":","the","ground","truth","time","series",".",":","param","forecast",":","the","model","'s","forecasted","values","for","the","time","series",":","param","stderr",":","the","standard","errors","of","the","model","'s","forecast",":","return",":","Anomaly","scores","based","on","the","difference","between","the","ground","truth","values","and","the","model","'s","forecast","."]
code: def forecast_to_anom_score(
      self,
      time_series: TimeSeries,
      forecast: TimeSeries,
      stderr: Optional[TimeSeries],
  ) -> pd.DataFrame:
      """
      Compare a model's forecast to a ground truth time series, in order to compute anomaly scores. By default, we
      compute a z-score if model uncertainty (``stderr``) is given, or the residuals if there is no model uncertainty.
  
      :param time_series: the ground truth time series.
      :param forecast: the model's forecasted values for the time series
      :param stderr: the standard errors of the model's forecast
  
      :return: Anomaly scores based on the difference between the ground truth values and the model's forecast.
      """
      if len(forecast) == 0:
          return pd.DataFrame(columns=["anom_score"])
      time_series = time_series.align(reference=forecast.time_stamps)
      time_series = time_series.univariates[
          time_series.names[self.target_seq_index]
      ]
      times = time_series.index
      y = time_series.np_values
      yhat = forecast.univariates[forecast.names[0]].np_values
      if stderr is None:
          return pd.DataFrame(
              y - yhat, index=times, columns=["anom_score"]
          )
      else:
          sigma = stderr.univariates[stderr.names[0]].np_values
          if np.isnan(sigma).all():
              sigma = 1
          else:
              sigma[np.isnan(sigma)] = np.mean(sigma)
          return pd.DataFrame(
              (y - yhat) / (sigma + 1e-8),
              index=times,
              columns=["anom_score"],
          )
  
imports: import copy
  import logging
  from typing import List, Optional, Tuple, Union
  import numpy
  import pandas
  from merlion.models.anomaly.base import DetectorBase
  from merlion.models.forecast.base import ForecasterBase
  from merlion.plot import Figure
  from merlion.utils import TimeSeries
  from merlion.utils.misc import AutodocABCMeta
label_desc: Use image node_id 2 for calling the ForecastingDetectorBase obj's underlying member method code with example usage: obj.forecast_to_anom_score(time_series, forecast, stderr) and returns: pd, pd, pd