code: def tbats_model_generator(
      y,
      seasonal_periods,
      k_vector,
      use_boxcox,
      bc_lower_bound,
      bc_upper_bound,
      use_trend,
      use_damped_trend,
      use_arma_errors,
      ar_coeffs,
      ma_coeffs,
  ):
      # Initial Box-Cox transformation (if required)
      if use_boxcox:
          BoxCox_lambda = (
              0  # This is the initial value used in the thesis
          )
          y_trans = boxcox(y, BoxCox_lambda)
      else:
          BoxCox_lambda = None
          y_trans = y
  
      p, q = findPQ(ar_coeffs, ma_coeffs)
  
      # select starting params
      (
          alpha,
          adj_beta,
          beta,
          b,
          phi,
          gamma_one_v,
          gamma_two_v,
          s_vector,
          d_vector,
          epsilon_vector,
      ) = initial_parameters(
          seasonal_periods,
          k_vector,
          use_trend,
          use_damped_trend,
          ar_coeffs,
          ma_coeffs,
      )
  
      # seed states
      x_nought = makeXMatrix(b, s_vector, d_vector, epsilon_vector)
  
      # tau
      tau = 2 * np.sum(k_vector)
  
      # Create w_transpose, g, and F matrices
      w_transpose = makeTBATSWMatrix(
          phi, k_vector, ar_coeffs, ma_coeffs, tau
      )
      g, gamma_bold = makeTBATSGMatrix(
          k_vector,
          alpha,
          adj_beta,
          beta,
          gamma_one_v,
          gamma_two_v,
          p,
          q,
          tau,
      )
      F = makeTBATSFMatrix(
          phi,
          tau,
          alpha,
          beta,
          ar_coeffs,
          ma_coeffs,
          gamma_bold,
          seasonal_periods,
          k_vector,
      )
      D = F - np.dot(g, w_transpose)
  
      # Find seed states
      _, e, x = calcTBATSFaster(y_trans, w_transpose, g, F, x_nought)
  
      w_tilda_transpose = np.zeros((y.shape[0], w_transpose.shape[1]))
      w_tilda_transpose[0, :] = w_transpose
  
      for k in range(1, w_tilda_transpose.shape[0]):
          w_tilda_transpose[k, :] = np.dot(
              w_tilda_transpose[k - 1, :], D
          )
  
      if p != 0 or q != 0:
          end_cut = w_tilda_transpose.shape[1]
          start_cut = end_cut - (p + q)
          new_cols = np.arange(0, start_cut, 1)
          w_tilda_transpose = w_tilda_transpose[:, new_cols]
  
      model = sm.OLS(
          e.reshape((e.shape[1], 1)), w_tilda_transpose
      ).fit()
      x_nought = model.params
  
      if (p != 0) or (q != 0):
          arma_seed_states = np.zeros((p + q,))
          x_nought = np.concatenate((x_nought, arma_seed_states))
  
      # Optimization
      # Create vector with parameters
      if use_boxcox:
          params = np.concatenate(
              [np.array([BoxCox_lambda]), np.array([alpha])]
          )
      else:
          params = np.array([alpha])
      if beta is not None:
          params = np.concatenate([params, np.array([beta])])
      if phi is not None and phi != 1:
          use_damped_trend = True
          params = np.concatenate([params, np.array([phi])])
      else:
          use_damped_trend = False
      params = np.concatenate([params, gamma_one_v, gamma_two_v])
      if ar_coeffs is not None:
          params = np.concatenate([params, ar_coeffs])
      if ma_coeffs is not None:
          params = np.concatenate([params, ma_coeffs])
      if use_boxcox:
          x_nought_untransformed = inv_boxcox(x_nought, BoxCox_lambda)
      else:
          x_nought_untransformed = x_nought
  
      objective_fn = partial(
          calcLikelihoodTBATS,
          use_boxcox=use_boxcox,
          use_trend=use_trend,
          use_damped_trend=use_damped_trend,
          use_arma_errors=use_arma_errors,
          y=y,
          y_trans=y_trans,
          seasonal_periods=seasonal_periods,
          k_vector=k_vector,
          tau=tau,
          w_transpose=w_transpose,
          F=F,
          g=g,
          gamma_bold=gamma_bold,
          x_nought=x_nought,
          x_nought_untransformed=x_nought_untransformed,
          bc_lower_bound=bc_lower_bound,
          bc_upper_bound=bc_upper_bound,
          p=p,
          q=q,
      )
      # Solve optimization problem
      optim_params = minimize(
          objective_fn, params, method="Nelder-Mead"
      ).x
  
      (
          optim_BoxCox_lambda,
          optim_alpha,
          optim_beta,
          optim_phi,
          optim_gamma_one_v,
          optim_gamma_two_v,
          optim_ar_coeffs,
          optim_ma_coeffs,
      ) = extract_params(
          optim_params,
          use_boxcox,
          use_trend,
          use_damped_trend,
          use_arma_errors,
          seasonal_periods,
          p,
          q,
      )
  
      w_transpose = updateTBATSWMatrix(
          w_transpose,
          optim_phi,
          tau,
          optim_ar_coeffs,
          optim_ma_coeffs,
          p,
          q,
      )
      g = updateTBATSGMatrix(
          g,
          gamma_bold,
          optim_alpha,
          optim_beta,
          k_vector,
          optim_gamma_one_v,
          optim_gamma_two_v,
      )
      F = updateTBATSFMatrix(
          F,
          optim_phi,
          optim_alpha,
          optim_beta,
          gamma_bold,
          optim_ar_coeffs,
          optim_ma_coeffs,
          p,
          q,
          tau,
      )
  
      fitted, errors, x = calcTBATSFaster(
          y_trans, w_transpose, g, F, x_nought
      )
  
      sigma2 = np.sum(errors * errors) / len(y_trans)
  
      # Calculate log-likelihood
      if use_boxcox:
          log_likelihood = len(y_trans) * np.log(
              np.nansum(errors**2)
          ) - 2 * (optim_BoxCox_lambda - 1) * np.nansum(np.log(y))
      else:
          log_likelihood = len(y_trans) * np.log(np.nansum(errors**2))
  
      kval = len(optim_params) + x_nought.shape[0]
      aic = log_likelihood + 2 * kval
      aic
  
      res = {
          "fitted": fitted,
          "errors": errors,
          "sigma2": sigma2,
          "aic": aic,
          "optim_params": optim_params,
          "F": F,
          "w_transpose": w_transpose,
          "g": g,
          "x": x,
          "k_vector": k_vector,
          "BoxCox_lambda": optim_BoxCox_lambda,
      }
  
      return res
  
imports: import warnings
  from functools import partial
  import numpy
  import pandas
  import scipy.linalg
  import statsmodels.api
  from numba import njit
  from numpy.polynomial.polynomial import Polynomial
  from scipy.special import inv_boxcox
  from scipy.stats import boxcox
  from scipy.optimize import minimize
  from statsmodels.tsa.stattools import adfuller
  from .arima import auto_arima_f
  from .utils import NOGIL, CACHE
label_desc: Use image node_id 15 for calling a global function with example usage: tbats_model_generator(y, seasonal_periods, k_vector, use_boxcox, bc_lower_bound, bc_upper_bound, use_trend, use_damped_trend, use_arma_errors, ar_coeffs, ma_coeffs) and returns: res