def _create_app(app_type_string):
     """
     Import the application module
     """
     app_class = ApplicationFactory.create(app_type_string)
     app_class.clear()
     return app_class
Exemple #2
0
 def _create_app(app_type_string):
     """
     Import the application module
     """
     app_class = ApplicationFactory.create(app_type_string)
     app_class.clear()
     return app_class
    def initialise_application(self, workflow_param, data_param):
        """
        This function receives all parameters from user config file,
        create an instance of application.
        :param workflow_param: a dictionary of user parameters,
        keys correspond to sections in the config file
        :param data_param: a dictionary of input image parameters,
        keys correspond to data properties to be used by image_reader
        :return:
        """
        try:
            system_param = workflow_param.get('SYSTEM', None)
            net_param = workflow_param.get('NETWORK', None)
            infer_param = workflow_param.get('INFERENCE', None)
            eval_param = workflow_param.get('EVALUATION', None)
            app_param = workflow_param.get('CUSTOM', None)
        except AttributeError:
            tf.logging.fatal('parameters should be dictionaries')
            raise
        self.num_threads = 1
        # self.num_threads = max(system_param.num_threads, 1)
        # self.num_gpus = system_param.num_gpus
        # set_cuda_device(system_param.cuda_devices)

        # set output TF model folders
        self.model_dir = touch_folder(
            os.path.join(system_param.model_dir, 'models'))
        self.session_prefix = os.path.join(self.model_dir, FILE_PREFIX)

        assert infer_param, 'inference parameters not specified'

        # create an application instance
        assert app_param, 'application specific param. not specified'
        self.app_param = app_param
        app_module = ApplicationFactory.create(app_param.name)
        self.app = app_module(net_param, infer_param,
                              system_param.action)

        self.eval_param = eval_param

        data_param, self.app_param = \
            self.app.add_inferred_output(data_param, self.app_param)
        # initialise data input
        data_partitioner = ImageSetsPartitioner()
        # clear the cached file lists
        data_partitioner.reset()
        if data_param:
            data_partitioner.initialise(
                data_param=data_param,
                new_partition=False,
                ratios=None,
                data_split_file=system_param.dataset_split_file)

        # initialise data input
        self.app.initialise_dataset_loader(data_param, self.app_param,
                                           data_partitioner)
        self.app.initialise_evaluator(eval_param)
Exemple #4
0
    def initialise_application(self, workflow_param, data_param):
        """
        This function receives all parameters from user config file,
        create an instance of application.
        :param workflow_param: a dictionary of user parameters,
        keys correspond to sections in the config file
        :param data_param: a dictionary of input image parameters,
        keys correspond to data properties to be used by image_reader
        :return:
        """
        try:
            system_param = workflow_param.get('SYSTEM', None)
            net_param = workflow_param.get('NETWORK', None)
            infer_param = workflow_param.get('INFERENCE', None)
            eval_param = workflow_param.get('EVALUATION', None)
            app_param = workflow_param.get('CUSTOM', None)
        except AttributeError:
            tf.logging.fatal('parameters should be dictionaries')
            raise
        self.num_threads = 1
        # self.num_threads = max(system_param.num_threads, 1)
        # self.num_gpus = system_param.num_gpus
        # set_cuda_device(system_param.cuda_devices)

        # set output TF model folders
        self.model_dir = touch_folder(
            os.path.join(system_param.model_dir, 'models'))
        self.session_prefix = os.path.join(self.model_dir, FILE_PREFIX)

        assert infer_param, 'inference parameters not specified'

        # create an application instance
        assert app_param, 'application specific param. not specified'
        self.app_param = app_param
        app_module = ApplicationFactory.create(app_param.name)
        self.app = app_module(net_param, infer_param, system_param.action)

        self.eval_param = eval_param

        data_param, self.app_param = \
            self.app.add_inferred_output(data_param, self.app_param)
        # initialise data input
        data_partitioner = ImageSetsPartitioner()
        # clear the cached file lists
        data_partitioner.reset()
        if data_param:
            data_partitioner.initialise(
                data_param=data_param,
                new_partition=False,
                ratios=None,
                data_split_file=system_param.dataset_split_file)

        # initialise data input
        self.app.initialise_dataset_loader(data_param, self.app_param,
                                           data_partitioner)
        self.app.initialise_evaluator(eval_param)
