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: Create a `tf.data.Dataset` from a layer_op (as a generator).
  
  :return: a `tf.data.Dataset`
docstr_tok: ["Create","a","`","tf.data.Dataset","`","from","a","layer_op","(","as","a","generator",")",".",":","return",":","a","`","tf.data.Dataset","`"]
code: def _dataset_from_generator(self):
      """
      Create a `tf.data.Dataset` from a layer_op (as a generator).
  
      :return: a `tf.data.Dataset`
      """
      tf.logging.info("Initialising dataset from generator...")
  
      if self._num_threads < 2 or not self.shuffle:
          window_generator = self
      else:
          # self._enqueuer = GeneratorEnqueuer(
          #     self(),
          #     use_multiprocessing=True,
          #     wait_time=0.01,
          #     seed=self._seed)
          self._enqueuer = GeneratorEnqueuer(
              self(), use_multiprocessing=True
          )
          self._enqueuer.start(
              workers=self._num_threads,
              max_queue_size=self.queue_length,
          )
          window_generator = self._enqueuer.get
  
      # dataset from generator
      dataset = tf.data.Dataset.from_generator(
          generator=window_generator,
          output_types=self.tf_dtypes,
          output_shapes=self.tf_shapes,
      )
  
      # dataset: slice the n-element window into n single windows
      dataset = dataset.flat_map(
          map_func=tf.data.Dataset.from_tensor_slices
      )
      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 11 for calling the ImageWindowDataset obj's underlying member method code with example usage: obj._dataset_from_generator() and returns: dataset