예제 #1
0
def test_dynamic_cli_parser(options, commandline_input, expected):
    """Test if the parser creates the arguments properly.

    Parameters
    ----------
    options : dict
        A Python dict with key being the full name of the option. The value is
        a kwargs dict that corresponds to input arguments of the
        ArgumentParser.add_argument function. Note: type argument values must be
        surrounded by quotes.
    commandline_input : list
        A list containing commandline inputs.
    expected : list
        Containing the expected option input values.

    Raises
    -------
    AssertionError
        If the performed test failed.

    """
    parser = argparse.ArgumentParser()
    parser = dynamic_cli_options(parser=parser, options=options)
    parsed_arguments = parser.parse_args(commandline_input)
    assert parsed_arguments.input == expected[0]
    assert parsed_arguments.output == expected[1]
    assert parsed_arguments.choice == expected[2]
    assert parsed_arguments.option_1 == expected[3]
    assert parsed_arguments.option_2 == expected[4]
예제 #2
0
    def _add_options(self):
        """Function for adding the parser and options to the given ArgumentParser.

        Notes
        -----
            Uses the class constructor's subparser object for appending the tool's parser and options.

        """
        # Create the description and options for the parser.
        description = "Create a VDJ or VJ model by executing IGoR's commandline tool via a python subprocess using default " \
            "model parameters."
        parser_options = {
            '-seqs': {
                'metavar':
                '<fasta/separated>',
                'required':
                'True',
                'type':
                'str',
                'help':
                "An input FASTA or separated data file with sequences for training the model."
            },
            '-ref': {
                'metavar': ('<gene>', '<fasta>'),
                'type':
                'str',
                'action':
                'append',
                'nargs':
                2,
                'required':
                'True',
                'help':
                "A gene (V, D or J) followed by a reference genome FASTA file. Note: the FASTA reference genome files "
                "needs to conform to IGMT annotation (separated by '|' character)."
            },
            '-type': {
                'type': 'str.lower',
                'choices': ['alpha', 'beta', 'light', 'heavy'],
                'required': 'True',
                'help':
                'The type of model to create. (select one: %(choices)s).'
            },
            '-n-iter': {
                'type':
                'int',
                'nargs':
                '?',
                'help':
                'The number of inference iterations to perform when creating the model (default: {}).'
                .format(get_config_data('BUILD', 'NUM_ITERATIONS', 'int'))
            }
        }

        # Add the options to the parser and return the updated parser.
        parser_tool = self.subparsers.add_parser('build',
                                                 help=description,
                                                 description=description)
        parser_tool = dynamic_cli_options(parser=parser_tool,
                                          options=parser_options)
예제 #3
0
    def _add_options(self):
        """Function for adding the parser/options to the input ArgumentParser.

        Notes
        -----
            Uses the class constructor's subparser object for appending the tool's parser and options.

        """
        # Create the description and options for the parser.
        description = "Create an alignment for the given reference genome FASTA files and seach the given alignment for " \
            "conserved motif regions. The located CDR3 anchors can be used for the other tools."
        parser_options = {
            '-ref': {
                'metavar': ('<gene>', '<fasta>'),
                'type':
                'str',
                'action':
                'append',
                'nargs':
                2,
                'required':
                'True',
                'help':
                "A gene (V or J) followed by a reference genome FASTA file. Note: the FASTA reference genome files "
                "needs to conform to IGMT annotation (separated by '|' character)."
            },
            '-motif': {
                'type':
                'str.upper',
                'action':
                'append',
                'help':
                "The motifs to look for (default: 'V' {} and 'J' {} respectivly)."
                .format(
                    get_config_data('LOCATE', 'V_MOTIFS').split(','),
                    get_config_data('LOCATE', 'J_MOTIFS').split(','))
            }
        }

        # Add the options to the parser and return the updated parser.
        parser_tool = self.subparsers.add_parser('locate',
                                                 help=description,
                                                 description=description)
        parser_tool = dynamic_cli_options(parser=parser_tool,
                                          options=parser_options)