Exemple #5
0
 def _create_app(app_type_string):
     """
     Import the application module
     """
     return ApplicationFactory.create(app_type_string)
def run():
    """
    meta_parser is first used to find out location
    of the configuration file. Based on the application_name
    or meta_parser.prog name, the section parsers are organised
    to find system parameters and application specific
    parameters.

    :return: system parameters is a group of parameters including
        SYSTEM_SECTIONS and app_module.REQUIRED_CONFIG_SECTION
        input_data_args is a group of input data sources to be
        used by niftynet.io.ImageReader
    """
    meta_parser = argparse.ArgumentParser(
        description="Launch a NiftyNet application.",
        formatter_class=argparse.RawDescriptionHelpFormatter,
        epilog=textwrap.dedent(EPILOG_STRING))
    version_string = get_niftynet_version_string()
    meta_parser.add_argument("action",
                             help="train networks, run inferences "
                             "or evaluate inferences",
                             metavar='ACTION',
                             choices=list(ACTIONS))
    meta_parser.add_argument("-v",
                             "--version",
                             action='version',
                             version=version_string)
    meta_parser.add_argument("-c",
                             "--conf",
                             help="specify configurations from a file",
                             metavar="CONFIG_FILE")
    meta_parser.add_argument("-a",
                             "--application_name",
                             help="specify an application module name",
                             metavar='APPLICATION_NAME',
                             default="")

    meta_args, args_from_cmdline = meta_parser.parse_known_args()
    print(version_string)

    # read configurations, to be parsed by sections
    config_file_name = __resolve_config_file_path(meta_args.conf)
    config = NiftyNetLaunchConfig()
    config.read([config_file_name])

    # infer application name from command
    app_name = None
    try:
        parser_prog = meta_parser.prog.replace('.py', '')
        app_name = parser_prog if parser_prog in SUPPORTED_APP \
            else meta_args.application_name
        assert app_name
    except (AttributeError, AssertionError):
        raise ValueError("\nUnknown application {}, or did you forget '-a' "
                         "command argument?{}".format(app_name, EPILOG_STRING))

    # load application by name
    app_module = ApplicationFactory.create(app_name)
    try:
        assert app_module.REQUIRED_CONFIG_SECTION, \
            "\nREQUIRED_CONFIG_SECTION should be static variable " \
            "in {}".format(app_module)
        has_section_in_config(config, app_module.REQUIRED_CONFIG_SECTION)
    except AttributeError:
        raise AttributeError(
            "Application code doesn't have REQUIRED_CONFIG_SECTION property. "
            "{} should be an instance of "
            "niftynet.application.base_application".format(app_module))
    except ValueError:
        raise ValueError(
            "\n{} requires [{}] section in the config file.{}".format(
                app_name, app_module.REQUIRED_CONFIG_SECTION, EPILOG_STRING))

    # check keywords in configuration file
    _check_config_file_keywords(config)

    # using configuration as default, and parsing all command line arguments
    # command line args override the configure file options
    all_args = {}
    for section in config.sections():
        # try to rename user-specified sections for consistency
        section = standardise_section_name(config, section)
        section_defaults = dict(config.items(section))
        section_args, args_from_cmdline = \
            _parse_arguments_by_section([],
                                        section,
                                        section_defaults,
                                        args_from_cmdline,
                                        app_module.REQUIRED_CONFIG_SECTION)
        all_args[section] = section_args

    # check if any args from command line not recognised
    _check_cmd_remaining_keywords(list(args_from_cmdline))

    # split parsed results in all_args
    # into dictionaries of system_args and input_data_args
    system_args, input_data_args = {}, {}
    for section in all_args:

        # copy system default sections to ``system_args``
        if section in SYSTEM_SECTIONS:
            system_args[section] = all_args[section]
            continue

        # copy application specific sections to ``system_args``
        if section == app_module.REQUIRED_CONFIG_SECTION:
            system_args['CUSTOM'] = all_args[section]
            vars(system_args['CUSTOM'])['name'] = app_name
            continue

        # copy non-default sections to ``input_data_args``
        input_data_args[section] = all_args[section]

        # set the output path of csv list if not exists
        try:
            csv_path = resolve_file_name(
                input_data_args[section].csv_file,
                (os.path.dirname(config_file_name), NIFTYNET_HOME))
            input_data_args[section].csv_file = csv_path
            # don't search files if csv specified in config
            try:
                delattr(input_data_args[section], 'path_to_search')
            except AttributeError:
                pass
        except (IOError, TypeError):
            input_data_args[section].csv_file = ''

    # preserve ``config_file`` and ``action parameter`` from the meta_args
    system_args['CONFIG_FILE'] = argparse.Namespace(path=config_file_name)
    # mapping the captured action argument to a string in ACTIONS
    system_args['SYSTEM'].action = \
        look_up_operations(meta_args.action, ACTIONS)
    if not system_args['SYSTEM'].model_dir:
        system_args['SYSTEM'].model_dir = os.path.join(
            os.path.dirname(config_file_name), 'model')
    return system_args, input_data_args
