Ejemplo n.º 1
0
def main(args=None, log_level=None):
    """
     main entry point to integron_split

    :param str args: the arguments passed on the command line
    :param log_level: the output verbosity
    :type log_level: a positive int or a string among 'DEBUG', 'INFO', 'WARNING', 'ERROR', 'CRITICAL'
    """
    global _log

    args = sys.argv[1:] if args is None else args
    parsed_args = parse_args(args)

    integron_finder.init_logger(log_file=os.path.join(parsed_args.outdir, 'integron_split.out'),
                                out=not parsed_args.mute)
    _log = colorlog.getLogger('integron_finder.split')

    if not log_level:
        # logs are specify from args options
        logger_set_level(utils.log_level(parsed_args.verbose, parsed_args.quiet))
    else:
        # used by unit tests to mute or unmute logs
        logger_set_level(log_level)

    chunk_names = split(parsed_args.replicon, chunk=parsed_args.chunk, outdir=parsed_args.outdir)
    print(' '.join(chunk_names))
Ejemplo n.º 2
0
def main(args=None, log_level=None):
    """
     main entry point to integron_split

    :param str args: the arguments passed on the command line
    :param log_level: the output verbosity
    :type log_level: a positive int or a string among 'DEBUG', 'INFO', 'WARNING', 'ERROR', 'CRITICAL'
    """
    global _log

    args = sys.argv[1:] if args is None else args
    parsed_args = parse_args(args)

    integron_finder.init_logger(log_file=os.path.join(parsed_args.outdir,
                                                      'integron_split.out'),
                                out=not parsed_args.mute)
    _log = colorlog.getLogger('integron_finder.split')

    if not log_level:
        # logs are specify from args options
        logger_set_level(
            utils.log_level(parsed_args.verbose, parsed_args.quiet))
    else:
        # used by unit tests to mute or unmute logs
        logger_set_level(log_level)

    chunk_names = split(parsed_args.replicon,
                        chunk=parsed_args.chunk,
                        outdir=parsed_args.outdir)
    print(' '.join(chunk_names))
Ejemplo n.º 3
0
 def setUp(self):
     logger_set_level('INFO')
     self.tmp_dir = os.path.join(tempfile.gettempdir(),
                                 'tmp_test_integron_finder')
     if os.path.isdir(self.tmp_dir):
         shutil.rmtree(self.tmp_dir)
     os.makedirs(self.tmp_dir)
Ejemplo n.º 4
0
 def test_merge_no_files(self):
     outfile = os.path.join(self.out_dir, 'merged.integrons')
     for rep, res_dir in zip(self.replicons, self.res_dirs):
         os.unlink(os.path.join(res_dir, "{}.integrons".format(rep)))
     exp_msg = 'No integrons file to merge'
     with self.assertRaises(IntegronError) as ctx:
         # 100 is to disable CRITICAL log message
         logger_set_level(100)
         merge.merge_integrons(outfile, *self.res_dirs)
     self.assertEqual(str(ctx.exception), exp_msg)
Ejemplo n.º 5
0
 def test_merge_no_files(self):
     outfile = os.path.join(self.out_dir, 'merged.integrons')
     for rep, res_dir in zip(self.replicons, self.res_dirs):
         os.unlink(os.path.join(res_dir, "{}.integrons".format(rep)))
     exp_msg = 'No integrons file to merge'
     with self.assertRaises(IntegronError) as ctx:
         # 100 is to disable CRITICAL log message
         logger_set_level(100)
         merge.merge_integrons(outfile, *self.res_dirs)
     self.assertEqual(str(ctx.exception), exp_msg)
Ejemplo n.º 6
0
    def set_log_level(cls, level):
        levels = {'NOTSET': colorlog.logging.logging.NOTSET,
                  'DEBUG': colorlog.logging.logging.DEBUG,
                  'INFO': colorlog.logging.logging.INFO,
                  'WARNING': colorlog.logging.logging.WARNING,
                  'ERROR': colorlog.logging.logging.ERROR,
                  'CRITICAL': colorlog.logging.logging.CRITICAL,
        }
        if level in levels:
            level = levels[level]
        elif not isinstance(level, int):
            raise IntegronError("Level must be {} or a positive integer")
        elif level < 0:
            raise IntegronError("Level must be {} or a positive integer")

        logger_set_level(level)
