code: def tabularize_univariate_datetime(
      df,
      predict_mode=False,
      n_lags=0,
      n_forecasts=1,
      predict_steps=1,
      config_seasonality: Optional[configure.ConfigSeasonality] = None,
      config_events: Optional[configure.ConfigEvents] = None,
      config_country_holidays=None,
      config_lagged_regressors: Optional[
          configure.ConfigLaggedRegressors
      ] = None,
      config_regressors: Optional[
          configure.ConfigFutureRegressors
      ] = None,
      config_missing=None,
      prediction_frequency=None,
  ):
      """Create a tabular dataset from univariate timeseries for supervised forecasting.
      Note
      ----
      Data must have no gaps.
      If data contains missing values, they are ignored for the creation of the dataset.
      Parameters
      ----------
          df : pd.DataFrame
              Sequence of observations with original ``ds``, ``y`` and normalized ``t``, ``y_scaled`` columns
          config_seasonality : configure.ConfigSeasonality
              Configuration for seasonalities
          n_lags : int
              Number of lagged values of series to include as model inputs (aka AR-order)
          n_forecasts : int
              Number of steps to forecast into future
          config_events : configure.ConfigEvents
              User specified events, each with their upper, lower windows (int) and regularization
          config_country_holidays : configure.ConfigCountryHolidays
              Configurations (holiday_names, upper, lower windows, regularization) for country specific holidays
          config_lagged_regressors : configure.ConfigLaggedRegressors
              Configurations for lagged regressors
          config_regressors : configure.ConfigFutureRegressors
              Configuration for regressors
          predict_mode : bool
              Chooses the prediction mode
              Options
                  * (default) ``False``: Includes target values
                  * ``True``: Does not include targets but includes entire dataset as input
      Returns
      -------
          OrderedDict
              Model inputs, each of len(df) but with varying dimensions
              Note
              ----
              Contains the following data:
              Model Inputs
                  * ``time`` (np.array, float), dims: (num_samples, 1)
                  * ``seasonalities`` (OrderedDict), named seasonalities
                  each with features (np.array, float) - dims: (num_samples, n_features[name])
                  * ``lags`` (np.array, float), dims: (num_samples, n_lags)
                  * ``covariates`` (OrderedDict), named covariates,
                  each with features (np.array, float) of dims: (num_samples, n_lags)
                  * ``events`` (OrderedDict), events,
                  each with features (np.array, float) of dims: (num_samples, n_lags)
                  * ``regressors`` (OrderedDict), regressors,
                  each with features (np.array, float) of dims: (num_samples, n_lags)
          np.array, float
              Targets to be predicted of same length as each of the model inputs, dims: (num_samples, n_forecasts)
      """
      max_lags = get_max_num_lags(config_lagged_regressors, n_lags)
      n_samples = len(df) - max_lags + 1 - n_forecasts
      # data is stored in OrderedDict
      inputs = OrderedDict({})
  
      def _stride_time_features_for_forecasts(x):
          window_size = n_lags + n_forecasts
  
          if x.ndim == 1:
              shape = (n_samples, window_size)
          else:
              shape = (n_samples, window_size) + x.shape[1:]
  
          stride = x.strides[0]
          strides = (stride, stride) + x.strides[1:]
          start_index = max_lags - n_lags
          return np.lib.stride_tricks.as_strided(
              x[start_index:], shape=shape, strides=strides
          )
  
      def _stride_future_time_features_for_forecasts(x):
          return np.array(
              [
                  x[max_lags + i : max_lags + i + n_forecasts]
                  for i in range(n_samples)
              ],
              dtype=x.dtype,
          )
  
      def _stride_lagged_features(df_col_name, feature_dims):
          # only for case where max_lags > 0
          assert feature_dims >= 1
          series = df.loc[:, df_col_name].values
          # Added dtype=np.float64 to solve the problem with np.isnan for ubuntu test
          return np.array(
              [
                  series[i + max_lags - feature_dims : i + max_lags]
                  for i in range(n_samples)
              ],
              dtype=np.float32,
          )
  
      def _stride_timestamps_for_forecasts(x):
          # only for case where n_lags > 0
          if x.dtype != np.float64:
              dtype = np.datetime64
          else:
              dtype = np.float64
          return np.array(
              [
                  x[i + max_lags : i + max_lags + n_forecasts]
                  for i in range(n_samples)
              ],
              dtype=dtype,
          )
  
      # time is the time at each forecast step
      t = df.loc[:, "t"].values
      if max_lags == 0:
          assert n_forecasts == 1
          time = np.expand_dims(t, 1)
      else:
          time = _stride_time_features_for_forecasts(t)
      inputs["time"] = time  # contains n_lags + n_forecasts
  
      if prediction_frequency is not None:
          ds = df.loc[:, "ds"].values
          if max_lags == 0:  # is it rather n_lags?
              timestamps = np.expand_dims(ds, 1)
          else:
              timestamps = _stride_timestamps_for_forecasts(ds)
          inputs["timestamps"] = timestamps
  
      if config_seasonality is not None:
          seasonalities = seasonal_features_from_dates(
              df, config_seasonality
          )
          for name, features in seasonalities.items():
              if max_lags == 0:
                  seasonalities[name] = np.expand_dims(features, axis=1)
              else:
                  # stride into num_forecast at dim=1 for each sample, just like we did with time
                  seasonalities[
                      name
                  ] = _stride_time_features_for_forecasts(features)
          inputs["seasonalities"] = seasonalities
  
      if n_lags > 0 and "y" in df.columns:
          inputs["lags"] = _stride_lagged_features(
              df_col_name="y_scaled", feature_dims=n_lags
          )
  
      if config_lagged_regressors is not None and max_lags > 0:
          covariates = OrderedDict({})
          for covar in df.columns:
              if covar in config_lagged_regressors:
                  assert config_lagged_regressors[covar].n_lags > 0
                  window = config_lagged_regressors[covar].n_lags
                  covariates[covar] = _stride_lagged_features(
                      df_col_name=covar, feature_dims=window
                  )
          inputs["covariates"] = covariates
  
      # get the regressors features
      if config_regressors is not None:
          (
              additive_regressors,
              multiplicative_regressors,
          ) = make_regressors_features(df, config_regressors)
  
          regressors = OrderedDict({})
          if max_lags == 0:
              if additive_regressors is not None:
                  regressors["additive"] = np.expand_dims(
                      additive_regressors, axis=1
                  )
              if multiplicative_regressors is not None:
                  regressors["multiplicative"] = np.expand_dims(
                      multiplicative_regressors, axis=1
                  )
          else:
              if additive_regressors is not None:
                  additive_regressor_feature_windows = []
                  # additive_regressor_feature_windows_lagged = []
                  for i in range(0, additive_regressors.shape[1]):
                      # stride into num_forecast at dim=1 for each sample, just like we did with time
                      stride = _stride_time_features_for_forecasts(
                          additive_regressors[:, i]
                      )
                      additive_regressor_feature_windows.append(stride)
                  additive_regressors = np.dstack(
                      additive_regressor_feature_windows
                  )
                  regressors["additive"] = additive_regressors
  
              if multiplicative_regressors is not None:
                  multiplicative_regressor_feature_windows = []
                  for i in range(0, multiplicative_regressors.shape[1]):
                      stride = _stride_time_features_for_forecasts(
                          multiplicative_regressors[:, i]
                      )
                      multiplicative_regressor_feature_windows.append(
                          stride
                      )
                  multiplicative_regressors = np.dstack(
                      multiplicative_regressor_feature_windows
                  )
                  regressors[
                      "multiplicative"
                  ] = multiplicative_regressors
          inputs["regressors"] = regressors
  
      # get the events features
      if (
          config_events is not None
          or config_country_holidays is not None
      ):
          additive_events, multiplicative_events = make_events_features(
              df, config_events, config_country_holidays
          )
  
          events = OrderedDict({})
          if max_lags == 0:
              if additive_events is not None:
                  events["additive"] = np.expand_dims(
                      additive_events, axis=1
                  )
              if multiplicative_events is not None:
                  events["multiplicative"] = np.expand_dims(
                      multiplicative_events, axis=1
                  )
          else:
              if additive_events is not None:
                  additive_event_feature_windows = []
                  for i in range(0, additive_events.shape[1]):
                      # stride into num_forecast at dim=1 for each sample, just like we did with time
                      additive_event_feature_windows.append(
                          _stride_time_features_for_forecasts(
                              additive_events[:, i]
                          )
                      )
                  additive_events = np.dstack(
                      additive_event_feature_windows
                  )
                  events["additive"] = additive_events
  
              if multiplicative_events is not None:
                  multiplicative_event_feature_windows = []
                  # multiplicative_event_feature_windows_lagged = []
                  for i in range(0, multiplicative_events.shape[1]):
                      # stride into num_forecast at dim=1 for each sample, just like we did with time
                      multiplicative_event_feature_windows.append(
                          _stride_time_features_for_forecasts(
                              multiplicative_events[:, i]
                          )
                      )
                  multiplicative_events = np.dstack(
                      multiplicative_event_feature_windows
                  )
                  events["multiplicative"] = multiplicative_events
          inputs["events"] = events
  
      if predict_mode:
          targets = np.empty_like(time[:, n_lags:])
          targets = np.nan_to_num(targets)
      else:
          targets = _stride_future_time_features_for_forecasts(
              df["y_scaled"].values
          )
  
      tabularized_input_shapes_str = ""
      for key, value in inputs.items():
          if key in [
              "seasonalities",
              "covariates",
              "events",
              "regressors",
          ]:
              for name, period_features in value.items():
                  tabularized_input_shapes_str += (
                      f"    {name} {key} {period_features}\n"
                  )
          else:
              tabularized_input_shapes_str += (
                  f"    {key} {value.shape} \n"
              )
      log.debug(
          f"Tabularized inputs shapes: \n{tabularized_input_shapes_str}"
      )
  
      return inputs, targets, config_missing.drop_missing
  
imports: import logging
  from collections import OrderedDict, defaultdict
  from datetime import datetime
  from typing import Optional
  import numpy
  import pandas
  import torch
  from torch.utils.data.dataset import Dataset
  from neuralprophet import configure, utils
  from neuralprophet.df_utils import get_max_num_lags
  from neuralprophet.hdays_utils import get_country_holidays
label_desc: Use image node_id 1 for calling a global function with example usage: tabularize_univariate_datetime(df, predict_mode, n_lags, n_forecasts, predict_steps, config_seasonality, config_events, config_country_holidays, config_lagged_regressors, config_regressors, config_missing, prediction_frequency) and returns: inputs,  targets,  config_missing, np, np, np, np