code: def data_generator(
      self,
      data_group_labels=None,
      perpetual=False,
      case_list=None,
      yield_data=True,
      verbose=False,
      batch_size=1,
      just_one_batch=False,
  ):
      data_groups = self.get_data_groups(data_group_labels)
  
      if case_list is None:
          case_list = self.cases
  
      if case_list is None or case_list == "":
          print("No cases found. Yielding None.")
          yield None
  
      data_batch_labels = ["casename"]
      for data_group in data_groups:
          data_batch_labels += [
              data_group.label,
              data_group.label + "_augmentation_string",
              data_group.label + "_affine",
          ]
  
      data_batch = {label: [] for label in data_batch_labels}
  
      while True:
          np.random.shuffle(case_list)
  
          for case_idx, case_name in enumerate(case_list):
              if self.source == "hdf5":
                  case_name_string = (
                      data_groups[0]
                      .data_casenames[case_name][0]
                      .decode("utf-8")
                  )
              else:
                  case_name_string = case_name
  
              if verbose:
                  print(
                      (
                          "Working on image.. ",
                          case_idx,
                          "at",
                          case_name_string,
                      )
                  )
  
              # Is error-catching useful here?
              if True:
                  # try:
                  self.load_case_data(case_name)
              # except KeyboardInterrupt:
              # raise
              # except:
              # print 'Hit error on', case_name, 'skipping.'
              # yield False
  
              recursive_augmentation_generator = (
                  self.recursive_augmentation(
                      data_groups, augmentation_num=0
                  )
              )
  
              for i in range(self.multiplier):
                  next(recursive_augmentation_generator)
  
                  if yield_data:
                      # TODO: This section is terribly complex and repetitive. Revise!
  
                      for data_idx, data_group in enumerate(
                          data_groups
                      ):
                          if len(self.augmentations) == 0:
                              data_batch[data_group.label].append(
                                  data_group.preprocessed_case[0]
                              )
                          else:
                              data_batch[data_group.label].append(
                                  data_group.augmentation_cases[-1][0]
                              )
  
                          data_batch[
                              data_group.label + "_augmentation_string"
                          ].append(data_group.augmentation_strings[-1])
                          data_batch[
                              data_group.label + "_affine"
                          ].append(data_group.preprocessed_affine)
  
                      data_batch["casename"].append(case_name_string)
  
                      if (
                          len(data_batch[data_groups[0].label])
                          == batch_size
                      ):
                          for label in data_batch:
                              data_batch[label] = np.stack(
                                  data_batch[label]
                              )
  
                          if just_one_batch:
                              while True:
                                  yield data_batch
                          else:
                              yield data_batch
  
                          data_batch = {
                              label: [] for label in data_batch_labels
                          }
  
                  else:
                      yield True
  
          if not perpetual:
              yield None
              break
  
imports: import os
  import csv
  import numpy
  import tables
  import copy
  from tqdm import tqdm
  from deepneuro.augmentation.augment import Copy
  from deepneuro.utilities.conversion import read_image_files
  from deepneuro.data.data_group import DataGroup
  from deepneuro.data.data_load import parse_directories, parse_filepaths, parse_hdf5, parse_csv, parse_numpy
  from deepneuro.utilities.util import add_parameter
label_desc: Use image node_id 16 for calling the DataCollection obj's underlying member method code with example usage: obj.data_generator(data_group_labels, perpetual, case_list, yield_data, verbose, batch_size, just_one_batch) without return types