예제 #4
0
def main():
    """Function to create the ArgumentParser containing the sub-options."""
    # Setting up the logger.
    logging.basicConfig(
        format='%(asctime)s - %(name)s - %(levelname)s - %(message)s',
        level=os.environ.get("LOGLEVEL", "INFO")
    )
    logger = logging.getLogger(__name__)

    # Create the parser with general commands and set the subparser.
    description = 'Create IGoR models and calculate the generation probability of V(D)J and CDR3 sequences.'
    parser_general_options = {
        '-separator': {
            'type': 'str.lower',
            'choices': ['tab', 'semi-colon', 'comma'],
            'help': 'The separator character used for input files and for writing new files (select one: %(choices)s) '
                    '(default: {}).'.format(
                        {'\t': 'tab', ';': 'semi-colon', ',': 'comma'}[get_config_data('COMMON', 'SEPARATOR')])
        },
        '-threads': {
            'type': 'int',
            'nargs': '?',
            'help': 'The number of threads the program is allowed to use (default: {}).'
                    .format(get_config_data('COMMON', 'NUM_THREADS', 'int'))
        },
        '-set-wd': {
            'type': 'str',
            'nargs': '?',
            'help': 'An optional location for writing files (default: {}).'.format(get_config_data('COMMON', 'WORKING_DIR'))
        },
        '-out-name': {
            'type': 'str',
            'nargs': '?',
            'help': 'An optional output file name. If multiple files are created, the value is used as a prefix for the file '
                    '(default: {}).'.format(get_config_data('COMMON', 'OUT_NAME'))
        },
        '-config-file': {
            'type': 'str',
            'nargs': '?',
            'help': 'An optional configuration file path for ImmunoProbs. This file is always combined with the default '
                    'configuration to make up missing values.'
        },
    }
    parser = argparse.ArgumentParser(prog='immuno-probs', description=description)
    parser = dynamic_cli_options(parser=parser, options=parser_general_options)
    subparsers = parser.add_subparsers(
        help='Supported immuno-probs options, command plus help displays more information for the option.',
        dest='subparser_name'
    )

    # Add main- and suboptions to the subparser.
    logger.info('Setting up ImmunoProbs commandline tools')
    try:
        cas = ConvertAdaptiveSequences(subparsers=subparsers)
        lca = LocateCdr3Anchors(subparsers=subparsers)
        bim = BuildIgorModel(subparsers=subparsers)
        ges = GenerateSequences(subparsers=subparsers)
        evs = EvaluateSequences(subparsers=subparsers)
    except (TypeError) as err:
        logger.error(str(err))
        return

    # Parse the commandline arguments and set variables.
    logger.info('Parsing/formatting commandline arguments')
    try:
        parsed_arguments = parser.parse_args()
        if parsed_arguments.config_file is not None:
            set_config_data(parsed_arguments.config_file)
        if parsed_arguments.separator is not None:
            set_separator(parsed_arguments.separator)
        if parsed_arguments.threads is not None:
            set_num_threads(parsed_arguments.threads)
        if parsed_arguments.set_wd is not None:
            set_working_dir(parsed_arguments.set_wd)
        if parsed_arguments.out_name is not None:
            set_out_name(parsed_arguments.out_name)
    except (TypeError, ValueError, IOError) as err:
        logger.error(str(err))
        return

    # Create the directory paths for temporary files.
    logger.info('Setting up temporary system directory')
    try:
        output_dir = get_config_data('COMMON', 'WORKING_DIR')
        if get_config_data('EXPERT', 'USE_SYSTEM_TEMP', 'bool'):
            temp_dir = create_directory_path(os.path.join(tempfile.gettempdir(), get_config_data('EXPERT', 'TEMP_DIR')))
        else:
            temp_dir = create_directory_path(os.path.join(output_dir, get_config_data('EXPERT', 'TEMP_DIR')))
        set_working_dir(temp_dir)
    except (IOError, AttributeError) as err:
        logger.error(str(err))
        return

    # Execute the correct tool based on given subparser name.
    logger.info('Executing selected ImmunoProbs tool (%s)', parsed_arguments.subparser_name)
    if parsed_arguments.subparser_name == 'convert':
        cas.run(args=parsed_arguments, output_dir=output_dir)
    elif parsed_arguments.subparser_name == 'locate':
        lca.run(args=parsed_arguments, output_dir=output_dir)
    elif parsed_arguments.subparser_name == 'build':
        bim.run(args=parsed_arguments, output_dir=output_dir)
    elif parsed_arguments.subparser_name == 'generate':
        ges.run(args=parsed_arguments, output_dir=output_dir)
    elif parsed_arguments.subparser_name == 'evaluate':
        evs.run(args=parsed_arguments, output_dir=output_dir)
    else:
        logger.error('No tool selected, run help command to show all supported tools')

    # Finally, delete the temporary directory if specified.
    if get_config_data('EXPERT', 'REMOVE_TEMP_DIR', 'bool'):
        logger.info('Cleaning up working directory')
        rmtree(temp_dir, ignore_errors=True)
