class_docstr: Tests the `create_lagged_training_data` function defined in `darts.utils.data.tabularization`. There are broadly
  two 'groups' of tests defined in this module:
      1. 'Generated Test Cases': these test that `create_lagged_training_data` produces the same outputs
      as a simplified implementation of the 'time intersection' feature generation method (see
      `darts.utils.data.tabularization` for further details). For these tests, the 'correct answer' is not
      directly specified; instead, it is generated from a set of input parameters using the set of simplified
      functions. The rationale behind this approach is that it allows for many different combinations of input
      values to be effortlessly tested. The drawback of this, however, is that the correctness of these tests
      assumes that the simplified functions have been implemented correctly - if this isn't the case, then these
      tests are not to be trusted. In saying this, these simplified functions are significantly easier to
      understand and debug than the `create_lagged_training_data` function they're helping to test.
      2. 'Specified Test Cases': these test that `create_lagged_training_data` returns an exactly specified
      output; these specified outputs are *not* 'generated' by another function. Although these 'specified'
      test cases tend to be simpler and less extensive than the 'generated' test cases, their correctness does
      not assume the correct implementation of any other function.
class_docstr_tok: ["Tests","the","`","create_lagged_training_data","`","function","defined","in","`","darts.utils.data.tabularization","`",".","There","are","broadly","two","'groups","'","of","tests","defined","in","this","module",":","1",".","'Generated","Test","Cases","'",":","these","test","that","`","create_lagged_training_data","`","produces","the","same","outputs","as","a","simplified","implementation","of","the","'time","intersection","'","feature","generation","method","(","see","`","darts.utils.data.tabularization","`","for","further","details",")",".","For","these","tests",",","the","'correct","answer","'","is","not","directly","specified",";","instead",",","it","is","generated","from","a","set","of","input","parameters","using","the","set","of","simplified","functions",".","The","rationale","behind","this","approach","is","that","it","allows","for","many","different","combinations","of","input","values","to","be","effortlessly","tested",".","The","drawback","of","this",",","however",",","is","that","the","correctness","of","these","tests","assumes","that","the","simplified","functions","have","been","implemented","correctly","-","if","this","is","n't","the","case",",","then","these","tests","are","not","to","be","trusted",".","In","saying","this",",","these","simplified","functions","are","significantly","easier","to","understand","and","debug","than","the","`","create_lagged_training_data","`","function","they","'re","helping","to","test",".","2",".","'Specified","Test","Cases","'",":","these","test","that","`","create_lagged_training_data","`","returns","an","exactly","specified","output",";","these","specified","outputs","are","*","not","*","'generated","'","by","another","function",".","Although","these","'specified'","test","cases","tend","to","be","simpler","and","less","extensive","than","the","'generated","'","test","cases",",","their","correctness","does","not","assume","the","correct","implementation","of","any","other","function","."]
docstr: Helper function that creates the lagged features 'block' of a specific
  `series` (i.e. either `target_series`, `past_covariates`, or `future_covariates`);
  the feature matrix `X` is formed by concatenating the blocks of all of the specified
  series along the components axis. If `lags` is `None`, then `None` will be returned in
  lieu of an array. Please refer to the `create_lagged_features` docstring for further
  details about the structure of the `X` feature matrix.
  
  The returned `X_block` is constructed by looping over each time in `feature_times`,
  finding the index position of that time in the series, and then for each lag value in
  `lags`, offset this index position by a particular lag value; this offset index is then
  used to extract all of the components at a single lagged time.
  
  Unlike the implementation found in `darts.utils.data.tabularization`, this function doesn't
  use any 'vectorisation' tricks, which makes it slower to run, but more easily interpretable.
  
  Some of the times in `feature_times` may occur before the start *or* after the end of `series`;
  see the docstrings of `get_feature_times_past` and `get_feature_times_future` for why this is the
  case. Because of this, we need to prepend or append these 'extended times' to `series.time_index`
  before searching for the index of each time in the series. Even though the integer indices of the
  'extended times' won't be contained within the original `series`, offsetting these found indices
  by the requested lag value should 'bring us back' to a time within the original, unextended `series`.
  However, if we've prepended times to `series.time_index`, we have to note that all of the indices will
  be 'bumped up' by the number of values we've prepended, even after offsetting by a lag value. For example,
  if we extended `series.time_index` by prepending two values to the start, the integer index of the first
  actual value in `series` will occur at an index of `2` instead of `0`. To 'undo' this, we must subtract off
  the number of prepended value from the lag-offseted indices before retrieving values from `series`.
