code: def fourier(x, period, K, h=None):
      if h is None:
          times = np.arange(1, len(x) + 1)
      if h is not None:
          times = np.arange(len(x) + 1, len(x) + h + 1)
      # compute periods of all fourier terms
      # numba doesnt support list comprehension
      len_p = 0
      for k in K:
          if k > 0:
              len_p += k
      p = np.full(len_p, fill_value=np.nan)
      idx = 0
      for j, p_ in enumerate(period):
          if K[j] > 0:
              p[idx : (idx + K[j])] = np.arange(1, K[j] + 1) / period[j]
              idx += K[j]
      p = np.unique(p)
      # Remove columns where sinpi=0
      k = np.abs(2 * p - np.round(2 * p, 0, np.empty_like(p))) > smalno
      # Compute matrix of fourier terms
      X = np.full((len(times), 2 * len(p)), fill_value=np.nan)
      for j in range(len(p)):
          if k[j]:
              X[:, 2 * j - 1] = sinpi(2 * p[j] * times)
          X[:, 2 * j] = cospi(2 * p[j] * times)
      X = X[:, ~np.isnan(X.sum(axis=0))]
      return X
  
imports: import math
  from collections import namedtuple
  from typing import Tuple
  import numpy
  from numba import njit
  from numba.typed import List
  from statsmodels.tsa.seasonal import seasonal_decompose
  from .utils import _calculate_intervals, CACHE, NOGIL
label_desc: Use image node_id 11 for calling a global function with example usage: fourier(x, period, K, h) and returns: X