class_docstr: This class creates a ``tf.data.Dataset`` instance from
  a sampler's layer_op function or generator.
  
  If ``from_generator``, ``Dataset.from_generator`` interface will be used,
  ``Dataset.map`` interface will be used otherwise::
  
      if the windows are from a image reader,
      the total number of windows produced
      will be: `epoch x n_subjects x windows_per_image`
  
      if the windows are from a generator,
      the total number of windows produced
      will be: "iterations from the generator" x num_threads
class_docstr_tok: ["This","class","creates","a","``","tf.data.Dataset","``","instance","from","a","sampler","'s","layer_op","function","or","generator",".","If","``","from_generator","``",",","``","Dataset.from_generator","``","interface","will","be","used",",","``","Dataset.map","``","interface","will","be","used","otherwise",":",":","if","the","windows","are","from","a","image","reader",",","the","total","number","of","windows","produced","will","be",":","`","epoch","x","n_subjects","x","windows_per_image","`","if","the","windows","are","from","a","generator",",","the","total","number","of","windows","produced","will","be",":","``","iterations","from","the","generator","''","x","num_threads"]
docstr: dataset: batch and shuffle
  
  :param dataset: a `tf.data.Dataset` instance
  :return: a `tf.data.Dataset` instance
docstr_tok: ["dataset",":","batch","and","shuffle",":","param","dataset",":","a","`","tf.data.Dataset","`","instance",":","return",":","a","`","tf.data.Dataset","`","instance"]
code: def dataset_preprocessing(self, dataset):
      """
      dataset: batch and shuffle
  
      :param dataset: a `tf.data.Dataset` instance
      :return: a `tf.data.Dataset` instance
      """
      dataset = dataset.repeat(self.epoch)
      dataset = dataset.prefetch(buffer_size=self.queue_length)
      if self.shuffle:
          # locally shuffle the buffer of image windows
          dataset = dataset.shuffle(
              buffer_size=self.queue_length, seed=self._seed
          )
  
      if self.smaller_final_batch_mode == "drop":
          # drop the remainder if there's not enough windows to
          # form a batch, so that we have a fixed batch size.
          # dataset = dataset.apply(tf.contrib.data.batch_and_drop_remainder(
          #     batch_size=self.batch_size))
          # new API since TF 1.10
          dataset = dataset.batch(
              batch_size=self.batch_size, drop_remainder=True
          )
          return dataset
  
      dataset = dataset.batch(batch_size=self.batch_size)
  
      if (
          self.smaller_final_batch_mode == "dynamic"
          and self.batch_size > 1
      ):
          return dataset
  
      # self.smaller_final_batch_mode is 'pad'
      # if self.batch_size == 1 no actual padding
      # but this function will set the output shapes properly.
      def _pad_batch(batch_size):
          def _pad_batch_func(input_tensor_dict):
              """
              function to pad the batch dim to `batch_size`.
              (assuming the input dataset is a dictionary-based one)
              """
              out_dict = {}
              for in_name in list(input_tensor_dict):
                  in_var = input_tensor_dict[in_name]
                  var_shape = in_var.shape.as_list()
                  if batch_size > 1:
                      paddings = [[0, 0] for _ in in_var.shape]
                      paddings[0][1] = batch_size - tf.shape(in_var)[0]
                      in_var = tf.pad(
                          in_var,
                          paddings,
                          "CONSTANT",
                          constant_values=-1,
                      )
                  var_shape[0] = batch_size
                  in_var.set_shape(var_shape)
                  out_dict[in_name] = in_var
              return out_dict
  
          return _pad_batch_func
  
      dataset = dataset.map(_pad_batch(self.batch_size))
      return dataset
  
imports: from __future__ import absolute_import, division, print_function
  import inspect
  import numpy
  import tensorflow
  from tensorflow.python.data.util import nest
  from tensorflow.python.keras.utils import GeneratorEnqueuer
  from niftynet.engine.image_window import ImageWindow, N_SPATIAL, LOCATION_FORMAT, BUFFER_POSITION_NP_TYPE
  from niftynet.io.misc_io import squeeze_spatial_temporal_dim
  from niftynet.layer.base_layer import Layer
  from niftynet.utilities.util_common import look_up_operations
label_desc: Use image node_id 9 for calling the ImageWindowDataset obj's underlying member method code with example usage: obj.dataset_preprocessing(dataset) and returns: dataset, dataset, dataset, _pad_batch_func, out_dict