class_docstr: creates the training/validation batch generator. Samples n_batch_size patients (draws a slice from each patient if 2D)
  from the data set while maintaining foreground-class balance. Returned patches are cropped/padded to pre_crop_size.
  Actual patch_size is obtained after data augmentation.
  :param data: data dictionary as provided by 'load_dataset'.
  :param batch_size: number of patients to sample for the batch
  :return dictionary containing the batch data (b, c, x, y, (z)) / seg (b, 1, x, y, (z)) / pids / class_target
class_docstr_tok: ["creates","the","training\/validation","batch","generator",".","Samples","n_batch_size","patients","(","draws","a","slice","from","each","patient","if","2D",")","from","the","data","set","while","maintaining","foreground-class","balance",".","Returned","patches","are","cropped\/padded","to","pre_crop_size",".","Actual","patch_size","is","obtained","after","data","augmentation",".",":","param","data",":","data","dictionary","as","provided","by","'load_dataset","'",".",":","param","batch_size",":","number","of","patients","to","sample","for","the","batch",":","return","dictionary","containing","the","batch","data","(","b",",","c",",","x",",","y",",","(","z",")",")","\/","seg","(","b",",","1",",","x",",","y",",","(","z",")",")","\/","pids","\/","class_target"]
code: def generate_train_batch(self):
      batch_data, batch_segs, batch_pids, batch_targets = [], [], [], []
      class_targets_list = [
          v["class_target"] for (k, v) in self._data.items()
      ]
  
      # samples patients towards equilibrium of foreground classes on a roi-level (after randomly sampling the ratio "batch_sample_slack).
      batch_ixs = dutils.get_class_balanced_patients(
          class_targets_list,
          self.batch_size,
          self.cf.head_classes - 1,
          slack_factor=self.cf.batch_sample_slack,
      )
      patients = list(self._data.items())
  
      for b in batch_ixs:
          patient = patients[b][1]
          all_data = np.load(patient["data"], mmap_mode="r")
          data = all_data[0]
          seg = all_data[1].astype("uint8")
          batch_pids.append(patient["pid"])
          batch_targets.append(patient["class_target"])
          batch_data.append(data[np.newaxis])
          batch_segs.append(seg[np.newaxis])
  
      data = np.array(batch_data)
      seg = np.array(batch_segs).astype(np.uint8)
      class_target = np.array(batch_targets)
      return {
          "data": data,
          "seg": seg,
          "pid": batch_pids,
          "class_target": class_target,
      }
  
imports: import numpy
  import os
  from collections import OrderedDict
  import pandas
  import pickle
  import time
  import subprocess
  import utils.dataloader_utils
  from batchgenerators.dataloading.data_loader import SlimDataLoaderBase
  from batchgenerators.transforms.spatial_transforms import MirrorTransform
  from batchgenerators.transforms.abstract_transforms import Compose
  from batchgenerators.dataloading.multi_threaded_augmenter import MultiThreadedAugmenter
  from batchgenerators.dataloading import SingleThreadedAugmenter
  from batchgenerators.transforms.spatial_transforms import SpatialTransform
  from batchgenerators.transforms.crop_and_pad_transforms import CenterCropTransform
  from batchgenerators.transforms.utility_transforms import ConvertSegToBoundingBoxCoordinates
label_desc: Use image node_id 2 for calling the BatchGenerator obj's underlying member method code with example usage: obj.generate_train_batch() and returns: dict