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]
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)
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)
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)
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)
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)
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)