docstr: Private method to simulate streams. _ids_to_stats is a decorated function that is vectorised
  over the parallel streams. Not sufficient just to write a normal vectorised numpy implementation as this
  can lead to OOM errors (when trying to store (n+t_max) x (n+t_max) x n_bootstraps matrices of floats).
  However, we will store the boolean matrix of this size as it faster to compute this way (and 64x smaller).
  To further reduce memory requirements, _ids_to_stats can be called for batches of streams, so that
  the ids array is of shape batch_size x (n+t_max) x (n+t_max).
docstr_tok: ["Private","method","to","simulate","streams",".","_ids_to_stats","is","a","decorated","function","that","is","vectorised","over","the","parallel","streams",".","Not","sufficient","just","to","write","a","normal","vectorised","numpy","implementation","as","this","can","lead","to","OOM","errors","(","when","trying","to","store","(","n+t_max",")","x","(","n+t_max",")","x","n_bootstraps","matrices","of","floats",")",".","However",",","we","will","store","the","boolean","matrix","of","this","size","as","it","faster","to","compute","this","way","(","and","64x","smaller",")",".","To","further","reduce","memory","requirements",",","_ids_to_stats","can","be","called","for","batches","of","streams",",","so","that","the","ids","array","is","of","shape","batch_size","x","(","n+t_max",")","x","(","n+t_max",")","."]
code: def _simulate_streams(self, t_max: int) -> np.ndarray:
      """
      Private method to simulate streams. _ids_to_stats is a decorated function that is vectorised
      over the parallel streams. Not sufficient just to write a normal vectorised numpy implementation as this
      can lead to OOM errors (when trying to store (n+t_max) x (n+t_max) x n_bootstraps matrices of floats).
      However, we will store the boolean matrix of this size as it faster to compute this way (and 64x smaller).
      To further reduce memory requirements, _ids_to_stats can be called for batches of streams, so that
      the ids array is of shape batch_size x (n+t_max) x (n+t_max).
      """
      n_windows = len(self.window_sizes)
      stats = np.zeros((self.n_bootstraps, t_max, n_windows))
      n_batches = int(np.ceil(self.n_bootstraps / self.batch_size))
      idxs = np.array_split(np.arange(self.n_bootstraps), n_batches)
      batches = (
          enumerate(
              tqdm(
                  idxs,
                  "Computing thresholds over %d batches" % n_batches,
              )
          )
          if self.verbose
          else enumerate(idxs)
      )
      for b, idx in batches:
          xs = np.random.randn(len(idx), self.n + t_max)
          ids = xs[:, None, :] >= xs[:, :, None]
          stats[idx, :, :] = _ids_to_stats(
              ids[:, : self.n, :],
              ids[:, self.n :, :],
              np.asarray(self.window_sizes),
          )
  
      # Remove stats prior to windows being full
      for k, ws in enumerate(self.window_sizes):
          stats[:, : ws - 1, k] = np.nan
      return stats
  
imports: import numpy
  from typing import Any, Callable, List, Optional, Union
  from alibi_detect.base import DriftConfigMixin
  from alibi_detect.cd.base_online import BaseUniDriftOnline
  from alibi_detect.utils.misc import quantile
  import numba
  from tqdm import tqdm
  import warnings
label_desc: Use image node_id 4 for calling the CVMDriftOnline obj's underlying member method code with example usage: obj._simulate_streams(t_max) and returns: stats