code: def auto_theta(
      y,
      m,
      model=None,
      initial_smoothed=None,
      alpha=None,
      theta=None,
      nmse=3,
      decomposition_type="multiplicative",
  ):
      # converting params to floats
      # to improve numba compilation
      if initial_smoothed is None:
          initial_smoothed = np.nan
      if alpha is None:
          alpha = np.nan
      if theta is None:
          theta = np.nan
      if nmse < 1 or nmse > 30:
          raise ValueError("nmse out of range")
      # constan values
      if is_constant(y):
          thetamodel(
              y=y,
              m=m,
              modeltype="STM",
              nmse=nmse,
              initial_smoothed=np.mean(y) / 2,
              alpha=0.5,
              theta=2.0,
          )
      # seasonal decomposition if needed
      decompose = False
      # seasonal test
      if m >= 4:
          r = acf(y, nlags=m, fft=False)[1:]
          stat = np.sqrt((1 + 2 * np.sum(r[:-1] ** 2)) / len(y))
          decompose = np.abs(r[-1]) / stat > norm.ppf(0.95)
  
      data_positive = min(y) > 0
      if decompose:
          # change decomposition type if data is not positive
          if (
              decomposition_type == "multiplicative"
              and not data_positive
          ):
              decomposition_type = "additive"
          y_decompose = seasonal_decompose(
              y, model=decomposition_type, period=m
          ).seasonal
          if decomposition_type == "multiplicative" and any(
              y_decompose < 0.01
          ):
              decomposition_type = "additive"
              y_decompose = seasonal_decompose(
                  y, model="additive", period=m
              ).seasonal
          if decomposition_type == "additive":
              y = y - y_decompose
          else:
              y = y / y_decompose
          seas_forecast = _seasonal_naive(
              y=y_decompose, h=m, season_length=m, fitted=False
          )
  
      # validate model
      if model not in [None, "STM", "OTM", "DSTM", "DOTM"]:
          raise ValueError("Invalid model type")
  
      n = len(y)
      npars = 3
      # non-optimized tiny datasets
      if n <= npars:
          raise NotImplementedError("tiny datasets")
      if model is None:
          modeltype = ["STM", "OTM", "DSTM", "DOTM"]
      else:
          modeltype = [model]
  
      best_ic = np.inf
      for mtype in modeltype:
          fit = thetamodel(
              y=y,
              m=m,
              modeltype=mtype,
              nmse=nmse,
              initial_smoothed=initial_smoothed,
              alpha=alpha,
              theta=theta,
          )
          fit_ic = fit["mse"]
          if not np.isnan(fit_ic):
              if fit_ic < best_ic:
                  model = fit
                  best_ic = fit_ic
      if np.isinf(best_ic):
          raise Exception("no model able to be fitted")
  
      if decompose:
          if decomposition_type == "multiplicative":
              model["residuals"] = model["residuals"] * y_decompose
          else:
              model["residuals"] = model["residuals"] + y_decompose
          model["decompose"] = decompose
          model["decomposition_type"] = decomposition_type
          model["seas_forecast"] = dict(seas_forecast)
      return model
  
imports: import math
  from typing import Tuple
  import numpy
  from numba import njit
  from scipy.stats import norm
  from statsmodels.tsa.seasonal import seasonal_decompose
  from statsmodels.tsa.stattools import acf
  from .ets import restrict_to_bounds, results
  from .utils import _seasonal_naive, _repeat_val_seas, CACHE, NOGIL
label_desc: Use image node_id 16 for calling a global function with example usage: auto_theta(y, m, model, initial_smoothed, alpha, theta, nmse, decomposition_type) and returns: model