예제 #5
0
    def _add_options(self):
        """Function for adding the parser and options to the given ArgumentParser.

        Notes
        -----
            Uses the class constructor's subparser object for appending the tool's parser and options.

        """
        # Create the description and options for the parser.
        description = "Evaluate VDJ or VJ sequences given a custom IGoR model (or build-in) through IGoR's commandline " \
            "tool via python subprocess. Or evaluate CDR3 sequences with the model by using OLGA."
        parser_options = {
            '-seqs': {
                'metavar': '<fasta/separated>',
                'required': 'True',
                'type': 'str',
                'help': "An input FASTA or separated data file with sequences to evaluate."
            },
            '-model': {
                'type': 'str.lower',
                'choices': get_default_model_file_paths(),
                'required': '-custom-model' not in sys.argv,
                'help': "Specify a pre-installed model for evaluation. (required if -custom-model NOT specified) "
                        "(select one: %(choices)s)."
            },
            '-ref': {
                'metavar': ('<gene>', '<fasta>'),
                'type': 'str',
                'action': 'append',
                'nargs': 2,
                'required': ('-cdr3' not in sys.argv and '-custom-model' in sys.argv),
                'help': "A gene (V, D or J) followed by a reference genome FASTA file. Note: the FASTA reference genome files "
                        "needs to conform to IGMT annotation (separated by '|' character). (required for -custom-model "
                        "without -cdr3)"
            },
            '-type': {
                'type': 'str.lower',
                'choices': ['alpha', 'beta', 'light', 'heavy'],
                'required': ('-custom-model' in sys.argv),
                'help': 'The type of the custom model to use. (select one: %(choices)s) (required for -custom-model).'
            },
            '-custom-model': {
                'metavar': ('<parameters>', '<marginals>'),
                'type': 'str',
                'nargs': 2,
                'help': 'A IGoR parameters file followed by an IGoR marginals file.'
            },
            '-anchor': {
                'metavar': ('<gene>', '<separated>'),
                'type': 'str',
                'action': 'append',
                'nargs': 2,
                'required': ('-cdr3' in sys.argv and '-custom-model' in sys.argv),
                'help': 'A gene (V or J) followed by a CDR3 anchor separated data file. Note: need to contain gene in the '
                        'first column, anchor index in the second and gene function in the third (required for -cdr3 and '
                        '-custom-model).'
            },
            '-cdr3': {
                'action': 'store_true',
                'help': 'If specified (True), CDR3 sequences should be evaluated, otherwise V(D)J sequences (default: {}).'
                        .format(get_config_data('EVALUATE', 'EVAL_CDR3', 'bool'))
            },
            '-use-allele': {
                'action': 'store_true',
                'help': "If specified (True), in combination with the '-cdr3' flag, the allele information from the gene "
                        "choice fields is used to calculate the generation probability (default: {})."
                        .format(get_config_data('EVALUATE', 'USE_ALLELE', 'bool'))
            },
        }

        # Add the options to the parser and return the updated parser.
        parser_tool = self.subparsers.add_parser('evaluate', help=description, description=description)
        parser_tool = dynamic_cli_options(parser=parser_tool, options=parser_options)