Exemple #7
0
def run():
    """
    meta_parser is first used to find out location
    of the configuration file. based on the application_name
    or meta_parser.prog name, the section parsers are organised
    to find system parameters and application specific
    parameters.

    :return: system parameters is a group of parameters including
        SYSTEM_SECTIONS and app_module.REQUIRED_CONFIG_SECTION
        input_data_args is a group of input data sources to be
        used by niftynet.io.ImageReader
    """
    meta_parser = argparse.ArgumentParser(
        description="Launch a NiftyNet application.",
        formatter_class=argparse.RawDescriptionHelpFormatter,
        epilog=textwrap.dedent(epilog_string))
    version_string = get_niftynet_version_string()
    meta_parser.add_argument("action",
                             help="train networks or run inferences",
                             metavar='ACTION',
                             choices=['train', 'inference'])
    meta_parser.add_argument("-v",
                             "--version",
                             action='version',
                             version=version_string)
    meta_parser.add_argument("-c",
                             "--conf",
                             help="specify configurations from a file",
                             metavar="CONFIG_FILE")
    meta_parser.add_argument("-a",
                             "--application_name",
                             help="specify an application module name",
                             metavar='APPLICATION_NAME',
                             default="")

    meta_args, args_from_cmdline = meta_parser.parse_known_args()
    print(version_string)

    # read configurations, to be parsed by sections
    if not meta_args.conf:
        print("\nNo configuration file has been provided, did you "
              "forget '-c' command argument?{}".format(epilog_string))
        raise IOError

    # Resolve relative configuration file location
    config_path = meta_args.conf
    if not os.path.isfile(config_path):
        relative_conf_file = os.path.join(
            NiftyNetGlobalConfig().get_default_examples_folder(), config_path,
            config_path + "_config.ini")
        if os.path.isfile(relative_conf_file):
            config_path = relative_conf_file
            os.chdir(os.path.dirname(config_path))
        else:
            print("\nConfiguration file not found: {}.{}".format(
                config_path, epilog_string))
            raise IOError

    config = configparser.ConfigParser()
    config.read([config_path])
    app_module = None
    module_name = None
    try:
        if meta_parser.prog[:-3] in SUPPORTED_APP:
            module_name = meta_parser.prog[:-3]
        elif meta_parser.prog in SUPPORTED_APP:
            module_name = meta_parser.prog
        else:
            module_name = meta_args.application_name
        app_module = ApplicationFactory.create(module_name)
        assert app_module.REQUIRED_CONFIG_SECTION, \
            "\nREQUIRED_CONFIG_SECTION should be static variable " \
            "in {}".format(app_module)
        has_section_in_config(config, app_module.REQUIRED_CONFIG_SECTION)
    except ValueError:
        if app_module:
            section_name = app_module.REQUIRED_CONFIG_SECTION
            print('\n{} requires [{}] section in the config file.{}'.format(
                module_name, section_name, epilog_string))
        if not module_name:
            print("\nUnknown application {}, or did you forget '-a' "
                  "command argument?{}".format(module_name, epilog_string))
        raise

    # check keywords in configuration file
    check_keywords(config)

    # using configuration as default, and parsing all command line arguments
    all_args = {}
    for section in config.sections():
        # try to rename user-specified sections for consistency
        section = standardise_section_name(config, section)
        section_defaults = dict(config.items(section))
        section_args, args_from_cmdline = \
            _parse_arguments_by_section([],
                                        section,
                                        section_defaults,
                                        args_from_cmdline,
                                        app_module.REQUIRED_CONFIG_SECTION)
        all_args[section] = section_args
    # command line parameters should be valid
    assert not args_from_cmdline, \
        '\nUnknown parameter: {}{}'.format(args_from_cmdline, epilog_string)

    # split parsed results in all_args
    # into dictionaries of system_args and input_data_args
    system_args = {}
    input_data_args = {}

    # copy system default sections to ``system_args``
    for section in all_args:
        if section in SYSTEM_SECTIONS:
            system_args[section] = all_args[section]
        elif section == app_module.REQUIRED_CONFIG_SECTION:
            system_args['CUSTOM'] = all_args[section]
            vars(system_args['CUSTOM'])['name'] = module_name

    if all_args['SYSTEM'].model_dir is None:
        all_args['SYSTEM'].model_dir = os.path.join(
            os.path.dirname(meta_args.conf), 'model')

    # copy non-default sections to ``input_data_args``
    for section in all_args:
        if section in SYSTEM_SECTIONS:
            continue
        if section == app_module.REQUIRED_CONFIG_SECTION:
            continue
        input_data_args[section] = all_args[section]
        # set the output path of csv list if not exists
        csv_path = input_data_args[section].csv_file
        if os.path.isfile(csv_path):
            # don't search files if csv specified in config
            try:
                delattr(input_data_args[section], 'path_to_search')
            except AttributeError:
                pass
        else:
            input_data_args[section].csv_file = ''

    # preserve ``config_file`` and ``action parameter`` from the meta_args
    system_args['CONFIG_FILE'] = argparse.Namespace(path=meta_args.conf)
    system_args['SYSTEM'].action = meta_args.action
    return system_args, input_data_args
