code: def split_from_end_by_blocks(
      self,
      horizon: int,
      context: Optional[int] = None,
      n_rolls: int = 1,
      n_blocks: int = 1,
      shift: Optional[int] = None,
      raise_error: bool = True,
  ) -> Tuple[TimeSeriesCorpus, TimeSeriesCorpus]:
      shift = shift or horizon
      train_scopes = []
      test_scopes = []
      # assert self.instances == self.scopes
      for ts_id, scope in self.scopes:
          block_size = len(self.instances[ts_id][scope]) // n_blocks
          ini = scope.start or 0
          for i in range(n_blocks):
              start = ini + i * block_size
              stop = start + block_size
              new_start = stop - shift * (n_rolls - 1) - horizon
              test_start = (
                  start if context is None else new_start - context
              )
              if test_start < start:
                  err_msg = (
                      f"Scope {ts_id}, requested {test_start}:{stop} is not "
                      f"contained by the current block {start}:{top}."
                  )
                  if raise_error:
                      raise ValueError(err_msg)
                  warnings.warn(
                      f"{err_msg} No scope added to test split."
                  )
                  train_scopes.append((ts_id, slice(start, stop)))
              else:
                  test_scopes.append((ts_id, slice(test_start, stop)))
                  train_scopes.append((ts_id, slice(start, new_start)))
      train_corpus = TimeSeriesCorpus(
          self.instances,
          train_scopes,
          categorical_encoders=self.categorical_encoders,
          numerical_encoders=self.numerical_scalers,
          add_series_id=self.add_series_id,
      )
      test_corpus = TimeSeriesCorpus(
          self.instances,
          test_scopes,
          categorical_encoders=self.categorical_encoders,
          numerical_encoders=self.numerical_scalers,
          add_series_id=self.add_series_id,
      )
      return train_corpus, test_corpus
  
imports: from __future__ import annotations
  from typing import List, Tuple, Dict, Union, Sequence, Optional, Callable, overload
  from operator import eq
  from collections import defaultdict
  import warnings
  from sklearn.preprocessing import LabelEncoder, StandardScaler
  from numpy import ndarray
  from tqdm import tqdm
  import numpy
  import pandas
  import torch
label_desc: Use image node_id 9 for calling the TimeSeriesCorpus obj's underlying member method code with example usage: obj.split_from_end_by_blocks(horizon, context, n_rolls, n_blocks, shift, raise_error) and returns: train_corpus,  test_corpus