gtf2gff.py:gtf2gff.pl 的替代品

最近我们不得不使用 gtf2gff.pl 工具将 CONTRASTTwinScan GTF 输出转换为许多注释工具可读取的 GFF 格式。

使用该脚本工作非常困难,它根本不报告错误,而且完全不可编程重用。互联网上有不同版本的 perl 脚本,但我们需要的是一个标准化、简短、可读的版本,使用 argparse 等标准工具进行正确的命令行解析,以及可从其他脚本使用的转换函数。

gtf2gff.py
#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""
gtf2gff.py -- 将 GTF 转换为 GFF 文件的脚本。
... 以及 gtf2gff.pl 的更好替代品

版本 1.1:Python3 就绪,各种小改进
"""
# Python 2.x 支持
from __future__ import with_statement, print_function
import argparse
import sys
import os.path

__author__    = "Uli Köhler & Anton Smirnov"
__copyright__ = "Copyright 2013 Uli Köhler & Anton Smirnov"
__license__   = "Apache v2.0"
__version__   = "1.1"

class GTFException(Exception):
    pass

def gtf2gff(infilepath, outfilepath, startindex, endindex, program):
    with open(infilepath, "r") as infile, open(outfilepath, "w") as outfile:
        genId = 0
        for line in infile:
            line = line.strip()
            if not line: continue
            words = line.split("\t")
            if len(words) != 9:
                raise GTFException("Encountered %d columns instead of the expected 9 in line: '%s'" % (len(words), line))
            if words[2].find("start_codon") != -1 and words[6] == "+":
                genId += 1
            if words[2].find("stop_codon") != -1 and words[6] == "-":
                genId += 1
            if int(words[3]) >= startindex and int(words[3]) <= endindex:
                words[0] += "_%d" % genId
                words[1] = program
                words[3] = str(int(words[3]) - startindex)
                words[4] = str(int(words[4]) - startindex)
                print ("\t".join(words), file=outfile)
            if int(words[3]) > endindex:
                break

if __name__ == "__main__":
    parser = argparse.ArgumentParser()
    parser.add_argument('-s', '--startindex', help="Start index of the part to extract. Entry Indices will be adjusted to this value, meaning, here you should be precise. Take the value: Sbjct_Index - Query_Index", type=int, nargs="?")
    parser.add_argument('-l', '--length', help="Start  index of the part to extract. Entry Indices will  be adjusted to this  value, meaning, here you should be precise. Take  the value: Sbjct_Index -  Query_Index", type=int, nargs="?")
    parser.add_argument('-e', '--endindex', help="End index. Only Entries smaller than this value are included", type=int, nargs="?")
    parser.add_argument('-p', '--program', help='The name of the program which generated the GTF file, e.g. twinscan or CONTRAST',required=True)
    parser.add_argument('infile', help="The GTF input file.",)
    parser.add_argument('outfile', help="The GFF output file.", nargs="?")
    args = parser.parse_args()
    #检查参数一致性
    num_length_args = (1 if args.startindex is not None else 0) \
        + (1 if args.endindex is not None  else 0) \
        + (1 if args.length is not None  else 0)
    if num_length_args < 2:
        parser.print_help()
        print ("你需要指定 --startindex、--length 和 --endindex 中的至少两个")
        sys.exit(1)
    if args.startindex is not None and args.endindex is not None and args.startindex > args.endindex:
        parser.print_help()
        print('检查你的开始和结束索引!')
        sys.exit(1)
    if args.length is not None and args.length < 1:
        parser.print_help()
        print('长度太短')
        sys.exit(1)
    if args.length is not None and args.startindex is not None and args.endindex is not None and (args.endindex - args.startindex) != args.length:
        parser.print_help()
        print('长度与开始/结束索引不匹配。')
        sys.exit(1)
    if args.startindex is None: args.startindex = args.endindex - args.length
    if args.endindex is None: args.endindex = args.startindex + args.length
    # 构建 if
    outfilename = args.outfile
    if outfilename is None:
        outfilename = "{}.gff".format(os.path.splitext(args.infile)[0])
    #执行转换器
    print(args.infile, outfilename)
    gtf2gff(args.infile, outfilename, args.startindex, args.endindex, args.program)

Check out similar posts by category: Allgemein