code: def test_extra_pred_cols(hourly_data, daily_data_reg, weekly_data):
      """Tests ``convert_simple_silverkite_params`` extra_pred_cols output
      It should contain:
  
          - growth
          - regressors
          - holidays
          - feature sets
  
      And not have any duplicates.
      """
      extra_pred_cols = ["epc1", "epc2"]
      growth_term = "linear"
  
      # some columns that belong to each feature set
      # assumes the default holidays are used
      # assumes `growth_term="linear"`
      example_cols_hour_of_week = [
          "C(Q('dow_hr'), levels=['1_00', '1_01', '1_02', '1_03', '1_04', '1_05', '1_06', '1_07', '1_08', '1_09', '1_10', '1_11', '1_12', '1_13', '1_14', '1_15', '1_16', '1_17', '1_18', '1_19', '1_20', '1_21', '1_22', '1_23', '2_00', '2_01', '2_02', '2_03', '2_04', '2_05', '2_06', '2_07', '2_08', '2_09', '2_10', '2_11', '2_12', '2_13', '2_14', '2_15', '2_16', '2_17', '2_18', '2_19', '2_20', '2_21', '2_22', '2_23', '3_00', '3_01', '3_02', '3_03', '3_04', '3_05', '3_06', '3_07', '3_08', '3_09', '3_10', '3_11', '3_12', '3_13', '3_14', '3_15', '3_16', '3_17', '3_18', '3_19', '3_20', '3_21', '3_22', '3_23', '4_00', '4_01', '4_02', '4_03', '4_04', '4_05', '4_06', '4_07', '4_08', '4_09', '4_10', '4_11', '4_12', '4_13', '4_14', '4_15', '4_16', '4_17', '4_18', '4_19', '4_20', '4_21', '4_22', '4_23', '5_00', '5_01', '5_02', '5_03', '5_04', '5_05', '5_06', '5_07', '5_08', '5_09', '5_10', '5_11', '5_12', '5_13', '5_14', '5_15', '5_16', '5_17', '5_18', '5_19', '5_20', '5_21', '5_22', '5_23', '6_00', '6_01', '6_02', '6_03', '6_04', '6_05', '6_06', '6_07', '6_08', '6_09', '6_10', '6_11', '6_12', '6_13', '6_14', '6_15', '6_16', '6_17', '6_18', '6_19', '6_20', '6_21', '6_22', '6_23', '7_00', '7_01', '7_02', '7_03', '7_04', '7_05', '7_06', '7_07', '7_08', '7_09', '7_10', '7_11', '7_12', '7_13', '7_14', '7_15', '7_16', '7_17', '7_18', '7_19', '7_20', '7_21', '7_22', '7_23'])"
      ]  # noqa: E501
      example_cols_weekend_seas = [
          "is_weekend:sin12_tod_daily",
          "is_weekend:cos12_tod_daily",
      ]
      example_cols_day_of_week_seas = [
          "C(Q('str_dow'), levels=['1-Mon', '2-Tue', '3-Wed', '4-Thu', '5-Fri', '6-Sat', '7-Sun']):sin12_tod_daily",
          "C(Q('str_dow'), levels=['1-Mon', '2-Tue', '3-Wed', '4-Thu', '5-Fri', '6-Sat', '7-Sun']):cos12_tod_daily",
      ]  # noqa: E501
      example_cols_trend_daily_seas = [
          "is_weekend:ct1:sin12_tod_daily",
          "is_weekend:ct1:cos12_tod_daily",
      ]
      example_cols_event_seas = [
          "C(Q('events_Independence Day'), levels=['', 'event']):sin12_tod_daily",
          "C(Q('events_New Years Day_plus_1'), levels=['', 'event']):cos12_tod_daily",
      ]  # noqa: E501
      example_cols_event_weekend_seas = [
          "is_weekend:C(Q('events_Independence Day'), levels=['', 'event']):sin12_tod_daily",
          "is_weekend:C(Q('events_New Years Day_plus_1'), levels=['', 'event']):cos12_tod_daily",
      ]  # noqa: E501
      example_cols_day_of_week = [
          "C(Q('str_dow'), levels=['1-Mon', '2-Tue', '3-Wed', '4-Thu', '5-Fri', '6-Sat', '7-Sun'])"
      ]  # noqa: E501
      example_cols_trend_weekend = ["is_weekend:ct1"]
      example_cols_trend_day_of_week = [
          "C(Q('str_dow'), levels=['1-Mon', '2-Tue', '3-Wed', '4-Thu', '5-Fri', '6-Sat', '7-Sun']):ct1"
      ]  # noqa: E501
      example_cols_trend_weekly_seas = [
          "ct1:sin4_tow_weekly",
          "ct1:cos4_tow_weekly",
      ]
      example_cols = {
          SilverkiteColumn.COLS_HOUR_OF_WEEK: example_cols_hour_of_week,
          SilverkiteColumn.COLS_WEEKEND_SEAS: example_cols_weekend_seas,
          SilverkiteColumn.COLS_DAY_OF_WEEK_SEAS: example_cols_day_of_week_seas,
          SilverkiteColumn.COLS_TREND_DAILY_SEAS: example_cols_trend_daily_seas,
          SilverkiteColumn.COLS_EVENT_SEAS: example_cols_event_seas,
          SilverkiteColumn.COLS_EVENT_WEEKEND_SEAS: example_cols_event_weekend_seas,
          SilverkiteColumn.COLS_DAY_OF_WEEK: example_cols_day_of_week,
          SilverkiteColumn.COLS_TREND_WEEKEND: example_cols_trend_weekend,
          SilverkiteColumn.COLS_TREND_DAY_OF_WEEK: example_cols_trend_day_of_week,
          SilverkiteColumn.COLS_TREND_WEEKLY_SEAS: example_cols_trend_weekly_seas,
      }
      # example holiday columns expected in the output
      example_holiday_cols = [
          "C(Q('events_Chinese New Year'), levels=['', 'event'])",
          "C(Q('events_Chinese New Year_minus_1'), levels=['', 'event'])",
          "C(Q('events_Chinese New Year_minus_2'), levels=['', 'event'])",
          "C(Q('events_Chinese New Year_plus_1'), levels=['', 'event'])",
          "C(Q('events_Chinese New Year_plus_2'), levels=['', 'event'])",
          "C(Q('events_Independence Day'), levels=['', 'event'])",
      ]
      excluded_holiday_cols = [  # should not appear
          "C(Q('events_Chinese New Year_minus_3'), levels=['', 'event'])"
          "C(Q('events_Independence Day_plus_3'), levels=['', 'event'])"
      ]
  
      # TEST 1 -- specified feature sets, on hourly data
      feature_sets_enabled = {
          SilverkiteColumn.COLS_HOUR_OF_WEEK: False,
          SilverkiteColumn.COLS_WEEKEND_SEAS: True,
          SilverkiteColumn.COLS_DAY_OF_WEEK_SEAS: False,
          SilverkiteColumn.COLS_TREND_DAILY_SEAS: True,
          SilverkiteColumn.COLS_EVENT_SEAS: False,
          SilverkiteColumn.COLS_EVENT_WEEKEND_SEAS: True,
          SilverkiteColumn.COLS_DAY_OF_WEEK: False,
          SilverkiteColumn.COLS_TREND_WEEKEND: True,
          SilverkiteColumn.COLS_TREND_DAY_OF_WEEK: False,
          SilverkiteColumn.COLS_TREND_WEEKLY_SEAS: True,
      }
  
      silverkite = SimpleSilverkiteForecast()
      parameters = silverkite.convert_params(
          df=hourly_data,
          time_col=cst.TIME_COL,
          value_col=cst.VALUE_COL,
          growth_term=growth_term,
          feature_sets_enabled=feature_sets_enabled,
          extra_pred_cols=extra_pred_cols,
      )
      result_cols = parameters["extra_pred_cols"]
  
      feature_set_cols = []  # feature set columns that should appear
      excluded_cols = []  # columns that should not appear
      excluded_cols += excluded_holiday_cols
      for feature_set_name, use_set in feature_sets_enabled.items():
          if use_set:
              feature_set_cols += example_cols[feature_set_name]
          else:
              excluded_cols += example_cols[feature_set_name]
      expected_cols = set(
          [cst.GrowthColEnum[growth_term].value]
          + example_holiday_cols
          + feature_set_cols
          + extra_pred_cols
      )
      assert len(result_cols) == 427  # desired length
      assert len(result_cols) == len(set(result_cols))  # no duplicates
      assert set(expected_cols).issubset(
          set(result_cols)
      )  # contains expected cols
      assert (
          len(set(excluded_cols).intersection(set(result_cols))) == 0
      )  # does not contain excluded cols
  
      # No feature sets
      parameters = silverkite.convert_params(
          df=hourly_data,
          time_col=cst.TIME_COL,
          value_col=cst.VALUE_COL,
          growth_term=growth_term,
          feature_sets_enabled=None,  # equivalent to False
          extra_pred_cols=extra_pred_cols,
      )
      result_cols = parameters["extra_pred_cols"]
      assert len(result_cols) == 58
      assert not any(
          col in result_cols
          for _, cols in example_cols.items()
          for col in cols
      )
  
      # TEST 2 -- specified feature sets, on daily data with regressors
      # NB: some feature sets don't make sense for daily data, used here for unit test
      regressor_cols = ["regressor1", "regressor2"]
      feature_sets_enabled = {
          SilverkiteColumn.COLS_HOUR_OF_WEEK: True,
          SilverkiteColumn.COLS_WEEKEND_SEAS: True,
          SilverkiteColumn.COLS_DAY_OF_WEEK_SEAS: True,
          SilverkiteColumn.COLS_TREND_DAILY_SEAS: True,
          SilverkiteColumn.COLS_EVENT_SEAS: True,
          SilverkiteColumn.COLS_EVENT_WEEKEND_SEAS: True,
          SilverkiteColumn.COLS_DAY_OF_WEEK: True,
          SilverkiteColumn.COLS_TREND_WEEKEND: False,
          SilverkiteColumn.COLS_TREND_DAY_OF_WEEK: True,
          SilverkiteColumn.COLS_TREND_WEEKLY_SEAS: False,
      }
      # Adds some extra holidays and checks if they are included
      event_df_dict = get_holidays(
          ["UnitedStates", "China"], year_start=2015, year_end=2030
      )
      more_example_holiday_cols = [
          "C(Q('events_China'), levels=['', \"New Year's Day\", 'Chinese New Year', 'Tomb-Sweeping Day', "
          "'Labor Day', 'Dragon Boat Festival', 'Mid-Autumn Festival', 'National Day', 'National Day, "
          "Mid-Autumn Festival'])",
          "C(Q('events_UnitedStates'), levels=['', \"New Year's Day\", 'Martin Luther King Jr. Day', "
          "\"Washington's Birthday\", 'Memorial Day', 'Independence Day', 'Independence Day (Observed)', "
          "'Labor Day', 'Columbus Day', 'Veterans Day', 'Thanksgiving', 'Christmas Day', 'Halloween', "
          "'Christmas Day (Observed)', \"New Year's Day (Observed)\", 'Veterans Day (Observed)', "
          "'Juneteenth National Independence Day', 'Juneteenth National Independence Day (Observed)'])",
      ]
  
      parameters = silverkite.convert_params(
          df=daily_data_reg,
          time_col="custom_time_col",
          value_col="custom_value_col",
          daily_event_df_dict=event_df_dict,
          growth_term=growth_term,
          regressor_cols=regressor_cols,
          feature_sets_enabled=feature_sets_enabled,
          extra_pred_cols=extra_pred_cols,
      )
      result_cols = parameters["extra_pred_cols"]
  
      feature_set_cols = []  # feature set columns that should appear
      excluded_cols = []  # columns that should not appear
      excluded_cols += excluded_holiday_cols
      # no daily seasonality for daily data, so these aren't used
      feature_sets_used = feature_sets_enabled.copy()
      feature_sets_used[SilverkiteColumn.COLS_WEEKEND_SEAS] = False
      feature_sets_used[SilverkiteColumn.COLS_DAY_OF_WEEK_SEAS] = False
      feature_sets_used[SilverkiteColumn.COLS_TREND_DAILY_SEAS] = False
      feature_sets_used[SilverkiteColumn.COLS_EVENT_SEAS] = False
      feature_sets_used[
          SilverkiteColumn.COLS_EVENT_WEEKEND_SEAS
      ] = False
      for feature_set_name, use_set in feature_sets_used.items():
          if use_set:
              feature_set_cols += example_cols[feature_set_name]
          else:
              excluded_cols += example_cols[feature_set_name]
      expected_cols = set(
          [cst.GrowthColEnum[growth_term].value]
          + regressor_cols
          + example_holiday_cols
          + more_example_holiday_cols
          + feature_set_cols
          + extra_pred_cols
      )
      assert len(result_cols) == 65  # desired length
      assert len(result_cols) == len(set(result_cols))  # no duplicates
      assert set(expected_cols).issubset(
          set(result_cols)
      )  # contains expected cols
      assert (
          len(set(excluded_cols).intersection(set(result_cols))) == 0
      )  # does not contain excluded cols
  
      # TEST 3 -- default feature sets, on weekly data
      parameters = silverkite.convert_params(
          df=weekly_data,
          time_col=cst.TIME_COL,
          value_col=cst.VALUE_COL,
          growth_term=growth_term,
          extra_pred_cols=extra_pred_cols,
      )
      result_cols = parameters["extra_pred_cols"]
  
      feature_set_cols = []  # feature set columns that should appear
      excluded_cols = []  # columns that should not appear
      excluded_cols += excluded_holiday_cols
      # no feature sets apply for weekly data
      feature_sets_used = {
          SilverkiteColumn.COLS_HOUR_OF_WEEK: False,
          SilverkiteColumn.COLS_WEEKEND_SEAS: False,
          SilverkiteColumn.COLS_DAY_OF_WEEK_SEAS: False,
          SilverkiteColumn.COLS_TREND_DAILY_SEAS: False,
          SilverkiteColumn.COLS_EVENT_SEAS: False,
          SilverkiteColumn.COLS_EVENT_WEEKEND_SEAS: False,
          SilverkiteColumn.COLS_DAY_OF_WEEK: False,
          SilverkiteColumn.COLS_TREND_WEEKEND: False,
          SilverkiteColumn.COLS_TREND_DAY_OF_WEEK: False,
          SilverkiteColumn.COLS_TREND_WEEKLY_SEAS: False,
      }
      for feature_set_name, use_set in feature_sets_used.items():
          if use_set:
              feature_set_cols += example_cols[feature_set_name]
          else:
              excluded_cols += example_cols[feature_set_name]
      expected_cols = set(
          [cst.GrowthColEnum[growth_term].value]
          + example_holiday_cols
          + feature_set_cols
          + extra_pred_cols
      )
      assert len(result_cols) == 58  # desired length
      assert len(result_cols) == len(set(result_cols))  # no duplicates
      assert set(expected_cols).issubset(
          set(result_cols)
      )  # contains expected cols
      assert len(set(excluded_cols).intersection(set(result_cols))) == 0
  