def run():
    """
    meta_parser is first used to find out location
    of the configuration file. based on the application_name
    or meta_parser.prog name, the section parsers are organised
    to find system parameters and application specific
    parameters.

    :return: system parameters is a group of parameters including
        SYSTEM_SECTIONS and app_module.REQUIRED_CONFIG_SECTION
        input_data_args is a group of input data sources to be
        used by niftynet.io.ImageReader
    """
    meta_parser = argparse.ArgumentParser(
        description="Launch a NiftyNet application.",
        formatter_class=argparse.RawDescriptionHelpFormatter,
        epilog=textwrap.dedent(epilog_string))
    version_string = get_niftynet_version_string()
    meta_parser.add_argument("action",
                             help="train networks or run inferences",
                             metavar='ACTION',
                             choices=['train', 'inference'])
    meta_parser.add_argument("-v", "--version",
                             action='version',
                             version=version_string)
    meta_parser.add_argument("-c", "--conf",
                             help="specify configurations from a file",
                             metavar="CONFIG_FILE")
    meta_parser.add_argument("-a", "--application_name",
                             help="specify an application module name",
                             metavar='APPLICATION_NAME',
                             default="")

    meta_args, args_from_cmdline = meta_parser.parse_known_args()
    print(version_string)

    # read configurations, to be parsed by sections
    if not meta_args.conf:
        print("\nNo configuration file has been provided, did you "
              "forget '-c' command argument?{}".format(epilog_string))
        raise IOError

    # Resolve relative configuration file location
    config_path = os.path.expanduser(meta_args.conf)
    if not os.path.isfile(config_path):
        relative_conf_file = os.path.join(
            NiftyNetGlobalConfig().get_default_examples_folder(),
            config_path,
            config_path + "_config.ini")
        if os.path.isfile(relative_conf_file):
            config_path = relative_conf_file
            os.chdir(os.path.dirname(config_path))
        else:
            print("\nConfiguration file not found: {}.{}".format(
                config_path, epilog_string))
            raise IOError

    config = configparser.ConfigParser()
    config.read([config_path])
    app_module = None
    module_name = None
    try:
        if meta_parser.prog[:-3] in SUPPORTED_APP:
            module_name = meta_parser.prog[:-3]
        elif meta_parser.prog in SUPPORTED_APP:
            module_name = meta_parser.prog
        else:
            module_name = meta_args.application_name
        app_module = ApplicationFactory.create(module_name)
        assert app_module.REQUIRED_CONFIG_SECTION, \
            "\nREQUIRED_CONFIG_SECTION should be static variable " \
            "in {}".format(app_module)
        has_section_in_config(config, app_module.REQUIRED_CONFIG_SECTION)
    except ValueError:
        if app_module:
            section_name = app_module.REQUIRED_CONFIG_SECTION
            print('\n{} requires [{}] section in the config file.{}'.format(
                module_name, section_name, epilog_string))
        if not module_name:
            print("\nUnknown application {}, or did you forget '-a' "
                  "command argument?{}".format(module_name, epilog_string))
        raise

    # check keywords in configuration file
    check_keywords(config)

    # using configuration as default, and parsing all command line arguments
    all_args = {}
    for section in config.sections():
        # try to rename user-specified sections for consistency
        section = standardise_section_name(config, section)
        section_defaults = dict(config.items(section))
        section_args, args_from_cmdline = \
            _parse_arguments_by_section([],
                                        section,
                                        section_defaults,
                                        args_from_cmdline,
                                        app_module.REQUIRED_CONFIG_SECTION)
        all_args[section] = section_args
    # command line parameters should be valid
    assert not args_from_cmdline, \
        '\nUnknown parameter: {}{}'.format(args_from_cmdline, epilog_string)

    # split parsed results in all_args
    # into dictionaries of system_args and input_data_args
    system_args = {}
    input_data_args = {}

    # copy system default sections to ``system_args``
    for section in all_args:
        if section in SYSTEM_SECTIONS:
            system_args[section] = all_args[section]
        elif section == app_module.REQUIRED_CONFIG_SECTION:
            system_args['CUSTOM'] = all_args[section]
            vars(system_args['CUSTOM'])['name'] = module_name

    if all_args['SYSTEM'].model_dir is None:
        all_args['SYSTEM'].model_dir = os.path.join(
            os.path.dirname(meta_args.conf), 'model')

    # copy non-default sections to ``input_data_args``
    for section in all_args:
        if section in SYSTEM_SECTIONS:
            continue
        if section == app_module.REQUIRED_CONFIG_SECTION:
            continue
        input_data_args[section] = all_args[section]
        # set the output path of csv list if not exists
        csv_path = input_data_args[section].csv_file
        if os.path.isfile(csv_path):
            # don't search files if csv specified in config
            try:
                delattr(input_data_args[section], 'path_to_search')
            except AttributeError:
                pass
        else:
            input_data_args[section].csv_file = ''

    # preserve ``config_file`` and ``action parameter`` from the meta_args
    system_args['CONFIG_FILE'] = argparse.Namespace(path=meta_args.conf)
    system_args['SYSTEM'].action = meta_args.action
    return system_args, input_data_args
    def initialise_application(self, workflow_param, data_param=None):
        """
        This function receives all parameters from user config file,
        create an instance of application.

        :param workflow_param: a dictionary of user parameters,
            keys correspond to sections in the config file
        :param data_param: a dictionary of input image parameters,
            keys correspond to data properties to be used by image_reader
        :return:
        """
        try:
            system_param = workflow_param.get('SYSTEM', None)
            net_param = workflow_param.get('NETWORK', None)
            train_param = workflow_param.get('TRAINING', None)
            infer_param = workflow_param.get('INFERENCE', None)
            app_param = workflow_param.get('CUSTOM', None)
        except AttributeError:
            tf.logging.fatal('parameters should be dictionaries')
            raise

        assert os.path.exists(system_param.model_dir), \
            'Model folder not exists {}'.format(system_param.model_dir)
        self.model_dir = system_param.model_dir

        self.is_training_action = TRAIN.startswith(system_param.action.lower())
        # hardware-related parameters
        self.num_threads = max(system_param.num_threads, 1) \
            if self.is_training_action else 1
        self.num_gpus = system_param.num_gpus \
            if self.is_training_action else min(system_param.num_gpus, 1)
        set_cuda_device(system_param.cuda_devices)

        # set training params.
        if self.is_training_action:
            assert train_param, 'training parameters not specified'
            self.initial_iter = train_param.starting_iter
            self.final_iter = max(train_param.max_iter, self.initial_iter)
            self.save_every_n = train_param.save_every_n
            self.tensorboard_every_n = train_param.tensorboard_every_n
            self.max_checkpoints = max(self.max_checkpoints,
                                       train_param.max_checkpoints)
            self.validation_every_n = train_param.validation_every_n
            if self.validation_every_n > 0:
                self.validation_max_iter = max(self.validation_max_iter,
                                               train_param.validation_max_iter)
            action_param = train_param
        else:  # set inference params.
            assert infer_param, 'inference parameters not specified'
            self.initial_iter = infer_param.inference_iter
            action_param = infer_param

        # infer the initial iteration from model files
        if self.initial_iter < 0:
            self.initial_iter = infer_latest_model_file(
                os.path.join(self.model_dir, 'models'))

        # create an application instance
        assert app_param, 'application specific param. not specified'
        app_module = ApplicationFactory.create(app_param.name)
        self.app = app_module(net_param, action_param, system_param.action)

        # clear the cached file lists
        self.data_partitioner.reset()
        if data_param:
            do_new_partition = \
                self.is_training_action and self.initial_iter == 0 and \
                (not os.path.isfile(system_param.dataset_split_file)) and \
                (train_param.exclude_fraction_for_validation > 0 or
                 train_param.exclude_fraction_for_inference > 0)
            data_fractions = (train_param.exclude_fraction_for_validation,
                              train_param.exclude_fraction_for_inference) \
                if do_new_partition else None

            self.data_partitioner.initialise(
                data_param=data_param,
                new_partition=do_new_partition,
                ratios=data_fractions,
                data_split_file=system_param.dataset_split_file)
            assert self.data_partitioner.has_validation or \
                self.validation_every_n <= 0, \
                'validation_every_n is set to {}, ' \
                'but train/validation splitting not available.\nPlease ' \
                'check dataset partition list {} ' \
                '(remove file to generate a new dataset partition), ' \
                'check "exclude_fraction_for_validation" ' \
                '(current config value: {}).\nAlternatively, ' \
                'set "validation_every_n" to -1.'.format(
                    self.validation_every_n,
                    system_param.dataset_split_file,
                    train_param.exclude_fraction_for_validation)

        # initialise readers
        self.app.initialise_dataset_loader(data_param, app_param,
                                           self.data_partitioner)

        # make the list of initialised event handler instances.
        self.load_event_handlers(system_param.event_handler
                                 or DEFAULT_EVENT_HANDLERS)
        self._generator = IteratorFactory.create(
            system_param.iteration_generator or DEFAULT_ITERATION_GENERATOR)