예제 #6
0
    def _add_options(self):
        """Function for adding the parser and options to the given ArgumentParser.

        Notes
        -----
            Uses the class constructor's subparser object for appending the
            tool's parser and options.

        """
        # Create the description and options for the parser.
        description = "Generate VDJ or VJ sequences given a custom IGoR model (or build-in) by executing IGoR's " \
            "commandline tool via python subprocess. Or generate CDR3 sequences from the model by using OLGA."
        parser_options = {
            '-model': {
                'type':
                'str.lower',
                'choices':
                get_default_model_file_paths(),
                'required':
                '-custom-model' not in sys.argv,
                'help':
                "Specify a pre-installed model for generation. (required if -custom-model NOT specified) "
                "(select one: %(choices)s)."
            },
            '-type': {
                'type':
                'str.lower',
                'choices': ['alpha', 'beta', 'light', 'heavy'],
                'required': ('-custom-model' in sys.argv),
                'help':
                'The type of the custom model to use. (select one: %(choices)s) (required for -custom-model).'
            },
            '-anchor': {
                'metavar': ('<gene>', '<separated>'),
                'type':
                'str',
                'action':
                'append',
                'nargs':
                2,
                'required': ('-cdr3' in sys.argv
                             and '-custom-model' in sys.argv),
                'help':
                'A gene (V or J) followed by a CDR3 anchor separated data file. Note: need to contain gene in the '
                'first column, anchor index in the second and gene function in the third (required for -cdr3 and '
                '-custom-model).'
            },
            '-custom-model': {
                'metavar': ('<parameters>', '<marginals>'),
                'type':
                'str',
                'nargs':
                2,
                'help':
                'A IGoR parameters file followed by an IGoR marginals file.'
            },
            '-n-gen': {
                'type':
                'int',
                'nargs':
                '?',
                'help':
                'The number of sequences to generate (default: {}).'.format(
                    get_config_data('GENERATE', 'NUM_GENERATE', 'int'))
            },
            '-cdr3': {
                'action':
                'store_true',
                'help':
                'If specified (True), CDR3 sequences are generated, otherwise V(D)J sequences (default: {}).'
                .format(get_config_data('GENERATE', 'EVAL_CDR3', 'bool'))
            },
        }

        # Add the options to the parser and return the updated parser.
        parser_tool = self.subparsers.add_parser('generate',
                                                 help=description,
                                                 description=description)
        parser_tool = dynamic_cli_options(parser=parser_tool,
                                          options=parser_options)
예제 #7
0
    def _add_options(self):
        """Function for adding the parser/options to the input ArgumentParser.

        Notes
        -----
            Uses the class constructor's subparser object for appending the tool's parser and options.

        """
        # Create the description and options for the parser.
        description = "Converts the full length (VDJ for productive, unproductive and the total) and CDR3 sequences from a " \
            "given adaptive input sequence file. The VDJ sequences can be used to build a new IGoR model and the CDR3 " \
            "sequences can be evaluated."
        parser_options = {
            '-seqs': {
                'metavar':
                '<separated>',
                'required':
                'True',
                'type':
                'str',
                'help':
                "An input separated data file with sequences to convert using the defined column names."
            },
            '-ref': {
                'metavar': ('<gene>', '<fasta>'),
                'type':
                'str',
                'action':
                'append',
                'nargs':
                2,
                'required':
                'True',
                'help':
                "A gene (V or J) followed by a reference genome FASTA file. Note: the FASTA reference genome files "
                "needs to conform to IGMT annotation (separated by '|' character)."
            },
            '-n-random': {
                'type':
                'int',
                'nargs':
                '?',
                'help':
                "Number of random sequences (subset) to convert from the given file (default: {})."
                .format(get_config_data('CONVERT', 'NUM_RANDOM', 'int'))
            },
            '-use-allele': {
                'action':
                'store_true',
                'help':
                "If specified (True), the allele information from the resolved gene fields are used to when "
                "reconstructing the gene choices (default: {}).".format(
                    get_config_data('CONVERT', 'USE_ALLELE', 'bool'))
            },
        }

        # Add the options to the parser and return the updated parser.
        parser_tool = self.subparsers.add_parser('convert',
                                                 help=description,
                                                 description=description)
        parser_tool = dynamic_cli_options(parser=parser_tool,
                                          options=parser_options)