imports: import datetime
  import math
  import sys
  import warnings
  from datetime import timedelta
  import pandas
  import pytest
  from testfixtures import LogCapture
  import greykite.common.constants
  from greykite.algo.changepoint.adalasso.changepoint_detector import ChangepointDetector
  from greykite.algo.forecast.silverkite.constants.silverkite_column import SilverkiteColumn
  from greykite.algo.forecast.silverkite.constants.silverkite_holiday import SilverkiteHoliday
  from greykite.algo.forecast.silverkite.constants.silverkite_seasonality import SilverkiteSeasonality
  from greykite.algo.forecast.silverkite.constants.silverkite_seasonality import SilverkiteSeasonalityEnum
  from greykite.algo.forecast.silverkite.forecast_simple_silverkite import SimpleSilverkiteForecast
  from greykite.algo.forecast.silverkite.forecast_simple_silverkite_helper import generate_holiday_events
  from greykite.common.constants import CHANGEPOINT_COL_PREFIX
  from greykite.common.constants import EVENT_DF_DATE_COL
  from greykite.common.constants import EVENT_DF_LABEL_COL
  from greykite.common.constants import LOGGER_NAME
  from greykite.common.constants import TIME_COL
  from greykite.common.constants import VALUE_COL
  from greykite.common.data_loader import DataLoader
  from greykite.common.enums import SimpleTimeFrequencyEnum
  from greykite.common.enums import TimeEnum
  from greykite.common.features.timeseries_features import get_available_holidays_across_countries
  from greykite.common.features.timeseries_features import get_holidays
  from greykite.common.python_utils import assert_equal
  from greykite.common.python_utils import update_dictionary
  from greykite.common.testing_utils import generate_df_for_tests
  from greykite.common.testing_utils import generate_df_with_reg_for_tests
label_desc: Use image node_id 8 for calling a global function with example usage: test_extra_pred_cols(hourly_data, daily_data_reg, weekly_data) without return types