Exemple #10
0
def run():
    """
    meta_parser is first used to find out location
    of the configuration file. based on the application_name
    or meta_parser.prog name, the section parsers are organised
    to find system parameters and application specific
    parameters

    :return: system parameters is a group of parameters including
        SYSTEM_SECTIONS and app_module.REQUIRED_CONFIG_SECTION
        input_data_args is a group of input data sources to be
        used by niftynet.io.ImageReader
    """
    meta_parser = argparse.ArgumentParser(
        epilog=
        'Please visit https://cmiclab.cs.ucl.ac.uk/CMIC/NiftyNet/tree/dev/demos '
        'for more info.')
    version_string = get_niftynet_version_string()
    meta_parser.add_argument("-v",
                             "--version",
                             action='version',
                             version=version_string)
    meta_parser.add_argument(
        "-c",
        "--conf",
        help="Specify configurations from a file",
        metavar="File",
    )
    meta_parser.add_argument(
        "-a",
        "--application_name",
        help="Specify application name",
        default="",
    )
    meta_args, args_from_cmdline = meta_parser.parse_known_args()
    print(version_string)

    # read configurations, to be parsed by sections
    if (meta_args.conf is None) or (not os.path.isfile(meta_args.conf)):
        raise IOError("Configuration file not found {}".format(meta_args.conf))
    config = configparser.ConfigParser()
    config.read([meta_args.conf])
    try:
        if meta_parser.prog[:-3] in SUPPORTED_APP:
            module_name = meta_parser.prog[:-3]
        elif meta_parser.prog in SUPPORTED_APP:
            module_name = meta_parser.prog
        else:
            module_name = meta_args.application_name
        app_module = ApplicationFactory.create(module_name)
        assert app_module.REQUIRED_CONFIG_SECTION, \
            "REQUIRED_CONFIG_SECTION should be static variable " \
            "in {}".format(app_module)
        has_section_in_config(config, app_module.REQUIRED_CONFIG_SECTION)
    except ValueError:
        raise ValueError('{} requires [{}] section in the config file'.format(
            module_name, app_module.REQUIRED_CONFIG_SECTION))

    # check keywords in configuration file
    check_keywords(config)

    # using configuration as default, and parsing all command line arguments
    all_args = {}
    for section in config.sections():
        # try to rename user-specified sections for consistency
        section = standardise_section_name(config, section)
        section_defaults = dict(config.items(section))
        section_args, args_from_cmdline = \
            _parse_arguments_by_section([],
                                        section,
                                        section_defaults,
                                        args_from_cmdline,
                                        app_module.REQUIRED_CONFIG_SECTION)
        all_args[section] = section_args
    # command line parameters should be valid
    assert not args_from_cmdline, \
        'unknown parameter: {}'.format(args_from_cmdline)

    # split parsed results in all_args
    # into dictionary of system_args and input_data_args
    system_args = {}
    input_data_args = {}
    for section in all_args:
        if section in SYSTEM_SECTIONS:
            system_args[section] = all_args[section]
        elif section == app_module.REQUIRED_CONFIG_SECTION:
            system_args['CUSTOM'] = all_args[section]
            vars(system_args['CUSTOM'])['name'] = module_name
        else:
            input_data_args[section] = all_args[section]
            # set the output path of csv list if not exists
            csv_path = input_data_args[section].csv_file
            if not os.path.isfile(csv_path):
                csv_filename = os.path.join(all_args['SYSTEM'].model_dir,
                                            '{}.csv'.format(section))
                input_data_args[section].csv_file = csv_filename
            else:
                # don't search files if csv specified in config
                try:
                    delattr(input_data_args[section], 'path_to_search')
                except AttributeError:
                    pass

    # update conf path
    system_args['CONFIG_FILE'] = argparse.Namespace(path=meta_args.conf)
    return system_args, input_data_args
