code: def build_seasonality_feature_df_with_changes(
      df,
      time_col,
      origin_for_time_vars=None,
      changepoints_dict=None,
      fs_components_df=pd.DataFrame(
          {
              "name": [
                  TimeFeaturesEnum.tod.value,
                  TimeFeaturesEnum.tow.value,
                  TimeFeaturesEnum.toy.value,
              ],
              "period": [24.0, 7.0, 1.0],
              "order": [3, 3, 5],
              "seas_names": ["daily", "weekly", "yearly"],
          }
      ),
  ):
      """A function to generate yearly seasonality features from a given time series df.
  
      The seasonality features include n_changepoints * 2 columns of the format
      1{x > c_i} * sin(2 * pi / period * order * x) and 1{x > c_i} * cos(2 * pi / period * order * x),
      where c_i is the i-th change point value.
  
      Parameters
      ----------
      df : `pandas.DataFrame`
          The data df.
      time_col : `str'
          The column name of time column in ``df``, entries can be parsed with pd.to_datetime.
      origin_for_time_vars : `float` or `None`, default `None`
          Original continuous time value, if not provided, will be parsed from data.
      changepoints_dict: `dict` or `None`, default `None`
          Change point dictionary, compatible with
          `~greykite.common.features.timeseries_features.get_changepoint_features_and_values_from_config`
          If not provided, default is no change points.
      fs_components_df: `pandas.DataFrame`
          fs_components config df, compatible with
          `~greykite.common.features.timeseries_features.fourier_series_multi_fcn`
  
      Returns
      -------
      df : `pandas.DataFrame`
          Seasonality feature df with [sum_{component_i} (2 * order_of_component_i)] * (num_changepoints + 1)
          columns.
          Each sum_{component_i} (2 * order_of_component_i) columns form a block. The first block contains the
          original seasonality features, which accounts for the overall seasonality magnitudes. Each of the
          rest num_changepoints block is a copy of the first block, with rows whose timestamps are before the
          corresponding changepoint replaced by zeros. Such blocks only have effect on the seasonality
          magnitudes after the corresponding changepoints.
      """
      df = df.copy()
      # Gets changepoints features from config. Evenly distributed with n_changepoints specified is recommended.
      if origin_for_time_vars is None:
          origin_for_time_vars = get_default_origin_for_time_vars(
              df, time_col
          )
      features_df = add_time_features_df(
          df=df,
          time_col=time_col,
          conti_year_origin=origin_for_time_vars,
      )
      fs_func = None
      fs_cols = []
      if fs_components_df is not None:
          fs_components_df = fs_components_df[
              fs_components_df["order"] != 0
          ]
          fs_components_df = fs_components_df.reset_index()
          if fs_components_df.shape[0] > 0:
              fs_func = fourier_series_multi_fcn(
                  col_names=fs_components_df["name"],
                  periods=fs_components_df.get("period"),
                  orders=fs_components_df.get("order"),
                  seas_names=fs_components_df.get("seas_names"),
              )
              time_features_example_df = build_time_features_df(
                  df[time_col][
                      :2
                  ],  # only needs the first two rows to get the column info
                  conti_year_origin=origin_for_time_vars,
              )
              fs = fs_func(time_features_example_df)
              fs_cols = fs["cols"]
      fs_features = fs_func(features_df)
      fs_df = fs_features["df"]
      fs_df.index = pd.to_datetime(df[time_col])
      # Augments regular Fourier columns to truncated Fourier columns.
      if changepoints_dict is not None:
          changepoint_dates = (
              get_changepoint_dates_from_changepoints_dict(
                  changepoints_dict=changepoints_dict,
                  df=df,
                  time_col=time_col,
              )
          )
          changepoint_dates = unique_elements_in_list(changepoint_dates)
          # The following lines truncates the fourier series at each change point
          # For each change point, the values of the fourier series before the change point are
          # set to zero. The column name is simply appending `_%Y_%m_%d_%H` after the original column names.
          col_names = fs_cols + [
              f"{col}{date.strftime('_%Y_%m_%d_%H')}"
              for date in changepoint_dates
              for col in fs_cols
          ]
          fs_truncated_df = pd.concat(
              [fs_df] * (len(changepoint_dates) + 1), axis=1
          )
          fs_truncated_df.columns = col_names
          for i, date in enumerate(changepoint_dates):
              cols = fs_truncated_df.columns[fs_df.shape[1] * (i + 1) :]
              fs_truncated_df.loc[
                  (features_df["datetime"] < date).values, cols
              ] = 0
          fs_df = fs_truncated_df
      return fs_df
  
imports: import warnings
  from datetime import timedelta
  import numpy
  import pandas
  import plotly.graph_objects
  from pandas.plotting import register_matplotlib_converters
  from pandas.tseries.frequencies import to_offset
  from sklearn.linear_model import Lasso
  from sklearn.linear_model import LassoCV
  from sklearn.linear_model import LinearRegression
  from sklearn.linear_model import RidgeCV
  from greykite.common.constants import CHANGEPOINT_COL_PREFIX
  from greykite.common.constants import TimeFeaturesEnum
  from greykite.common.features.timeseries_features import add_time_features_df
  from greykite.common.features.timeseries_features import build_time_features_df
  from greykite.common.features.timeseries_features import fourier_series_multi_fcn
  from greykite.common.features.timeseries_features import get_changepoint_dates_from_changepoints_dict
  from greykite.common.features.timeseries_features import get_changepoint_features
  from greykite.common.features.timeseries_features import get_changepoint_features_and_values_from_config
  from greykite.common.features.timeseries_features import get_default_origin_for_time_vars
  from greykite.common.python_utils import get_pattern_cols
  from greykite.common.python_utils import unique_elements_in_list
label_desc: Use image node_id 3 for calling a global function with example usage: build_seasonality_feature_df_with_changes(df, time_col, origin_for_time_vars, changepoints_dict, fs_components_df) and returns: fs_df