code: def hourly_data():
      """Generates data for testing `GreykiteDetector`."""
  
      df = generate_df_for_tests(
          freq="H",
          train_start_date=datetime.datetime(2020, 1, 1),
          intercept=50,
          train_frac=0.99,
          periods=24 * 28,
      )["df"]
  
      anomaly_block_list = [
          np.arange(100, 105),
          np.arange(200, 210),
          np.arange(310, 315),
          np.arange(400, 410),
          np.arange(460, 480),
          np.arange(601, 610),
          np.arange(620, 625),
          np.arange(650, 654),
          np.arange(666, 667),
      ]
  
      # Contaminates `df` with anomalies at the specified locations,
      # via `anomaly_block_list`.
      # If original value is y, the anomalous value is: (1 +/- delta)*y.
      df = contaminate_df_with_anomalies(
          df=df,
          anomaly_block_list=anomaly_block_list,
          delta_range_lower=0.1,
          delta_range_upper=0.2,
          value_col=VALUE_COL,
          min_admissible_value=None,
          max_admissible_value=None,
      )
  
      fig = plot_lines_markers(
          df=df, x_col=TIME_COL, line_cols=["y", "contaminated_y"]
      )
  
      fig.layout.update(title="Generation of hourly anomalous data")
      fig.update_yaxes()
      assert fig is not None
      if FIG_SHOW:
          fig.show()
  
      df = df.drop(columns=[VALUE_COL]).rename(
          columns={"contaminated_y": VALUE_COL}
      )
  
      df[ANOMALY_COL] = df[ANOMALY_COL] == 1
  
      assert len(df) == (28 * 24)
      assert sum(df[ANOMALY_COL]) == 69
  
      train_size = int(26 * 24)
      df_train = df[:train_size].reset_index(drop=True)
      df_test = df[train_size:].reset_index(drop=True)
  
      assert len(df_train) == 26 * 24
      assert len(df_test) == 2 * 24
  
      return {"df_train": df_train, "df_test": df_test, "df": df}
  
imports: import datetime
  import numpy
  import pandas
  import plotly.express
  import pytest
  from greykite.common.constants import ACTUAL_COL
  from greykite.common.constants import ANOMALY_COL
  from greykite.common.constants import END_TIME_COL
  from greykite.common.constants import PREDICTED_ANOMALY_COL
  from greykite.common.constants import PREDICTED_COL
  from greykite.common.constants import PREDICTED_LOWER_COL
  from greykite.common.constants import PREDICTED_UPPER_COL
  from greykite.common.constants import START_TIME_COL
  from greykite.common.constants import TIME_COL
  from greykite.common.constants import VALUE_COL
  from greykite.common.testing_utils import generate_df_for_tests
  from greykite.common.testing_utils_anomalies import contaminate_df_with_anomalies
  from greykite.common.viz.timeseries_annotate import plot_anomalies_over_forecast_vs_actual
  from greykite.common.viz.timeseries_annotate import plot_lines_markers
  from greykite.common.viz.timeseries_annotate import plt_compare_series_annotations
  from greykite.detection.common.ad_evaluation import f1_score
  from greykite.detection.common.ad_evaluation import precision_score
  from greykite.detection.common.ad_evaluation import recall_score
  from greykite.detection.detector.ad_utils import partial_return
  from greykite.detection.detector.config import F1
  from greykite.detection.detector.config import ADConfig
  from greykite.detection.detector.data import DetectorData
  from greykite.detection.detector.greykite import DETECTOR_PREDICT_COLS
  from greykite.detection.detector.greykite import GreykiteDetector
  from greykite.detection.detector.reward import Reward
  from greykite.framework.templates.autogen.forecast_config import EvaluationPeriodParam
  from greykite.framework.templates.autogen.forecast_config import ForecastConfig
  from greykite.framework.templates.autogen.forecast_config import MetadataParam
  from greykite.framework.templates.autogen.forecast_config import ModelComponentsParam
label_desc: Use image node_id 1 for calling a global function with example usage: hourly_data() and returns: dict