def run():
    """
    meta_parser is first used to find out location
    of the configuration file. Based on the application_name
    or meta_parser.prog name, the section parsers are organised
    to find system parameters and application specific
    parameters.

    :return: system parameters is a group of parameters including
        SYSTEM_SECTIONS and app_module.REQUIRED_CONFIG_SECTION
        input_data_args is a group of input data sources to be
        used by niftynet.io.ImageReader
    """
    meta_parser = argparse.ArgumentParser(
        description="Launch a NiftyNet application.",
        formatter_class=argparse.RawDescriptionHelpFormatter,
        epilog=textwrap.dedent(EPILOG_STRING))
    version_string = get_niftynet_version_string()
    meta_parser.add_argument("action",
                             help="train networks, run inferences "
                                  "or evaluate inferences",
                             metavar='ACTION',
                             choices=['train', 'inference', 'evaluation'])
    meta_parser.add_argument("-v", "--version",
                             action='version',
                             version=version_string)
    meta_parser.add_argument("-c", "--conf",
                             help="specify configurations from a file",
                             metavar="CONFIG_FILE")
    meta_parser.add_argument("-a", "--application_name",
                             help="specify an application module name",
                             metavar='APPLICATION_NAME',
                             default="")

    meta_args, args_from_cmdline = meta_parser.parse_known_args()
    print(version_string)

    # read configurations, to be parsed by sections
    config_file_name = __resolve_config_file_path(meta_args.conf)
    config = configparser.ConfigParser()
    config.read([config_file_name])

    # infer application name from command
    app_name = None
    try:
        parser_prog = meta_parser.prog.replace('.py', '')
        app_name = parser_prog if parser_prog in SUPPORTED_APP \
            else meta_args.application_name
        assert app_name
    except (AttributeError, AssertionError):
        raise ValueError(
            "\nUnknown application {}, or did you forget '-a' "
            "command argument?{}".format(app_name, EPILOG_STRING))

    # load application by name
    app_module = ApplicationFactory.create(app_name)
    try:
        assert app_module.REQUIRED_CONFIG_SECTION, \
            "\nREQUIRED_CONFIG_SECTION should be static variable " \
            "in {}".format(app_module)
        has_section_in_config(config, app_module.REQUIRED_CONFIG_SECTION)
    except AttributeError:
        raise AttributeError(
            "Application code doesn't have REQUIRED_CONFIG_SECTION property. "
            "{} should be an instance of "
            "niftynet.application.base_application".format(app_module))
    except ValueError:
        raise ValueError(
            "\n{} requires [{}] section in the config file.{}".format(
                app_name, app_module.REQUIRED_CONFIG_SECTION, EPILOG_STRING))

    # check keywords in configuration file
    _check_config_file_keywords(config)

    # using configuration as default, and parsing all command line arguments
    # command line args override the configure file options
    all_args = {}
    for section in config.sections():
        # try to rename user-specified sections for consistency
        section = standardise_section_name(config, section)
        section_defaults = dict(config.items(section))
        section_args, args_from_cmdline = \
            _parse_arguments_by_section([],
                                        section,
                                        section_defaults,
                                        args_from_cmdline,
                                        app_module.REQUIRED_CONFIG_SECTION)
        all_args[section] = section_args

    # check if any args from command line not recognised
    _check_cmd_remaining_keywords(list(args_from_cmdline))

    # split parsed results in all_args
    # into dictionaries of system_args and input_data_args
    system_args, input_data_args = {}, {}
    for section in all_args:

        # copy system default sections to ``system_args``
        if section in SYSTEM_SECTIONS:
            system_args[section] = all_args[section]
            continue

        # copy application specific sections to ``system_args``
        if section == app_module.REQUIRED_CONFIG_SECTION:
            system_args['CUSTOM'] = all_args[section]
            vars(system_args['CUSTOM'])['name'] = app_name
            continue

        # copy non-default sections to ``input_data_args``
        input_data_args[section] = all_args[section]

        # set the output path of csv list if not exists
        try:
            csv_path = resolve_file_name(
                input_data_args[section].csv_file,
                (os.path.dirname(config_file_name), NIFTYNET_HOME))
            input_data_args[section].csv_file = csv_path
            # don't search files if csv specified in config
            try:
                delattr(input_data_args[section], 'path_to_search')
            except AttributeError:
                pass
        except (IOError, TypeError):
            input_data_args[section].csv_file = ''

    # preserve ``config_file`` and ``action parameter`` from the meta_args
    system_args['CONFIG_FILE'] = argparse.Namespace(path=config_file_name)
    system_args['SYSTEM'].action = meta_args.action
    if not system_args['SYSTEM'].model_dir:
        system_args['SYSTEM'].model_dir = os.path.join(
            os.path.dirname(config_file_name), 'model')
    return system_args, input_data_args