annotate blastxml_to_tabular_selectable.py @ 1:5da5dcc5e13a default tip

Update from 24 to 25 columns and update versions to 1.0.0
author Jim Johnson <jj@umn.edu>
date Wed, 08 Oct 2014 18:57:39 -0500
parents 2bd0cbccb3c6
children
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
0
2bd0cbccb3c6 Uploaded
galaxyp
parents:
diff changeset
1 #!/usr/bin/env python
2bd0cbccb3c6 Uploaded
galaxyp
parents:
diff changeset
2 """Convert a BLAST XML file to 12 column tabular output
2bd0cbccb3c6 Uploaded
galaxyp
parents:
diff changeset
3
2bd0cbccb3c6 Uploaded
galaxyp
parents:
diff changeset
4 Takes three command line options, input BLAST XML filename, output tabular
2bd0cbccb3c6 Uploaded
galaxyp
parents:
diff changeset
5 BLAST filename, output format (std for standard 12 columns, or ext for the
2bd0cbccb3c6 Uploaded
galaxyp
parents:
diff changeset
6 extended 25 columns offered in the BLAST+ wrappers).
2bd0cbccb3c6 Uploaded
galaxyp
parents:
diff changeset
7
2bd0cbccb3c6 Uploaded
galaxyp
parents:
diff changeset
8 The 12 columns output are 'qseqid sseqid pident length mismatch gapopen qstart
2bd0cbccb3c6 Uploaded
galaxyp
parents:
diff changeset
9 qend sstart send evalue bitscore' or 'std' at the BLAST+ command line, which
2bd0cbccb3c6 Uploaded
galaxyp
parents:
diff changeset
10 mean:
2bd0cbccb3c6 Uploaded
galaxyp
parents:
diff changeset
11
2bd0cbccb3c6 Uploaded
galaxyp
parents:
diff changeset
12 ====== ========= ============================================
2bd0cbccb3c6 Uploaded
galaxyp
parents:
diff changeset
13 Column NCBI name Description
2bd0cbccb3c6 Uploaded
galaxyp
parents:
diff changeset
14 ------ --------- --------------------------------------------
2bd0cbccb3c6 Uploaded
galaxyp
parents:
diff changeset
15 1 qseqid Query Seq-id (ID of your sequence)
2bd0cbccb3c6 Uploaded
galaxyp
parents:
diff changeset
16 2 sseqid Subject Seq-id (ID of the database hit)
2bd0cbccb3c6 Uploaded
galaxyp
parents:
diff changeset
17 3 pident Percentage of identical matches
2bd0cbccb3c6 Uploaded
galaxyp
parents:
diff changeset
18 4 length Alignment length
2bd0cbccb3c6 Uploaded
galaxyp
parents:
diff changeset
19 5 mismatch Number of mismatches
2bd0cbccb3c6 Uploaded
galaxyp
parents:
diff changeset
20 6 gapopen Number of gap openings
2bd0cbccb3c6 Uploaded
galaxyp
parents:
diff changeset
21 7 qstart Start of alignment in query
2bd0cbccb3c6 Uploaded
galaxyp
parents:
diff changeset
22 8 qend End of alignment in query
2bd0cbccb3c6 Uploaded
galaxyp
parents:
diff changeset
23 9 sstart Start of alignment in subject (database hit)
2bd0cbccb3c6 Uploaded
galaxyp
parents:
diff changeset
24 10 send End of alignment in subject (database hit)
2bd0cbccb3c6 Uploaded
galaxyp
parents:
diff changeset
25 11 evalue Expectation value (E-value)
2bd0cbccb3c6 Uploaded
galaxyp
parents:
diff changeset
26 12 bitscore Bit score
2bd0cbccb3c6 Uploaded
galaxyp
parents:
diff changeset
27 ====== ========= ============================================
2bd0cbccb3c6 Uploaded
galaxyp
parents:
diff changeset
28
2bd0cbccb3c6 Uploaded
galaxyp
parents:
diff changeset
29 The additional columns offered in the Galaxy BLAST+ wrappers are:
2bd0cbccb3c6 Uploaded
galaxyp
parents:
diff changeset
30
2bd0cbccb3c6 Uploaded
galaxyp
parents:
diff changeset
31 ====== ============= ===========================================
2bd0cbccb3c6 Uploaded
galaxyp
parents:
diff changeset
32 Column NCBI name Description
2bd0cbccb3c6 Uploaded
galaxyp
parents:
diff changeset
33 ------ ------------- -------------------------------------------
2bd0cbccb3c6 Uploaded
galaxyp
parents:
diff changeset
34 13 sallseqid All subject Seq-id(s), separated by a ';'
2bd0cbccb3c6 Uploaded
galaxyp
parents:
diff changeset
35 14 score Raw score
2bd0cbccb3c6 Uploaded
galaxyp
parents:
diff changeset
36 15 nident Number of identical matches
2bd0cbccb3c6 Uploaded
galaxyp
parents:
diff changeset
37 16 positive Number of positive-scoring matches
2bd0cbccb3c6 Uploaded
galaxyp
parents:
diff changeset
38 17 gaps Total number of gaps
2bd0cbccb3c6 Uploaded
galaxyp
parents:
diff changeset
39 18 ppos Percentage of positive-scoring matches
2bd0cbccb3c6 Uploaded
galaxyp
parents:
diff changeset
40 19 qframe Query frame
2bd0cbccb3c6 Uploaded
galaxyp
parents:
diff changeset
41 20 sframe Subject frame
2bd0cbccb3c6 Uploaded
galaxyp
parents:
diff changeset
42 21 qseq Aligned part of query sequence
2bd0cbccb3c6 Uploaded
galaxyp
parents:
diff changeset
43 22 sseq Aligned part of subject sequence
2bd0cbccb3c6 Uploaded
galaxyp
parents:
diff changeset
44 23 qlen Query sequence length
2bd0cbccb3c6 Uploaded
galaxyp
parents:
diff changeset
45 24 slen Subject sequence length
2bd0cbccb3c6 Uploaded
galaxyp
parents:
diff changeset
46 25 salltitles All subject titles, separated by '&lt;&gt;'
2bd0cbccb3c6 Uploaded
galaxyp
parents:
diff changeset
47 ====== ============= ===========================================
2bd0cbccb3c6 Uploaded
galaxyp
parents:
diff changeset
48
2bd0cbccb3c6 Uploaded
galaxyp
parents:
diff changeset
49 Most of these fields are given explicitly in the XML file, others some like
2bd0cbccb3c6 Uploaded
galaxyp
parents:
diff changeset
50 the percentage identity and the number of gap openings must be calculated.
2bd0cbccb3c6 Uploaded
galaxyp
parents:
diff changeset
51
2bd0cbccb3c6 Uploaded
galaxyp
parents:
diff changeset
52 Be aware that the sequence in the extended tabular output or XML direct from
2bd0cbccb3c6 Uploaded
galaxyp
parents:
diff changeset
53 BLAST+ may or may not use XXXX masking on regions of low complexity. This
2bd0cbccb3c6 Uploaded
galaxyp
parents:
diff changeset
54 can throw the off the calculation of percentage identity and gap openings.
2bd0cbccb3c6 Uploaded
galaxyp
parents:
diff changeset
55 [In fact, both BLAST 2.2.24+ and 2.2.25+ have a subtle bug in this regard,
2bd0cbccb3c6 Uploaded
galaxyp
parents:
diff changeset
56 with these numbers changing depending on whether or not the low complexity
2bd0cbccb3c6 Uploaded
galaxyp
parents:
diff changeset
57 filter is used.]
2bd0cbccb3c6 Uploaded
galaxyp
parents:
diff changeset
58
2bd0cbccb3c6 Uploaded
galaxyp
parents:
diff changeset
59 This script attempts to produce identical output to what BLAST+ would have done.
2bd0cbccb3c6 Uploaded
galaxyp
parents:
diff changeset
60 However, check this with "diff -b ..." since BLAST+ sometimes includes an extra
2bd0cbccb3c6 Uploaded
galaxyp
parents:
diff changeset
61 space character (probably a bug).
2bd0cbccb3c6 Uploaded
galaxyp
parents:
diff changeset
62 """
2bd0cbccb3c6 Uploaded
galaxyp
parents:
diff changeset
63 import sys
2bd0cbccb3c6 Uploaded
galaxyp
parents:
diff changeset
64 import re
2bd0cbccb3c6 Uploaded
galaxyp
parents:
diff changeset
65 import os
2bd0cbccb3c6 Uploaded
galaxyp
parents:
diff changeset
66 from optparse import OptionParser
2bd0cbccb3c6 Uploaded
galaxyp
parents:
diff changeset
67
2bd0cbccb3c6 Uploaded
galaxyp
parents:
diff changeset
68 if "-v" in sys.argv or "--version" in sys.argv:
1
5da5dcc5e13a Update from 24 to 25 columns and update versions to 1.0.0
Jim Johnson <jj@umn.edu>
parents: 0
diff changeset
69 print "v1.0.0"
0
2bd0cbccb3c6 Uploaded
galaxyp
parents:
diff changeset
70 sys.exit(0)
2bd0cbccb3c6 Uploaded
galaxyp
parents:
diff changeset
71
2bd0cbccb3c6 Uploaded
galaxyp
parents:
diff changeset
72 if sys.version_info[:2] >= ( 2, 5 ):
2bd0cbccb3c6 Uploaded
galaxyp
parents:
diff changeset
73 try:
2bd0cbccb3c6 Uploaded
galaxyp
parents:
diff changeset
74 from xml.etree import cElementTree as ElementTree
2bd0cbccb3c6 Uploaded
galaxyp
parents:
diff changeset
75 except ImportError:
2bd0cbccb3c6 Uploaded
galaxyp
parents:
diff changeset
76 from xml.etree import ElementTree as ElementTree
2bd0cbccb3c6 Uploaded
galaxyp
parents:
diff changeset
77 else:
2bd0cbccb3c6 Uploaded
galaxyp
parents:
diff changeset
78 from galaxy import eggs
2bd0cbccb3c6 Uploaded
galaxyp
parents:
diff changeset
79 import pkg_resources; pkg_resources.require( "elementtree" )
2bd0cbccb3c6 Uploaded
galaxyp
parents:
diff changeset
80 from elementtree import ElementTree
2bd0cbccb3c6 Uploaded
galaxyp
parents:
diff changeset
81
2bd0cbccb3c6 Uploaded
galaxyp
parents:
diff changeset
82 def stop_err( msg ):
2bd0cbccb3c6 Uploaded
galaxyp
parents:
diff changeset
83 sys.stderr.write("%s\n" % msg)
2bd0cbccb3c6 Uploaded
galaxyp
parents:
diff changeset
84 sys.exit(1)
2bd0cbccb3c6 Uploaded
galaxyp
parents:
diff changeset
85
2bd0cbccb3c6 Uploaded
galaxyp
parents:
diff changeset
86 usage = "usage: %prog [options] blastxml[,...]"
2bd0cbccb3c6 Uploaded
galaxyp
parents:
diff changeset
87 parser = OptionParser(usage=usage)
2bd0cbccb3c6 Uploaded
galaxyp
parents:
diff changeset
88 parser.add_option('-o','--output', dest='output', default = None, help='output file path', metavar="FILE")
2bd0cbccb3c6 Uploaded
galaxyp
parents:
diff changeset
89 parser.add_option("-c", "--columns", dest="columns", default='std', help="[std|ext|colname[,colname,...]] std: 12 column, ext: 25 column, or user specified columns")
2bd0cbccb3c6 Uploaded
galaxyp
parents:
diff changeset
90 parser.add_option("-a", "--allqueries", action="store_true", dest="allqueries", default=False, help="ouptut row for each query, including those with no hits")
2bd0cbccb3c6 Uploaded
galaxyp
parents:
diff changeset
91 parser.add_option("-d", "--qdef", action="store_true", dest="qdef", default=False, help="use Iteration_query-def for qseqid")
2bd0cbccb3c6 Uploaded
galaxyp
parents:
diff changeset
92 parser.add_option('-u', '--unmatched', dest='unmatched', default = None, help='unmatched queries file path', metavar="FILE")
2bd0cbccb3c6 Uploaded
galaxyp
parents:
diff changeset
93 parser.add_option('-m', '--maxhits', dest='maxhits', type="int", default = 1, help='maximum number of HITs for output for a Query')
2bd0cbccb3c6 Uploaded
galaxyp
parents:
diff changeset
94 parser.add_option('-p', '--maxhsps', dest='maxhsps', type="int", default = 1, help='maximum number of HSPs for output for a Hit')
2bd0cbccb3c6 Uploaded
galaxyp
parents:
diff changeset
95 (options, args) = parser.parse_args()
2bd0cbccb3c6 Uploaded
galaxyp
parents:
diff changeset
96
2bd0cbccb3c6 Uploaded
galaxyp
parents:
diff changeset
97 colnames = 'qseqid,sseqid,pident,length,mismatch,gapopen,qstart,qend,sstart,send,evalue,bitscore,sallseqid,score,nident,positive,gaps,ppos,qframe,sframe,qseq,sseq,qlen,slen,salltitles'.split(',')
2bd0cbccb3c6 Uploaded
galaxyp
parents:
diff changeset
98
2bd0cbccb3c6 Uploaded
galaxyp
parents:
diff changeset
99 if len(args) < 1:
2bd0cbccb3c6 Uploaded
galaxyp
parents:
diff changeset
100 parser.error("no BLASTXML input files")
2bd0cbccb3c6 Uploaded
galaxyp
parents:
diff changeset
101
2bd0cbccb3c6 Uploaded
galaxyp
parents:
diff changeset
102 if options.columns == "std":
2bd0cbccb3c6 Uploaded
galaxyp
parents:
diff changeset
103 out_fmt = 'std'
2bd0cbccb3c6 Uploaded
galaxyp
parents:
diff changeset
104 extended = False
2bd0cbccb3c6 Uploaded
galaxyp
parents:
diff changeset
105 columns = colnames[0:12]
2bd0cbccb3c6 Uploaded
galaxyp
parents:
diff changeset
106 elif options.columns == "x22":
2bd0cbccb3c6 Uploaded
galaxyp
parents:
diff changeset
107 stop_err("Format argument x22 has been replaced with ext (extended 25 columns)")
2bd0cbccb3c6 Uploaded
galaxyp
parents:
diff changeset
108 elif options.columns == "ext":
2bd0cbccb3c6 Uploaded
galaxyp
parents:
diff changeset
109 out_fmt = 'ext'
2bd0cbccb3c6 Uploaded
galaxyp
parents:
diff changeset
110 extended = True
2bd0cbccb3c6 Uploaded
galaxyp
parents:
diff changeset
111 columns = colnames[0:25]
2bd0cbccb3c6 Uploaded
galaxyp
parents:
diff changeset
112 else:
2bd0cbccb3c6 Uploaded
galaxyp
parents:
diff changeset
113 out_fmt = 'cols'
2bd0cbccb3c6 Uploaded
galaxyp
parents:
diff changeset
114 extended = True
2bd0cbccb3c6 Uploaded
galaxyp
parents:
diff changeset
115 sel_cols = options.columns.split(',')
2bd0cbccb3c6 Uploaded
galaxyp
parents:
diff changeset
116 columns = []
2bd0cbccb3c6 Uploaded
galaxyp
parents:
diff changeset
117 for col in sel_cols:
2bd0cbccb3c6 Uploaded
galaxyp
parents:
diff changeset
118 if col in colnames:
2bd0cbccb3c6 Uploaded
galaxyp
parents:
diff changeset
119 columns.append(col)
2bd0cbccb3c6 Uploaded
galaxyp
parents:
diff changeset
120
2bd0cbccb3c6 Uploaded
galaxyp
parents:
diff changeset
121 for in_file in args:
2bd0cbccb3c6 Uploaded
galaxyp
parents:
diff changeset
122 if not os.path.isfile(in_file):
2bd0cbccb3c6 Uploaded
galaxyp
parents:
diff changeset
123 stop_err("Input BLAST XML file not found: %s" % in_file)
2bd0cbccb3c6 Uploaded
galaxyp
parents:
diff changeset
124
2bd0cbccb3c6 Uploaded
galaxyp
parents:
diff changeset
125 unhitfile = open(options.unmatched,'w') if options.unmatched else None
2bd0cbccb3c6 Uploaded
galaxyp
parents:
diff changeset
126
2bd0cbccb3c6 Uploaded
galaxyp
parents:
diff changeset
127 re_default_query_id = re.compile("^Query_\d+$")
2bd0cbccb3c6 Uploaded
galaxyp
parents:
diff changeset
128 assert re_default_query_id.match("Query_101")
2bd0cbccb3c6 Uploaded
galaxyp
parents:
diff changeset
129 assert not re_default_query_id.match("Query_101a")
2bd0cbccb3c6 Uploaded
galaxyp
parents:
diff changeset
130 assert not re_default_query_id.match("MyQuery_101")
2bd0cbccb3c6 Uploaded
galaxyp
parents:
diff changeset
131 re_default_subject_id = re.compile("^Subject_\d+$")
2bd0cbccb3c6 Uploaded
galaxyp
parents:
diff changeset
132 assert re_default_subject_id.match("Subject_1")
2bd0cbccb3c6 Uploaded
galaxyp
parents:
diff changeset
133 assert not re_default_subject_id.match("Subject_")
2bd0cbccb3c6 Uploaded
galaxyp
parents:
diff changeset
134 assert not re_default_subject_id.match("Subject_12a")
2bd0cbccb3c6 Uploaded
galaxyp
parents:
diff changeset
135 assert not re_default_subject_id.match("TheSubject_1")
2bd0cbccb3c6 Uploaded
galaxyp
parents:
diff changeset
136
2bd0cbccb3c6 Uploaded
galaxyp
parents:
diff changeset
137 header = "#%s\n" % "\t".join(columns)
2bd0cbccb3c6 Uploaded
galaxyp
parents:
diff changeset
138 outfile = open(options.output, 'w') if options.output else sys.stdout
2bd0cbccb3c6 Uploaded
galaxyp
parents:
diff changeset
139 outfile.write(header)
2bd0cbccb3c6 Uploaded
galaxyp
parents:
diff changeset
140
2bd0cbccb3c6 Uploaded
galaxyp
parents:
diff changeset
141 def handle_event(event, elem):
2bd0cbccb3c6 Uploaded
galaxyp
parents:
diff changeset
142 blast_program = None
2bd0cbccb3c6 Uploaded
galaxyp
parents:
diff changeset
143 if event == "end" and elem.tag == "BlastOutput_program":
2bd0cbccb3c6 Uploaded
galaxyp
parents:
diff changeset
144 blast_program = elem.text
2bd0cbccb3c6 Uploaded
galaxyp
parents:
diff changeset
145 # for every <Iteration> tag
2bd0cbccb3c6 Uploaded
galaxyp
parents:
diff changeset
146 if event == "end" and elem.tag == "Iteration":
2bd0cbccb3c6 Uploaded
galaxyp
parents:
diff changeset
147 #Expecting either this, from BLAST 2.2.25+ using FASTA vs FASTA
2bd0cbccb3c6 Uploaded
galaxyp
parents:
diff changeset
148 # <Iteration_query-ID>sp|Q9BS26|ERP44_HUMAN</Iteration_query-ID>
2bd0cbccb3c6 Uploaded
galaxyp
parents:
diff changeset
149 # <Iteration_query-def>Endoplasmic reticulum resident protein 44 OS=Homo sapiens GN=ERP44 PE=1 SV=1</Iteration_query-def>
2bd0cbccb3c6 Uploaded
galaxyp
parents:
diff changeset
150 # <Iteration_query-len>406</Iteration_query-len>
2bd0cbccb3c6 Uploaded
galaxyp
parents:
diff changeset
151 # <Iteration_hits></Iteration_hits>
2bd0cbccb3c6 Uploaded
galaxyp
parents:
diff changeset
152 #
2bd0cbccb3c6 Uploaded
galaxyp
parents:
diff changeset
153 #Or, from BLAST 2.2.24+ run online
2bd0cbccb3c6 Uploaded
galaxyp
parents:
diff changeset
154 # <Iteration_query-ID>Query_1</Iteration_query-ID>
2bd0cbccb3c6 Uploaded
galaxyp
parents:
diff changeset
155 # <Iteration_query-def>Sample</Iteration_query-def>
2bd0cbccb3c6 Uploaded
galaxyp
parents:
diff changeset
156 # <Iteration_query-len>516</Iteration_query-len>
2bd0cbccb3c6 Uploaded
galaxyp
parents:
diff changeset
157 # <Iteration_hits>...
2bd0cbccb3c6 Uploaded
galaxyp
parents:
diff changeset
158 qseqid = elem.findtext("Iteration_query-ID")
2bd0cbccb3c6 Uploaded
galaxyp
parents:
diff changeset
159 if options.qdef or re_default_query_id.match(qseqid):
2bd0cbccb3c6 Uploaded
galaxyp
parents:
diff changeset
160 #Place holder ID, take the first word of the query definition
2bd0cbccb3c6 Uploaded
galaxyp
parents:
diff changeset
161 qseqid = elem.findtext("Iteration_query-def").split(None,1)[0]
2bd0cbccb3c6 Uploaded
galaxyp
parents:
diff changeset
162 qlen = int(elem.findtext("Iteration_query-len"))
2bd0cbccb3c6 Uploaded
galaxyp
parents:
diff changeset
163 # If no hits in this iteration
2bd0cbccb3c6 Uploaded
galaxyp
parents:
diff changeset
164 if not elem.find("Iteration_hits/Hit"):
2bd0cbccb3c6 Uploaded
galaxyp
parents:
diff changeset
165 if unhitfile:
2bd0cbccb3c6 Uploaded
galaxyp
parents:
diff changeset
166 unhitfile.write("%s\n" % qseqid)
2bd0cbccb3c6 Uploaded
galaxyp
parents:
diff changeset
167 if options.allqueries:
2bd0cbccb3c6 Uploaded
galaxyp
parents:
diff changeset
168 if columns and len(columns) > 0:
2bd0cbccb3c6 Uploaded
galaxyp
parents:
diff changeset
169 v = []
2bd0cbccb3c6 Uploaded
galaxyp
parents:
diff changeset
170 for name in columns:
2bd0cbccb3c6 Uploaded
galaxyp
parents:
diff changeset
171 if name == 'qseqid':
2bd0cbccb3c6 Uploaded
galaxyp
parents:
diff changeset
172 v.append(qseqid)
2bd0cbccb3c6 Uploaded
galaxyp
parents:
diff changeset
173 elif name == 'qlen':
2bd0cbccb3c6 Uploaded
galaxyp
parents:
diff changeset
174 v.append(str(qlen))
2bd0cbccb3c6 Uploaded
galaxyp
parents:
diff changeset
175 else:
2bd0cbccb3c6 Uploaded
galaxyp
parents:
diff changeset
176 v.append('')
2bd0cbccb3c6 Uploaded
galaxyp
parents:
diff changeset
177 outfile.write("\t".join(v) + "\n")
2bd0cbccb3c6 Uploaded
galaxyp
parents:
diff changeset
178 # for every <Hit> within <Iteration>
2bd0cbccb3c6 Uploaded
galaxyp
parents:
diff changeset
179 for hitn, hit in enumerate(elem.findall("Iteration_hits/Hit")):
2bd0cbccb3c6 Uploaded
galaxyp
parents:
diff changeset
180 if hitn >= options.maxhits:
2bd0cbccb3c6 Uploaded
galaxyp
parents:
diff changeset
181 break
2bd0cbccb3c6 Uploaded
galaxyp
parents:
diff changeset
182 #Expecting either this,
2bd0cbccb3c6 Uploaded
galaxyp
parents:
diff changeset
183 # <Hit_id>gi|3024260|sp|P56514.1|OPSD_BUFBU</Hit_id>
2bd0cbccb3c6 Uploaded
galaxyp
parents:
diff changeset
184 # <Hit_def>RecName: Full=Rhodopsin</Hit_def>
2bd0cbccb3c6 Uploaded
galaxyp
parents:
diff changeset
185 # <Hit_accession>P56514</Hit_accession>
2bd0cbccb3c6 Uploaded
galaxyp
parents:
diff changeset
186 #or,
2bd0cbccb3c6 Uploaded
galaxyp
parents:
diff changeset
187 # <Hit_id>Subject_1</Hit_id>
2bd0cbccb3c6 Uploaded
galaxyp
parents:
diff changeset
188 # <Hit_def>gi|57163783|ref|NP_001009242.1| rhodopsin [Felis catus]</Hit_def>
2bd0cbccb3c6 Uploaded
galaxyp
parents:
diff changeset
189 # <Hit_accession>Subject_1</Hit_accession>
2bd0cbccb3c6 Uploaded
galaxyp
parents:
diff changeset
190 #
2bd0cbccb3c6 Uploaded
galaxyp
parents:
diff changeset
191 #apparently depending on the parse_deflines switch
2bd0cbccb3c6 Uploaded
galaxyp
parents:
diff changeset
192 #
2bd0cbccb3c6 Uploaded
galaxyp
parents:
diff changeset
193 #Or, with a local database not using -parse_seqids can get this,
2bd0cbccb3c6 Uploaded
galaxyp
parents:
diff changeset
194 # <Hit_id>gnl|BL_ORD_ID|2</Hit_id>
2bd0cbccb3c6 Uploaded
galaxyp
parents:
diff changeset
195 # <Hit_def>chrIII gi|240255695|ref|NC_003074.8| Arabidopsis thaliana chromosome 3, complete sequence</Hit_def>
2bd0cbccb3c6 Uploaded
galaxyp
parents:
diff changeset
196 # <Hit_accession>2</Hit_accession>
2bd0cbccb3c6 Uploaded
galaxyp
parents:
diff changeset
197 sseqid = hit.findtext("Hit_id").split(None,1)[0]
2bd0cbccb3c6 Uploaded
galaxyp
parents:
diff changeset
198 hit_def = sseqid + " " + hit.findtext("Hit_def")
2bd0cbccb3c6 Uploaded
galaxyp
parents:
diff changeset
199 if re_default_subject_id.match(sseqid) \
2bd0cbccb3c6 Uploaded
galaxyp
parents:
diff changeset
200 and sseqid == hit.findtext("Hit_accession"):
2bd0cbccb3c6 Uploaded
galaxyp
parents:
diff changeset
201 #Place holder ID, take the first word of the subject definition
2bd0cbccb3c6 Uploaded
galaxyp
parents:
diff changeset
202 hit_def = hit.findtext("Hit_def")
2bd0cbccb3c6 Uploaded
galaxyp
parents:
diff changeset
203 sseqid = hit_def.split(None,1)[0]
2bd0cbccb3c6 Uploaded
galaxyp
parents:
diff changeset
204 # for every <Hsp> within <Hit>
2bd0cbccb3c6 Uploaded
galaxyp
parents:
diff changeset
205 for hspn,hsp in enumerate(hit.findall("Hit_hsps/Hsp")):
2bd0cbccb3c6 Uploaded
galaxyp
parents:
diff changeset
206 if hspn >= options.maxhsps:
2bd0cbccb3c6 Uploaded
galaxyp
parents:
diff changeset
207 break
2bd0cbccb3c6 Uploaded
galaxyp
parents:
diff changeset
208 nident = hsp.findtext("Hsp_identity")
2bd0cbccb3c6 Uploaded
galaxyp
parents:
diff changeset
209 length = hsp.findtext("Hsp_align-len")
2bd0cbccb3c6 Uploaded
galaxyp
parents:
diff changeset
210 pident = "%0.2f" % (100*float(nident)/float(length))
2bd0cbccb3c6 Uploaded
galaxyp
parents:
diff changeset
211
2bd0cbccb3c6 Uploaded
galaxyp
parents:
diff changeset
212 q_seq = hsp.findtext("Hsp_qseq")
2bd0cbccb3c6 Uploaded
galaxyp
parents:
diff changeset
213 h_seq = hsp.findtext("Hsp_hseq")
2bd0cbccb3c6 Uploaded
galaxyp
parents:
diff changeset
214 m_seq = hsp.findtext("Hsp_midline")
2bd0cbccb3c6 Uploaded
galaxyp
parents:
diff changeset
215 assert len(q_seq) == len(h_seq) == len(m_seq) == int(length)
2bd0cbccb3c6 Uploaded
galaxyp
parents:
diff changeset
216 gapopen = str(len(q_seq.replace('-', ' ').split())-1 + \
2bd0cbccb3c6 Uploaded
galaxyp
parents:
diff changeset
217 len(h_seq.replace('-', ' ').split())-1)
2bd0cbccb3c6 Uploaded
galaxyp
parents:
diff changeset
218
2bd0cbccb3c6 Uploaded
galaxyp
parents:
diff changeset
219 mismatch = m_seq.count(' ') + m_seq.count('+') \
2bd0cbccb3c6 Uploaded
galaxyp
parents:
diff changeset
220 - q_seq.count('-') - h_seq.count('-')
2bd0cbccb3c6 Uploaded
galaxyp
parents:
diff changeset
221 #TODO - Remove this alternative mismatch calculation and test
2bd0cbccb3c6 Uploaded
galaxyp
parents:
diff changeset
222 #once satisifed there are no problems
2bd0cbccb3c6 Uploaded
galaxyp
parents:
diff changeset
223 expected_mismatch = len(q_seq) \
2bd0cbccb3c6 Uploaded
galaxyp
parents:
diff changeset
224 - sum(1 for q,h in zip(q_seq, h_seq) \
2bd0cbccb3c6 Uploaded
galaxyp
parents:
diff changeset
225 if q == h or q == "-" or h == "-")
2bd0cbccb3c6 Uploaded
galaxyp
parents:
diff changeset
226 xx = sum(1 for q,h in zip(q_seq, h_seq) if q=="X" and h=="X")
2bd0cbccb3c6 Uploaded
galaxyp
parents:
diff changeset
227 if not (expected_mismatch - q_seq.count("X") <= int(mismatch) <= expected_mismatch + xx):
2bd0cbccb3c6 Uploaded
galaxyp
parents:
diff changeset
228 stop_err("%s vs %s mismatches, expected %i <= %i <= %i" \
2bd0cbccb3c6 Uploaded
galaxyp
parents:
diff changeset
229 % (qseqid, sseqid, expected_mismatch - q_seq.count("X"),
2bd0cbccb3c6 Uploaded
galaxyp
parents:
diff changeset
230 int(mismatch), expected_mismatch))
2bd0cbccb3c6 Uploaded
galaxyp
parents:
diff changeset
231
2bd0cbccb3c6 Uploaded
galaxyp
parents:
diff changeset
232 #TODO - Remove this alternative identity calculation and test
2bd0cbccb3c6 Uploaded
galaxyp
parents:
diff changeset
233 #once satisifed there are no problems
2bd0cbccb3c6 Uploaded
galaxyp
parents:
diff changeset
234 expected_identity = sum(1 for q,h in zip(q_seq, h_seq) if q == h)
2bd0cbccb3c6 Uploaded
galaxyp
parents:
diff changeset
235 if not (expected_identity - xx <= int(nident) <= expected_identity + q_seq.count("X")):
2bd0cbccb3c6 Uploaded
galaxyp
parents:
diff changeset
236 stop_err("%s vs %s identities, expected %i <= %i <= %i" \
2bd0cbccb3c6 Uploaded
galaxyp
parents:
diff changeset
237 % (qseqid, sseqid, expected_identity, int(nident),
2bd0cbccb3c6 Uploaded
galaxyp
parents:
diff changeset
238 expected_identity + q_seq.count("X")))
2bd0cbccb3c6 Uploaded
galaxyp
parents:
diff changeset
239
2bd0cbccb3c6 Uploaded
galaxyp
parents:
diff changeset
240
2bd0cbccb3c6 Uploaded
galaxyp
parents:
diff changeset
241 evalue = hsp.findtext("Hsp_evalue")
2bd0cbccb3c6 Uploaded
galaxyp
parents:
diff changeset
242 if evalue == "0":
2bd0cbccb3c6 Uploaded
galaxyp
parents:
diff changeset
243 evalue = "0.0"
2bd0cbccb3c6 Uploaded
galaxyp
parents:
diff changeset
244 else:
2bd0cbccb3c6 Uploaded
galaxyp
parents:
diff changeset
245 evalue = "%0.0e" % float(evalue)
2bd0cbccb3c6 Uploaded
galaxyp
parents:
diff changeset
246
2bd0cbccb3c6 Uploaded
galaxyp
parents:
diff changeset
247 bitscore = float(hsp.findtext("Hsp_bit-score"))
2bd0cbccb3c6 Uploaded
galaxyp
parents:
diff changeset
248 if bitscore < 100:
2bd0cbccb3c6 Uploaded
galaxyp
parents:
diff changeset
249 #Seems to show one decimal place for lower scores
2bd0cbccb3c6 Uploaded
galaxyp
parents:
diff changeset
250 bitscore = "%0.1f" % bitscore
2bd0cbccb3c6 Uploaded
galaxyp
parents:
diff changeset
251 else:
2bd0cbccb3c6 Uploaded
galaxyp
parents:
diff changeset
252 #Note BLAST does not round to nearest int, it truncates
2bd0cbccb3c6 Uploaded
galaxyp
parents:
diff changeset
253 bitscore = "%i" % bitscore
2bd0cbccb3c6 Uploaded
galaxyp
parents:
diff changeset
254
2bd0cbccb3c6 Uploaded
galaxyp
parents:
diff changeset
255 values = [qseqid,
2bd0cbccb3c6 Uploaded
galaxyp
parents:
diff changeset
256 sseqid,
2bd0cbccb3c6 Uploaded
galaxyp
parents:
diff changeset
257 pident,
2bd0cbccb3c6 Uploaded
galaxyp
parents:
diff changeset
258 length, #hsp.findtext("Hsp_align-len")
2bd0cbccb3c6 Uploaded
galaxyp
parents:
diff changeset
259 str(mismatch),
2bd0cbccb3c6 Uploaded
galaxyp
parents:
diff changeset
260 gapopen,
2bd0cbccb3c6 Uploaded
galaxyp
parents:
diff changeset
261 hsp.findtext("Hsp_query-from"), #qstart,
2bd0cbccb3c6 Uploaded
galaxyp
parents:
diff changeset
262 hsp.findtext("Hsp_query-to"), #qend,
2bd0cbccb3c6 Uploaded
galaxyp
parents:
diff changeset
263 hsp.findtext("Hsp_hit-from"), #sstart,
2bd0cbccb3c6 Uploaded
galaxyp
parents:
diff changeset
264 hsp.findtext("Hsp_hit-to"), #send,
2bd0cbccb3c6 Uploaded
galaxyp
parents:
diff changeset
265 evalue, #hsp.findtext("Hsp_evalue") in scientific notation
2bd0cbccb3c6 Uploaded
galaxyp
parents:
diff changeset
266 bitscore, #hsp.findtext("Hsp_bit-score") rounded
2bd0cbccb3c6 Uploaded
galaxyp
parents:
diff changeset
267 ]
2bd0cbccb3c6 Uploaded
galaxyp
parents:
diff changeset
268
2bd0cbccb3c6 Uploaded
galaxyp
parents:
diff changeset
269 if extended:
2bd0cbccb3c6 Uploaded
galaxyp
parents:
diff changeset
270 sallseqid = ";".join(name.split(None,1)[0] for name in hit_def.split(">"))
2bd0cbccb3c6 Uploaded
galaxyp
parents:
diff changeset
271 salltitles = "<>".join(name.split(None,1)[1] for name in hit_def.split(" >"))
2bd0cbccb3c6 Uploaded
galaxyp
parents:
diff changeset
272 #print hit_def, "-->", sallseqid
2bd0cbccb3c6 Uploaded
galaxyp
parents:
diff changeset
273 positive = hsp.findtext("Hsp_positive")
2bd0cbccb3c6 Uploaded
galaxyp
parents:
diff changeset
274 ppos = "%0.2f" % (100*float(positive)/float(length))
2bd0cbccb3c6 Uploaded
galaxyp
parents:
diff changeset
275 qframe = hsp.findtext("Hsp_query-frame")
2bd0cbccb3c6 Uploaded
galaxyp
parents:
diff changeset
276 sframe = hsp.findtext("Hsp_hit-frame")
2bd0cbccb3c6 Uploaded
galaxyp
parents:
diff changeset
277 if blast_program == "blastp":
2bd0cbccb3c6 Uploaded
galaxyp
parents:
diff changeset
278 #Probably a bug in BLASTP that they use 0 or 1 depending on format
2bd0cbccb3c6 Uploaded
galaxyp
parents:
diff changeset
279 if qframe == "0": qframe = "1"
2bd0cbccb3c6 Uploaded
galaxyp
parents:
diff changeset
280 if sframe == "0": sframe = "1"
2bd0cbccb3c6 Uploaded
galaxyp
parents:
diff changeset
281 slen = int(hit.findtext("Hit_len"))
2bd0cbccb3c6 Uploaded
galaxyp
parents:
diff changeset
282 values.extend([sallseqid,
2bd0cbccb3c6 Uploaded
galaxyp
parents:
diff changeset
283 hsp.findtext("Hsp_score"), #score,
2bd0cbccb3c6 Uploaded
galaxyp
parents:
diff changeset
284 nident,
2bd0cbccb3c6 Uploaded
galaxyp
parents:
diff changeset
285 positive,
2bd0cbccb3c6 Uploaded
galaxyp
parents:
diff changeset
286 hsp.findtext("Hsp_gaps"), #gaps,
2bd0cbccb3c6 Uploaded
galaxyp
parents:
diff changeset
287 ppos,
2bd0cbccb3c6 Uploaded
galaxyp
parents:
diff changeset
288 qframe,
2bd0cbccb3c6 Uploaded
galaxyp
parents:
diff changeset
289 sframe,
2bd0cbccb3c6 Uploaded
galaxyp
parents:
diff changeset
290 #NOTE - for blastp, XML shows original seq, tabular uses XXX masking
2bd0cbccb3c6 Uploaded
galaxyp
parents:
diff changeset
291 q_seq,
2bd0cbccb3c6 Uploaded
galaxyp
parents:
diff changeset
292 h_seq,
2bd0cbccb3c6 Uploaded
galaxyp
parents:
diff changeset
293 str(qlen),
2bd0cbccb3c6 Uploaded
galaxyp
parents:
diff changeset
294 str(slen),
2bd0cbccb3c6 Uploaded
galaxyp
parents:
diff changeset
295 salltitles,
2bd0cbccb3c6 Uploaded
galaxyp
parents:
diff changeset
296 ])
2bd0cbccb3c6 Uploaded
galaxyp
parents:
diff changeset
297 if out_fmt == 'cols':
2bd0cbccb3c6 Uploaded
galaxyp
parents:
diff changeset
298 if columns and len(columns) > 0:
2bd0cbccb3c6 Uploaded
galaxyp
parents:
diff changeset
299 v = []
2bd0cbccb3c6 Uploaded
galaxyp
parents:
diff changeset
300 for name in columns:
2bd0cbccb3c6 Uploaded
galaxyp
parents:
diff changeset
301 v.append(values[colnames.index(name)])
2bd0cbccb3c6 Uploaded
galaxyp
parents:
diff changeset
302 values = v
2bd0cbccb3c6 Uploaded
galaxyp
parents:
diff changeset
303 #print "\t".join(values)
2bd0cbccb3c6 Uploaded
galaxyp
parents:
diff changeset
304 outfile.write("\t".join(values) + "\n")
2bd0cbccb3c6 Uploaded
galaxyp
parents:
diff changeset
305 # prevents ElementTree from growing large datastructure
2bd0cbccb3c6 Uploaded
galaxyp
parents:
diff changeset
306 root.clear()
2bd0cbccb3c6 Uploaded
galaxyp
parents:
diff changeset
307 elem.clear()
2bd0cbccb3c6 Uploaded
galaxyp
parents:
diff changeset
308
2bd0cbccb3c6 Uploaded
galaxyp
parents:
diff changeset
309
2bd0cbccb3c6 Uploaded
galaxyp
parents:
diff changeset
310 for in_file in args:
2bd0cbccb3c6 Uploaded
galaxyp
parents:
diff changeset
311 # get an iterable
2bd0cbccb3c6 Uploaded
galaxyp
parents:
diff changeset
312 try:
2bd0cbccb3c6 Uploaded
galaxyp
parents:
diff changeset
313 context = ElementTree.iterparse(in_file, events=("start", "end"))
2bd0cbccb3c6 Uploaded
galaxyp
parents:
diff changeset
314 except:
2bd0cbccb3c6 Uploaded
galaxyp
parents:
diff changeset
315 stop_err("Invalid data format.")
2bd0cbccb3c6 Uploaded
galaxyp
parents:
diff changeset
316 # turn it into an iterator
2bd0cbccb3c6 Uploaded
galaxyp
parents:
diff changeset
317 context = iter(context)
2bd0cbccb3c6 Uploaded
galaxyp
parents:
diff changeset
318 # get the root element
2bd0cbccb3c6 Uploaded
galaxyp
parents:
diff changeset
319 try:
2bd0cbccb3c6 Uploaded
galaxyp
parents:
diff changeset
320 event, root = context.next()
2bd0cbccb3c6 Uploaded
galaxyp
parents:
diff changeset
321 except:
2bd0cbccb3c6 Uploaded
galaxyp
parents:
diff changeset
322 stop_err( "Invalid data format." )
2bd0cbccb3c6 Uploaded
galaxyp
parents:
diff changeset
323 for event, elem in context:
2bd0cbccb3c6 Uploaded
galaxyp
parents:
diff changeset
324 handle_event(event, elem)
2bd0cbccb3c6 Uploaded
galaxyp
parents:
diff changeset
325
2bd0cbccb3c6 Uploaded
galaxyp
parents:
diff changeset
326 if unhitfile:
2bd0cbccb3c6 Uploaded
galaxyp
parents:
diff changeset
327 unhitfile.close()
2bd0cbccb3c6 Uploaded
galaxyp
parents:
diff changeset
328 if options.output:
2bd0cbccb3c6 Uploaded
galaxyp
parents:
diff changeset
329 outfile.close()