code: def apply_default_model_components(
      model_components=None, time_properties=None
  ):
      """Sets default values for ``model_components``.
  
      Parameters
      ----------
      model_components : :class:`~greykite.framework.templates.autogen.forecast_config.ModelComponentsParam` or None, default None
          Configuration of model growth, seasonality, events, etc.
          See :func:`~greykite.framework.templates.silverkite_templates.silverkite_template` for details.
      time_properties : `dict` [`str`, `any`] or None, default None
          Time properties dictionary (likely produced by
          `~greykite.common.time_properties_forecast.get_forecast_time_properties`)
          with keys:
  
          ``"period"`` : `int`
              Period of each observation (i.e. minimum time between observations, in seconds).
          ``"simple_freq"`` : `SimpleTimeFrequencyEnum`
              ``SimpleTimeFrequencyEnum`` member corresponding to data frequency.
          ``"num_training_points"`` : `int`
              Number of observations for training.
          ``"num_training_days"`` : `int`
              Number of days for training.
          ``"start_year"`` : `int`
              Start year of the training period.
          ``"end_year"`` : `int`
              End year of the forecast period.
          ``"origin_for_time_vars"`` : `float`
              Continuous time representation of the first date in ``df``.
  
      Returns
      -------
      model_components : :class:`~greykite.framework.templates.autogen.forecast_config.ModelComponentsParam`
          The provided ``model_components`` with default values set
      """
      if model_components is None:
          model_components = ModelComponentsParam()
      else:
          # makes a copy to avoid mutating input
          model_components = dataclasses.replace(model_components)
  
      # sets default values
      default_seasonality = {
          "fs_components_df": [
              pd.DataFrame(
                  {
                      "name": [
                          TimeFeaturesEnum.tod.value,
                          TimeFeaturesEnum.tow.value,
                          TimeFeaturesEnum.tom.value,
                          TimeFeaturesEnum.toq.value,
                          TimeFeaturesEnum.toy.value,
                      ],
                      "period": [24.0, 7.0, 1.0, 1.0, 1.0],
                      "order": [3, 3, 1, 1, 5],
                      "seas_names": [
                          "daily",
                          "weekly",
                          "monthly",
                          "quarterly",
                          "yearly",
                      ],
                  }
              )
          ],
      }
      model_components.seasonality = update_dictionary(
          default_seasonality,
          overwrite_dict=model_components.seasonality,
          allow_unknown_keys=False,
      )
  
      # model_components.growth must be empty.
      # Pass growth terms via `extra_pred_cols` instead.
      default_growth = {}
      model_components.growth = update_dictionary(
          default_growth,
          overwrite_dict=model_components.growth,
          allow_unknown_keys=False,
      )
  
      default_events = {
          "daily_event_df_dict": [None],
          "daily_event_neighbor_impact": [None],
          "daily_event_shifted_effect": [None],
      }
      model_components.events = update_dictionary(
          default_events,
          overwrite_dict=model_components.events,
          allow_unknown_keys=False,
      )
  
      default_changepoints = {
          "changepoints_dict": [None],
          "seasonality_changepoints_dict": [None],
          # Not allowed, to prevent leaking future information
          # into the past. Pass `changepoints_dict` with method="auto" for
          # automatic detection.
          # "changepoint_detector": [None],
      }
      model_components.changepoints = update_dictionary(
          default_changepoints,
          overwrite_dict=model_components.changepoints,
          allow_unknown_keys=False,
      )
  
      default_autoregression = {
          "autoreg_dict": [None],
          "simulation_num": [10],
          "fast_simulation": [False],
      }
      model_components.autoregression = update_dictionary(
          default_autoregression,
          overwrite_dict=model_components.autoregression,
          allow_unknown_keys=False,
      )
  
      default_regressors = {}
      model_components.regressors = update_dictionary(
          default_regressors,
          overwrite_dict=model_components.regressors,
          allow_unknown_keys=False,
      )
  
      default_lagged_regressors = {
          "lagged_regressor_dict": [None],
      }
      model_components.lagged_regressors = update_dictionary(
          default_lagged_regressors,
          overwrite_dict=model_components.lagged_regressors,
          allow_unknown_keys=False,
      )
  
      default_uncertainty = {
          "uncertainty_dict": [None],
      }
      model_components.uncertainty = update_dictionary(
          default_uncertainty,
          overwrite_dict=model_components.uncertainty,
          allow_unknown_keys=False,
      )
  
      if time_properties is not None:
          origin_for_time_vars = time_properties.get(
              "origin_for_time_vars"
          )
      else:
          origin_for_time_vars = None
  
      default_custom = {
          "silverkite": [
              SilverkiteForecast()
          ],  # NB: sklearn creates a copy in grid search
          # The same origin for every split, based on start year of full dataset.
          # To use first date of each training split, set to `None` in model_components.
          "origin_for_time_vars": [origin_for_time_vars],
          "extra_pred_cols": [
              TimeFeaturesEnum.ct1.value
          ],  # linear growth
          "drop_pred_cols": [None],
          "explicit_pred_cols": [None],
          "fit_algorithm_dict": [
              {
                  "fit_algorithm": "linear",
                  "fit_algorithm_params": None,
              }
          ],
          "min_admissible_value": [None],
          "max_admissible_value": [None],
          "regression_weight_col": [None],
          "normalize_method": [None],
          "remove_intercept": [False],
      }
      model_components.custom = update_dictionary(
          default_custom,
          overwrite_dict=model_components.custom,
          allow_unknown_keys=False,
      )
  
      # sets to {} if None, for each item if
      # `model_components.hyperparameter_override` is a list of dictionaries
      model_components.hyperparameter_override = update_dictionaries(
          {}, overwrite_dicts=model_components.hyperparameter_override
      )
  
      return model_components
  
imports: import dataclasses
  import functools
  from typing import Dict
  from typing import Optional
  import numpy
  import pandas
  from greykite.algo.forecast.silverkite.forecast_silverkite import SilverkiteForecast
  from greykite.common.constants import TimeFeaturesEnum
  from greykite.common.features.timeseries_lags import build_autoreg_df_multi
  from greykite.common.python_utils import dictionaries_values_to_lists
  from greykite.common.python_utils import unique_in_list
  from greykite.common.python_utils import update_dictionaries
  from greykite.common.python_utils import update_dictionary
  from greykite.framework.templates.autogen.forecast_config import ForecastConfig
  from greykite.framework.templates.autogen.forecast_config import ModelComponentsParam
  from greykite.framework.templates.base_template import BaseTemplate
  from greykite.sklearn.estimator.base_forecast_estimator import BaseForecastEstimator
  from greykite.sklearn.estimator.silverkite_estimator import SilverkiteEstimator
label_desc: Use image node_id 2 for calling a global function with example usage: apply_default_model_components(model_components, time_properties) and returns: model_components