Ejemplo n.º 7
0
    def set_log_level(cls, level):
        levels = {
            'NOTSET': colorlog.logging.logging.NOTSET,
            'DEBUG': colorlog.logging.logging.DEBUG,
            'INFO': colorlog.logging.logging.INFO,
            'WARNING': colorlog.logging.logging.WARNING,
            'ERROR': colorlog.logging.logging.ERROR,
            'CRITICAL': colorlog.logging.logging.CRITICAL,
        }
        if level in levels:
            level = levels[level]
        elif not isinstance(level, int):
            raise IntegronError("Level must be {} or a positive integer")
        elif level < 0:
            raise IntegronError("Level must be {} or a positive integer")

        logger_set_level(level)
Ejemplo n.º 8
0
def main(args=None, log_level=None):
    """
     main entry point to integron_merge

    :param str args: the arguments passed on the command line
    :param log_level: the output verbosity
    :type log_level: a positive int or a string among 'DEBUG', 'INFO', 'WARNING', 'ERROR', 'CRITICAL'
    """
    global _log

    args = sys.argv[1:] if args is None else args
    parsed_args = parse_args(args)

    integron_finder.init_logger()
    _log = colorlog.getLogger('integron_finder.merge')

    if not log_level:
        # logs are specify from args options
        if not log_level:
            # logs are specify from args options
            logger_set_level(
                utils.log_level(parsed_args.verbose, parsed_args.quiet))
    else:
        # used by unit tests to mute or unmute logs
        logger_set_level(log_level)

    outdir = os.path.realpath(parsed_args.outdir)
    if os.path.exists(outdir):
        if not os.path.isdir(outdir):
            msg = "'{}' already exists and is not a directory".format(outdir)
            _log.critical(msg)
            raise IOError(msg)
    else:
        os.makedirs(parsed_args.outdir)

    integron_file_out = os.path.join(outdir,
                                     parsed_args.outfile + ".integrons")
    merge_integrons(integron_file_out, *parsed_args.results)
    summary_file_out = os.path.join(outdir, parsed_args.outfile + ".summary")
    merge_summary(summary_file_out, *parsed_args.results)
    copy_file(outdir, '.gbk', *parsed_args.results)
    copy_file(outdir, '.pdf', *parsed_args.results)
    copy_dir(outdir, 'tmp_*', *parsed_args.results)
Ejemplo n.º 9
0
def main(args=None, log_level=None):
    """
     main entry point to integron_merge

    :param str args: the arguments passed on the command line
    :param log_level: the output verbosity
    :type log_level: a positive int or a string among 'DEBUG', 'INFO', 'WARNING', 'ERROR', 'CRITICAL'
    """
    global _log

    args = sys.argv[1:] if args is None else args
    parsed_args = parse_args(args)

    integron_finder.init_logger()
    _log = colorlog.getLogger('integron_finder.merge')

    if not log_level:
        # logs are specify from args options
        if not log_level:
            # logs are specify from args options
            logger_set_level(utils.log_level(parsed_args.verbose, parsed_args.quiet))
    else:
        # used by unit tests to mute or unmute logs
        logger_set_level(log_level)

    outdir = os.path.realpath(parsed_args.outdir)
    if os.path.exists(outdir):
        if not os.path.isdir(outdir):
            msg = "'{}' already exists and is not a directory".format(outdir)
            _log.critical(msg)
            raise IOError(msg)
    else:
        os.makedirs(parsed_args.outdir)

    integron_file_out = os.path.join(outdir, parsed_args.outfile + ".integrons")
    merge_integrons(integron_file_out, *parsed_args.results)
    summary_file_out = os.path.join(outdir, parsed_args.outfile + ".summary")
    merge_summary(summary_file_out, *parsed_args.results)
    copy_file(outdir, '.gbk', *parsed_args.results)
    copy_file(outdir, '.pdf', *parsed_args.results)
    copy_dir(outdir, 'tmp_*', *parsed_args.results)
