class_docstr: This class initialises an application by building a TF graph,
  and maintaining a session. It controls the
  starting/stopping of an application. Applications should be
  implemented by inheriting ``niftynet.application.base_application``
  to be compatible with this driver.
class_docstr_tok: ["This","class","initialises","an","application","by","building","a","TF","graph",",","and","maintaining","a","session",".","It","controls","the","starting\/stopping","of","an","application",".","Applications","should","be","implemented","by","inheriting","``","niftynet.application.base_application","``","to","be","compatible","with","this","driver","."]
docstr: Initialise a TF graph, connect data sampler and network within
  the graph context, run training loops or inference loops.
  
  :param application: a niftynet application
  :param graph: default base graph to run the application
  :return:
docstr_tok: ["Initialise","a","TF","graph",",","connect","data","sampler","and","network","within","the","graph","context",",","run","training","loops","or","inference","loops",".",":","param","application",":","a","niftynet","application",":","param","graph",":","default","base","graph","to","run","the","application",":","return",":"]
code: def run(self, application, graph=None):
      """
      Initialise a TF graph, connect data sampler and network within
      the graph context, run training loops or inference loops.
  
      :param application: a niftynet application
      :param graph: default base graph to run the application
      :return:
      """
      if graph is None:
          graph = ApplicationDriver.create_graph(
              application=application,
              num_gpus=self.num_gpus,
              num_threads=self.num_threads,
              is_training_action=self.is_training_action,
          )
  
      start_time = time.time()
      loop_status = {
          "current_iter": self.initial_iter,
          "normal_exit": False,
      }
  
      with tf.Session(config=tf_config(), graph=graph):
          try:
              # broadcasting event of session started
              SESS_STARTED.send(application, iter_msg=None)
  
              # create a iteration message generator and
              # iteratively run the graph (the main engine loop)
              iteration_messages = self._generator(**vars(self))()
              ApplicationDriver.loop(
                  application=application,
                  iteration_messages=iteration_messages,
                  loop_status=loop_status,
              )
  
          except KeyboardInterrupt:
              tf.logging.warning("User cancelled application")
          except (tf.errors.OutOfRangeError, EOFError):
              if not loop_status.get("normal_exit", False):
                  # reached the end of inference Dataset
                  loop_status["normal_exit"] = True
          except RuntimeError:
              import sys
              import traceback
  
              exc_type, exc_value, exc_traceback = sys.exc_info()
              traceback.print_exception(
                  exc_type, exc_value, exc_traceback, file=sys.stdout
              )
          finally:
              tf.logging.info("cleaning up...")
              # broadcasting session finished event
              iter_msg = IterationMessage()
              iter_msg.current_iter = loop_status.get(
                  "current_iter", -1
              )
              SESS_FINISHED.send(application, iter_msg=iter_msg)
  
      application.stop()
      if not loop_status.get("normal_exit", False):
          # loop didn't finish normally
          tf.logging.warning("stopped early, incomplete iterations.")
      tf.logging.info(
          "%s stopped (time in second %.2f).",
          type(application).__name__,
          (time.time() - start_time),
      )
  
imports: from __future__ import absolute_import
  from __future__ import division
  from __future__ import print_function
  import os
  import time
  import tensorflow
  from niftynet.engine.application_factory import ApplicationFactory, EventHandlerFactory, IteratorFactory
  from niftynet.engine.application_iteration import IterationMessage
  from niftynet.engine.application_variables import GradientsCollector, OutputsCollector
  from niftynet.engine.signal import TRAIN, ITER_STARTED, ITER_FINISHED, GRAPH_CREATED, SESS_FINISHED, SESS_STARTED
  from niftynet.io.image_sets_partitioner import ImageSetsPartitioner
  from niftynet.io.misc_io import infer_latest_model_file
  from niftynet.utilities.user_parameters_default import DEFAULT_EVENT_HANDLERS, DEFAULT_ITERATION_GENERATOR
  from niftynet.utilities.util_common import set_cuda_device, tf_config, device_string
  from niftynet.utilities.util_common import traverse_nested
label_desc: Use image node_id 3 for calling the ApplicationDriver obj's underlying member method code with example usage: obj.run(application, graph) without return types