docstr_tok: ["Helper","function","that","creates","the","lagged","features","'block","'","of","a","specific","`","series","`","(","i.e",".","either","`","target_series","`",",","`","past_covariates","`",",","or","`","future_covariates","`",")",";","the","feature","matrix","`","X","`","is","formed","by","concatenating","the","blocks","of","all","of","the","specified","series","along","the","components","axis",".","If","`","lags","`","is","`","None","`",",","then","`","None","`","will","be","returned","in","lieu","of","an","array",".","Please","refer","to","the","`","create_lagged_features","`","docstring","for","further","details","about","the","structure","of","the","`","X","`","feature","matrix",".","The","returned","`","X_block","`","is","constructed","by","looping","over","each","time","in","`","feature_times","`",",","finding","the","index","position","of","that","time","in","the","series",",","and","then","for","each","lag","value","in","`","lags","`",",","offset","this","index","position","by","a","particular","lag","value",";","this","offset","index","is","then","used","to","extract","all","of","the","components","at","a","single","lagged","time",".","Unlike","the","implementation","found","in","`","darts.utils.data.tabularization","`",",","this","function","doesn't","use","any","'vectorisation","'","tricks",",","which","makes","it","slower","to","run",",","but","more","easily","interpretable",".","Some","of","the","times","in","`","feature_times","`","may","occur","before","the","start","*","or","*","after","the","end","of","`","series","`",";","see","the","docstrings","of","`","get_feature_times_past","`","and","`","get_feature_times_future","`","for","why","this","is","the","case",".","Because","of","this",",","we","need","to","prepend","or","append","these","'extended","times","'","to","`","series.time_index","`","before","searching","for","the","index","of","each","time","in","the","series",".","Even","though","the","integer","indices","of","the","'extended","times","'","wo","n't","be","contained","within","the","original","`","series","`",",","offsetting","these","found","indices","by","the","requested","lag","value","should","'bring","us","back","'","to","a","time","within","the","original",",","unextended","`","series","`",".","However",",","if","we","'ve","prepended","times","to","`","series.time_index","`",",","we","have","to","note","that","all","of","the","indices","will","be","'bumped","up","'","by","the","number","of","values","we","'ve","prepended",",","even","after","offsetting","by","a","lag","value",".","For","example",",","if","we","extended","`","series.time_index","`","by","prepending","two","values","to","the","start",",","the","integer","index","of","the","first","actual","value","in","`","series","`","will","occur","at","an","index","of","`","2","`","instead","of","`","0","`",".","To","'undo","'","this",",","we","must","subtract","off","the","number","of","prepended","value","from","the","lag-offseted","indices","before","retrieving","values","from","`","series","`","."]
code: def construct_X_block(
      series: TimeSeries,
      feature_times: pd.Index,
      lags: Optional[Sequence[int]],
  ) -> np.array:
      """
      Helper function that creates the lagged features 'block' of a specific
      `series` (i.e. either `target_series`, `past_covariates`, or `future_covariates`);
      the feature matrix `X` is formed by concatenating the blocks of all of the specified
      series along the components axis. If `lags` is `None`, then `None` will be returned in
      lieu of an array. Please refer to the `create_lagged_features` docstring for further
      details about the structure of the `X` feature matrix.
  
      The returned `X_block` is constructed by looping over each time in `feature_times`,
      finding the index position of that time in the series, and then for each lag value in
      `lags`, offset this index position by a particular lag value; this offset index is then
      used to extract all of the components at a single lagged time.
  
      Unlike the implementation found in `darts.utils.data.tabularization`, this function doesn't
      use any 'vectorisation' tricks, which makes it slower to run, but more easily interpretable.
  
      Some of the times in `feature_times` may occur before the start *or* after the end of `series`;
      see the docstrings of `get_feature_times_past` and `get_feature_times_future` for why this is the
      case. Because of this, we need to prepend or append these 'extended times' to `series.time_index`
      before searching for the index of each time in the series. Even though the integer indices of the
      'extended times' won't be contained within the original `series`, offsetting these found indices
      by the requested lag value should 'bring us back' to a time within the original, unextended `series`.
      However, if we've prepended times to `series.time_index`, we have to note that all of the indices will
      be 'bumped up' by the number of values we've prepended, even after offsetting by a lag value. For example,
      if we extended `series.time_index` by prepending two values to the start, the integer index of the first
      actual value in `series` will occur at an index of `2` instead of `0`. To 'undo' this, we must subtract off
      the number of prepended value from the lag-offseted indices before retrieving values from `series`.
      """
      if lags is None:
          X_block = None
      else:
          series_times = series.time_index
          is_range_idx = isinstance(series_times[0], int)
          # If series ends before last time in `feature_times`:
          add_to_end = series_times[-1] < feature_times[-1]
          # If series starts after first time in `feature_times`:
          add_to_start = series_times[0] > feature_times[0]
          # Either add to start *OR* add to end, we can't have both (see `get_feature_times_future`):
          if add_to_end:
              num_prepended = 0
              if is_range_idx:
                  # `+ 1` since `stop` index is exclusive:
                  series_times = pd.RangeIndex(
                      start=series_times[0],
                      stop=feature_times[-1] + 1,
                      step=series.freq,
                  )
              else:
                  series_times = pd.date_range(
                      start=series_times[0],
                      end=feature_times[-1],
                      freq=series.freq,
                  )
          elif add_to_start:
              num_prepended = (
                  series_times[0] - feature_times[0]
              ) // series.freq
              if is_range_idx:
                  # `+ 1` since `stop` index is exclusive:
                  series_times = pd.RangeIndex(
                      start=feature_times[0],
                      stop=series_times[-1] + 1,
                      step=series.freq,
                  )
              else:
                  series_times = pd.date_range(
                      start=feature_times[0],
                      end=series_times[-1],
                      freq=series.freq,
                  )
          else:
              num_prepended = 0
          array_vals = series.all_values(copy=False)[:, :, 0]
          X_block = []
          for time in feature_times:
              # Find position of time within series:
              time_idx = np.searchsorted(series_times, time)
              X_row = []
              for lag in lags:
                  # Offet by particular lag value:
                  idx_to_get = time_idx + lag
                  # Account for prepended values:
                  idx_to_get -= num_prepended
                  raise_if_not(
                      idx_to_get >= 0,
                      f"Unexpected case encountered: `time_idx + lag - num_prepended = {idx_to_get} < 0`.",
                  )
                  # Extract all components at this lagged time:
                  X_row.append(array_vals[idx_to_get, :].reshape(-1))
              # Concatenate together all lagged values into a single row:
              X_row = np.concatenate(X_row, axis=0)
              X_block.append(X_row)
          # Concatenate all rows (i.e. observations) together into a block:
          X_block = np.stack(X_block, axis=0)
      return X_block
  
imports: import warnings
  from itertools import product
  from typing import Optional, Sequence
  import numpy
  import pandas
  import pytest
  from darts import TimeSeries
  from darts import concatenate
  from darts.logging import get_logger, raise_if, raise_if_not, raise_log
  from darts.utils.data.tabularization import create_lagged_component_names, create_lagged_training_data
  from darts.utils.timeseries_generation import linear_timeseries
label_desc: Use image node_id 6 for calling the TestCreateLaggedTrainingData obj's underlying member method code with example usage: obj.construct_X_block(series, feature_times, lags) and returns: X_block