Ejemplo n.º 10
0
def main(args=None, loglevel=None):
    """
    main entry point to integron_finder

    :param str args: the arguments passed on the command line
    :param loglevel: the output verbosity
    :type loglevel: a positive int or a string among 'DEBUG', 'INFO', 'WARNING', 'ERROR', 'CRITICAL'
    """
    global _log

    args = sys.argv[1:] if args is None else args
    config = parse_args(args)

    ###################################
    # Prepare directories for results #
    ###################################

    # need to create directory before to init logger
    # as we write log in integron_finder.out in this dir

    if not os.path.exists(config.outdir):
        os.mkdir(config.outdir)
    else:
        if not os.path.isdir(config.outdir):
            msg = "outdir '{}' already exists and is not a directory".format(config.outdir)
            # _log.critical(msg)
            # we can not log it because logger are not initialized yet.
            raise IsADirectoryError(msg)

    if not os.path.exists(config.result_dir):
        os.mkdir(config.result_dir)
    else:
        if not os.path.isdir(config.result_dir):
            msg = "result dir '{}' already exists and is not a directory".format(config.outdir)
            # _log.critical(msg)
            # we can not log it because logger are not initialized yet.
            raise IsADirectoryError(msg)
        elif not os.access(config.result_dir, os.W_OK):
            msg = "result dir '{}' already exists and is not writable".format(config.outdir)
            # _log.critical(msg)
            # we can not log it because logger are not initialized yet.
            raise PermissionError(msg)

    ####################
    # init the loggers #
    ####################
    log_file = os.path.join(config.result_dir, 'integron_finder.out')
    integron_finder.init_logger(log_file=log_file,
                                out=not config.mute)

    _log = colorlog.getLogger('integron_finder')

    if not loglevel:
        # logs are specify from args options
        logger_set_level(config.log_level)
    else:
        # used by unit tests to mute or unmute logs
        logger_set_level(loglevel)

    #######################################
    # do last config check before running #
    #######################################
    if config.cmsearch is None:
        msg = """cannot find 'cmsearch' in PATH.
Please install infernal package or setup 'cmsearch' binary path with --cmsearch option"""
        _log.critical(msg)
        raise RuntimeError(msg)

    if config.hmmsearch is None:
        msg = """cannot find 'hmmsearch' in PATH.
Please install hmmer package or setup 'hmmsearch' binary path with --hmmsearch option"""
        _log.critical(msg)
        raise RuntimeError(msg)

    if config.prodigal is None:
        msg = """cannot find 'prodigal' in PATH.
Please install prodigal package or setup 'prodigal' binary path with --prodigal option"""
        _log.critical(msg)
        raise RuntimeError(msg)

    ################
    # print Header #
    ################
    log_header = colorlog.getLogger('integron_finder.header')
    logging = colorlog.logging.logging
    handlers = []
    header_log_file = logging.FileHandler(log_file)
    handlers.append(header_log_file)
    if not config.mute:
        header_stream = colorlog.StreamHandler(sys.stdout)
        handlers.append(header_stream)
    formatter = colorlog.ColoredFormatter("%(message)s")
    for h in handlers:
        h.setFormatter(formatter)
        log_header.addHandler(h)
    log_header.setLevel(colorlog.logging.logging.INFO)
    log_header.propagate = False
    log_header.info(header(args))

    with utils.FastaIterator(config.input_seq_path, dist_threshold=config.distance_threshold) as sequences_db:
        ################
        # set topology #
        ################
        default_topology = 'circ' if len(sequences_db) == 1 else 'lin'
        if config.linear:
            default_topology = 'lin'
        elif config.circular:
            default_topology = 'circ'
        # the both options are mutually exclusive
        topologies = Topology(default_topology, topology_file=config.topology_file)

        # allow sequences_db to inject topology information
        # in seq.topology attribute
        sequences_db.topologies = topologies

        ##############
        # do the job #
        ##############
        sequences_db_len = len(sequences_db)
        all_integrons = []
        all_summaries = []
        for rep_no, replicon in enumerate(sequences_db, 1):
            # if replicon contains illegal characters
            # or replicon is too short < 50 bp
            # then replicon is None
            if replicon is not None:
                _log.info("############ Processing replicon {} ({}/{}) ############\n".format(replicon.id,
                                                                                              rep_no,
                                                                                              sequences_db_len))
                integron_res, summary = find_integron_in_one_replicon(replicon, config)
                if integron_res:
                    all_integrons.append(integron_res)
                if summary:
                    all_summaries.append(summary)
            else:
                _log.warning("############ Skipping replicon {}/{} ############".format(rep_no,
                                                                                        sequences_db_len))

    if not config.split_results:
        _log.info("Merging integrons results.\n")
        agg_integrons = results.merge_results(*all_integrons)
        agg_summary = results.merge_results(*all_summaries)
        outfile_base_name = os.path.join(config.result_dir, utils.get_name_from_path(config.input_seq_path))
        merged_integron_file = outfile_base_name + ".integrons"
        if not agg_integrons.empty:
            agg_integrons.to_csv(merged_integron_file, sep="\t", index=False, na_rep="NA")
        else:
            with open(merged_integron_file, "w") as out_f:
                out_f.write("# No Integron found\n")
        merged_summary_file = outfile_base_name + ".summary"
        if not agg_integrons.empty:
            agg_summary.to_csv(merged_summary_file, sep="\t", index=False, na_rep="NA",
                               columns=['ID_replicon', 'ID_integron', 'complete', 'In0', 'CALIN'])

        for _file in all_integrons + all_summaries:
            if _file != merged_integron_file and _file != merged_summary_file:
                # in special case where the merged file has the same name that a replicon result file
                os.unlink(_file)
Ejemplo n.º 11
0
 def tearDown(self):
     if os.path.exists(self.out_dir) and os.path.isdir(self.out_dir):
         shutil.rmtree(self.out_dir)
     logger_set_level('INFO')
Ejemplo n.º 12
0
 def tearDown(self):
     if os.path.exists(self.out_dir) and os.path.isdir(self.out_dir):
         shutil.rmtree(self.out_dir)
     logger_set_level('INFO')
Ejemplo n.º 13
0
def main(args=None, loglevel=None):
    """
    main entry point to integron_finder

    :param str args: the arguments passed on the command line
    :param loglevel: the output verbosity
    :type loglevel: a positive int or a string among 'DEBUG', 'INFO', 'WARNING', 'ERROR', 'CRITICAL'
    """
    global _log

    args = sys.argv[1:] if args is None else args
    config = parse_args(args)

    ###################################
    # Prepare directories for results #
    ###################################

    # need to create directory before to init logger
    # as we write log in integron_finder.out in this dir

    if not os.path.exists(config.outdir):
        os.mkdir(config.outdir)
    else:
        if not os.path.isdir(config.outdir):
            msg = "outdir '{}' already exists and is not a directory".format(
                config.outdir)
            # _log.critical(msg)
            # we can not log it because logger are not initialized yet.
            raise IsADirectoryError(msg)

    if not os.path.exists(config.result_dir):
        os.mkdir(config.result_dir)
    else:
        if not os.path.isdir(config.result_dir):
            msg = "result dir '{}' already exists and is not a directory".format(
                config.outdir)
            # _log.critical(msg)
            # we can not log it because logger are not initialized yet.
            raise IsADirectoryError(msg)
        elif not os.access(config.result_dir, os.W_OK):
            msg = "result dir '{}' already exists and is not writable".format(
                config.outdir)
            # _log.critical(msg)
            # we can not log it because logger are not initialized yet.
            raise PermissionError(msg)

    ####################
    # init the loggers #
    ####################
    log_file = os.path.join(config.result_dir, 'integron_finder.out')
    integron_finder.init_logger(log_file=log_file, out=not config.mute)

    _log = colorlog.getLogger('integron_finder')

    if not loglevel:
        # logs are specify from args options
        logger_set_level(config.log_level)
    else:
        # used by unit tests to mute or unmute logs
        logger_set_level(loglevel)

    #######################################
    # do last config check before running #
    #######################################
    if config.cmsearch is None:
        msg = """cannot find 'cmsearch' in PATH.
Please install infernal package or setup 'cmsearch' binary path with --cmsearch option"""
        _log.critical(msg)
        raise RuntimeError(msg)

    if config.hmmsearch is None:
        msg = """cannot find 'hmmsearch' in PATH.
Please install hmmer package or setup 'hmmsearch' binary path with --hmmsearch option"""
        _log.critical(msg)
        raise RuntimeError(msg)

    if config.prodigal is None:
        msg = """cannot find 'prodigal' in PATH.
Please install prodigal package or setup 'prodigal' binary path with --prodigal option"""
        _log.critical(msg)
        raise RuntimeError(msg)

    ################
    # print Header #
    ################
    log_header = colorlog.getLogger('integron_finder.header')
    logging = colorlog.logging.logging
    handlers = []
    header_log_file = logging.FileHandler(log_file)
    handlers.append(header_log_file)
    if not config.mute:
        header_stream = colorlog.StreamHandler(sys.stdout)
        handlers.append(header_stream)
    formatter = colorlog.ColoredFormatter("%(message)s")
    for h in handlers:
        h.setFormatter(formatter)
        log_header.addHandler(h)
    log_header.setLevel(colorlog.logging.logging.INFO)
    log_header.propagate = False
    log_header.info(header(args))

    with utils.FastaIterator(
            config.input_seq_path,
            dist_threshold=config.distance_threshold) as sequences_db:
        ################
        # set topology #
        ################
        default_topology = 'circ' if len(sequences_db) == 1 else 'lin'
        if config.linear:
            default_topology = 'lin'
        elif config.circular:
            default_topology = 'circ'
        # the both options are mutually exclusive
        topologies = Topology(default_topology,
                              topology_file=config.topology_file)

        # allow sequences_db to inject topology information
        # in seq.topology attribute
        sequences_db.topologies = topologies

        ##############
        # do the job #
        ##############
        sequences_db_len = len(sequences_db)
        all_integrons = []
        all_summaries = []
        for rep_no, replicon in enumerate(sequences_db, 1):
            # if replicon contains illegal characters
            # or replicon is too short < 50 bp
            # then replicon is None
            if replicon is not None:
                _log.info(
                    "############ Processing replicon {} ({}/{}) ############\n"
                    .format(replicon.id, rep_no, sequences_db_len))
                integron_res, summary = find_integron_in_one_replicon(
                    replicon, config)
                if integron_res:
                    all_integrons.append(integron_res)
                if summary:
                    all_summaries.append(summary)
            else:
                _log.warning(
                    "############ Skipping replicon {}/{} ############".format(
                        rep_no, sequences_db_len))

    if not config.split_results:
        _log.info("Merging integrons results.\n")
        agg_integrons = results.merge_results(*all_integrons)
        agg_summary = results.merge_results(*all_summaries)
        outfile_base_name = os.path.join(
            config.result_dir, utils.get_name_from_path(config.input_seq_path))
        merged_integron_file = outfile_base_name + ".integrons"
        if not agg_integrons.empty:
            agg_integrons.to_csv(merged_integron_file,
                                 sep="\t",
                                 index=False,
                                 na_rep="NA")
        else:
            with open(merged_integron_file, "w") as out_f:
                out_f.write("# No Integron found\n")
        merged_summary_file = outfile_base_name + ".summary"
        if not agg_integrons.empty:
            agg_summary.to_csv(merged_summary_file,
                               sep="\t",
                               index=False,
                               na_rep="NA",
                               columns=[
                                   'ID_replicon', 'ID_integron', 'complete',
                                   'In0', 'CALIN'
                               ])

        for _file in all_integrons + all_summaries:
            if _file != merged_integron_file and _file != merged_summary_file:
                # in special case where the merged file has the same name that a replicon result file
                os.unlink(_file)
Ejemplo n.º 14
0
 def setUp(self):
     logger_set_level('INFO')
     self.tmp_dir = os.path.join(tempfile.gettempdir(), 'tmp_test_integron_finder')
     if os.path.isdir(self.tmp_dir):
         shutil.rmtree(self.tmp_dir)
     os.makedirs(self.tmp_dir)