annotate blast_reporting.py @ 0:7db7ecc78ad6 draft

Uploaded
author damion
date Mon, 02 Mar 2015 20:46:00 -0500
parents
children
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
0
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
1 #!/usr/bin/python
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
2 """Convert a BLAST XML file to 12 column tabular output
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
3
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
4 This tool can be used both via command line and via a local Galaxy install.
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
5 Galaxy uses .loc files as indicated by the tool_data_table_conf.xml.sample.
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
6 The command line version uses .tab versions of the above files:
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
7 blast_reporting_fields.loc
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
8 fasta_reference_dbs.loc
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
9 So for command-line use, ensure the .tab files are updated to their .loc counterparts.
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
10
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
11 Takes three command line options, input BLAST XML filename, output tabular
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
12 BLAST filename, output format (std for standard 12 columns, or ext for the
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
13 extended 24 columns offered in the BLAST+ wrappers).
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
14
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
15 The 12 columns output are 'qseqid sseqid pident length mismatch gapopen qstart
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
16 qend sstart send evalue bitscore' or 'std' at the BLAST+ command line, which
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
17 mean:
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
18
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
19 ====== ========= ============================================
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
20 Column NCBI name Description
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
21 ------ --------- --------------------------------------------
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
22 1 qseqid Query Seq-id (ID of your sequence)
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
23 2 sseqid Subject Seq-id (ID of the database hit)
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
24 3 pident Percentage of identical matches
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
25 4 length Alignment length
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
26 5 mismatch Number of mismatches
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
27 6 gapopen Number of gap openings
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
28 7 qstart Start of alignment in query
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
29 8 qend End of alignment in query
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
30 9 sstart Start of alignment in subject (database hit)
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
31 10 send End of alignment in subject (database hit)
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
32 11 evalue Expectation value (E-value)
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
33 12 bitscore Bit score
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
34 ====== ========= ============================================
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
35
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
36 The additional columns offered in the Galaxy BLAST+ wrappers are:
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
37
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
38 ====== ============= ===========================================
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
39 Column NCBI name Description
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
40 ------ ------------- -------------------------------------------
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
41 13 sallseqid All subject Seq-id(s), separated by a ';'
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
42 14 score Raw score
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
43 15 nident Number of identical matches
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
44 16 positive Number of positive-scoring matches
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
45 17 gaps Total number of gaps
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
46 18 ppos Percentage of positive-scoring matches
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
47 19 qframe Query frame
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
48 20 sframe Subject frame
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
49 21 qseq Aligned part of query sequence
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
50 22 sseq Aligned part of subject sequence
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
51 23 qlen Query sequence length
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
52 24 slen Subject sequence length
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
53 ====== ============= ===========================================
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
54
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
55 Very slight modifications were made to the "BLAST XML to tabular" tool that
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
56 ships with Galaxy to output two more column columns:
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
57
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
58 ====== ============= ===========================================
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
59 Column NCBI name Description
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
60 ------ ------------- -------------------------------------------
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
61 25 pcov Percentage coverage
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
62 26 sallseqdescr All subject Seq-descr(s), separated by a ','
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
63 ====== ============= ===========================================
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
64
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
65 Most of these fields are given explicitly in the XML file, others some like
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
66 the percentage identity and the number of gap openings must be calculated.
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
67
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
68 In addition an option exists to select particular columns for the output
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
69 report. Reference bin columns will be added if they have been included in
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
70 search.
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
71
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
72 A command line version can be used. Type blast_reporting.py -h for help.
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
73
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
74 Be aware that the sequence in the extended tabular output or XML direct from
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
75 BLAST+ may or may not use XXXX masking on regions of low complexity. This
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
76 can throw the off the calculation of percentage identity and gap openings.
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
77 [In fact, both BLAST 2.2.24+ and 2.2.25+ have a subtle bug in this regard,
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
78 with these numbers changing depending on whether or not the low complexity
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
79 filter is used.]
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
80
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
81 This script attempts to produce identical output to what BLAST+ would have done.
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
82 However, check this with "diff -b ..." since BLAST+ sometimes includes an extra
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
83 space character (probably a bug).
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
84
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
85 python blast_reporting.py in_file out_tabular_file out_html_file out_format
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
86 """
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
87 import sys
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
88 import re
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
89 import os.path
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
90 import common
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
91 import reference_bins
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
92 #import templates.html_report
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
93
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
94 if __name__ == '__main__' and __package__ is None:
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
95 from os import path
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
96 sys.path.append(path.dirname(path.dirname(path.abspath(__file__))))
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
97
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
98 if sys.version_info[:2] >= ( 2, 5 ):
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
99 import xml.etree.cElementTree as ElementTree
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
100 else:
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
101 from galaxy import eggs
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
102 import pkg_resources; pkg_resources.require( "elementtree" )
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
103 from elementtree import ElementTree
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
104
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
105 class GenericRecord(object): pass
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
106
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
107 class XMLRecordScan(object):
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
108 """
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
109 XML Input file usually looks like:
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
110
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
111 <BlastOutput>
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
112 <BlastOutput_program>blastn</BlastOutput_program>
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
113 <BlastOutput_param>
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
114 <Parameters>
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
115 <Parameters_expect>0.001</Parameters_expect>
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
116 <Parameters_sc-match>1</Parameters_sc-match>
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
117 <Parameters_sc-mismatch>-2</Parameters_sc-mismatch>
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
118 <Parameters_gap-open>0</Parameters_gap-open>
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
119 <Parameters_gap-extend>0</Parameters_gap-extend>
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
120 <Parameters_filter>L;m;</Parameters_filter>
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
121 </Parameters>
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
122 </BlastOutput_param>
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
123 <Iteration>
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
124 <Iteration_iter-num>1</Iteration_iter-num>
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
125 <Iteration_query-ID>Query_1</Iteration_query-ID>
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
126 <Iteration_query-def>ENA|EF604038|EF604038.1 Uncultured bacterium clone 16saw43-2g09.q1k 16S ribosomal RNA gene, partial sequence</Iteration_query-def>
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
127 <Iteration_query-len>1364</Iteration_query-len>
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
128 <Iteration_hits>
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
129
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
130 <Hit>
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
131 <Hit_num>1</Hit_num>
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
132 <Hit_id>gi|444439670|ref|NR_074985.1|</Hit_id>
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
133 <Hit_hsps>...
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
134 <Hsp>...
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
135 """
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
136 def __init__(self, options, output_format):
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
137 """ Creates a record object that holds field data for each <hit> iteration in Blastn XML data
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
138
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
139 .record object: holds values read in from <XML> <hit> record mainly.
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
140 .tags dictionary: XML tags and the record.[x] fields/attributes that should be set to tag values.
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
141 .column_format dictionary: Name to field count dictionary used for selecting # of output fields
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
142 .fieldSpec dictionary: Specification of each possible field's type (for validation), full name, and suitability for sorting, filtering, etc.
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
143 .custom_columns array takes list of custom columns to output. (If sorting by a column it must be in this list)
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
144 .reference_bins dictionary
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
145
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
146 """
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
147 self.record = GenericRecord() # Set up so we can use object attributes.
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
148
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
149 #This is a list of all incomming blast generated XML fields that we want to capture
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
150 # self.record gets all underscored variables values as well as new derived ones in process() below
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
151 self.tags = {
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
152 "BlastOutput_program": '_blast_program',
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
153 "Iteration_query-ID": '_qseqid',
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
154 "Iteration_query-def": '_qdef',
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
155 "Iteration_query-len": '_qlen', #extended+ calc
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
156
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
157 "Hit_id": '_hit_id',
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
158 "Hit_def": '_hit_def', #extended+ calc
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
159 "Hit_accession": '_hit_acc',
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
160 "Hit_len": '_hit_len',
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
161
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
162 "Hsp_bit-score": '_bitscore', #basic
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
163 "Hsp_score": '_score', #extended
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
164 "Hsp_evalue": '_evalue', #basic
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
165 "Hsp_query-from": '_qstart', #basic, extended+ calc
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
166 "Hsp_query-to": '_qend', #basic, extended+ calc
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
167 "Hsp_hit-from": '_sstart', #basic
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
168 "Hsp_hit-to": '_send', #basic
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
169 "Hsp_query-frame": '_qframe', #extended only
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
170 "Hsp_hit-frame": '_sframe', #extended only
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
171 "Hsp_identity": '_nident', #extended
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
172 "Hsp_positive": '_positive', #extended
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
173 "Hsp_gaps": '_gaps', #extended
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
174 "Hsp_align-len": '_length', #basic
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
175 "Hsp_qseq": '_qseq', #extended
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
176 "Hsp_hseq": '_sseq', #extended
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
177 "Hsp_midline": '_mseq' #basic
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
178 }
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
179
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
180 self.column_format = {
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
181 'std':12,
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
182 'ext':24,
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
183 'std+seqs':12,
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
184 'ext+':26,
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
185 'custom':1
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
186 }
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
187
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
188 if not output_format in self.column_format:
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
189 common.stop_err("Format argument should be std (12 column) or ext (extended 24 columns) or ext+ (extended 26+ columns) or custom (you choose fields). Format argument x22 has been replaced with ext (extended 24 columns)")
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
190
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
191 # Array of columns destined for tab-delimited output - This defines default ORDER of fields too.
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
192 # Raw data fields that never get output: _bitscore, _evalue, _qframe, _sframe,
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
193 # and this that has no m_frame equivalent: _mseq
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
194 self.columns_in = 'qseqid sseqid pident _length mismatch gapopen _qstart _qend _sstart _send evalue bitscore \
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
195 sallseqid _score _nident _positive _gaps ppos qframe sframe _qseq _sseq qlen slen \
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
196 pcov sallseqdescr accessionid sseqdescr _mseq'.split()
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
197
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
198 fieldSpecFile = os.path.join(os.path.dirname(__file__), 'blast_reporting_fields.tab')
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
199 self.field_spec = common.FieldSpec(fieldSpecFile, self.columns_in)
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
200
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
201 # Include first N fields from .columns according to format.
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
202 # In all cases qseqid is included.
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
203 # Default everything to "column".
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
204 columns_out = self.columns_in[0:self.column_format[output_format]]
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
205
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
206 # This column list is designed for creating phylogeny reports.
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
207 if output_format == 'std+seqs': columns_out.extend(['_qseq','_sseq'])
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
208
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
209 self.columns = self.field_spec.initColumns(columns_out, options.custom_fields)
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
210
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
211 # We're making these columns hidden for this particular HTML report format
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
212 # UNLESS they are mentioned in options.custom_fields
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
213 if output_format == 'std+seqs':
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
214 for (ptr, target) in enumerate(self.columns):
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
215 if target['field'] in ['_qseq','_sseq'] and options.custom_fields and not target['field'] in options.custom_fields :
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
216 target['group'] = 'hidden'
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
217
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
218 # ADD SELECTED BINS TO COLUMN LIST;
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
219 self.binManager = reference_bins.ReferenceBins()
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
220 self.binManager.build_bins(options.reference_bins, self.columns)
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
221
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
222 def setRecordAttr(self, tag, text):
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
223 #self.record is a class object (not a dictionary) so using setattr()
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
224 setattr(self.record, self.tags[tag], text)
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
225
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
226 # Called after set() has processed a bunch of <hit> ...</hit> tags
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
227 def processRecord(self) :
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
228
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
229 bline = self.record
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
230
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
231 # NCBI notes: Expecting either this,
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
232 # <Hit_id>gi|3024260|sp|P56514.1|OPSD_BUFBU</Hit_id>
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
233 # <Hit_def>RecName: Full=Rhodopsin</Hit_def>
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
234 # <Hit_accession>P56514</Hit_accession>
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
235 #or,
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
236 # <Hit_id>Subject_1</Hit_id>
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
237 # <Hit_def>gi|57163783|ref|NP_001009242.1| rhodopsin [Felis catus]</Hit_def>
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
238 # <Hit_accession>Subject_1</Hit_accession>
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
239 #or,
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
240 # <Hit_id>Subject_1</Hit_id>
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
241 # <Hit_def>gi|57163783|ref|NP_001009242.1| rhodopsin [Felis catus]</Hit_def>
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
242 # <Hit_accession>Subject_1</Hit_accession>
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
243 #apparently depending on the parse_deflines switch
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
244
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
245 sseqid = self.record._hit_id.split(None,1)[0]
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
246
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
247 # If Hit_id == Hit_accession AND it is a default "Subject_1" ...
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
248 # OR Hit_accession IN Hit_id and BL_ORD_ID|XXXX contains hit_accession
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
249 if common.re_default_subject_id.match(sseqid) and sseqid.find(bline._hit_acc):
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
250 # and sseqid == bline._hit_acc:
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
251 #Place holder ID, take the first word of the subject definition
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
252 hit_def = bline._hit_def
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
253 sseqid = hit_def.split(None,1)[0]
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
254 else:
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
255 hit_def = sseqid + " " + bline._hit_def
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
256
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
257 self.record.sseqid = sseqid
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
258
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
259 if common.re_default_ncbi_id.match(sseqid):
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
260 self.record.accessionid = sseqid.split('|')[3]
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
261 elif common.re_default_ref_id.match(sseqid):
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
262 self.record.accessionid = sseqid.split('|')[1]
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
263 else:
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
264 # Have to use the whole string.
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
265 self.record.accessionid = sseqid
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
266
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
267
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
268 # NCBI notes: Expecting either this, from BLAST 2.2.25+ using FASTA vs FASTA
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
269 # <Iteration_query-ID>sp|Q9BS26|ERP44_HUMAN</Iteration_query-ID>
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
270 # <Iteration_query-def>Endoplasmic reticulum resident protein 44 OS=Homo sapiens GN=ERP44 PE=1 SV=1</Iteration_query-def>
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
271 # <Iteration_query-len>406</Iteration_query-len>
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
272 # <Iteration_hits></Iteration_hits>
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
273 #
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
274 #Or, from BLAST 2.2.24+ run online
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
275 # <Iteration_query-ID>Query_1</Iteration_query-ID>
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
276 # <Iteration_query-def>Sample</Iteration_query-def>
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
277 # <Iteration_query-len>516</Iteration_query-len>
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
278 # <Iteration_hits>...
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
279
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
280 # Note BioPython's approach http://biopython.org/DIST/docs/api/Bio.SearchIO.BlastIO.blast_xml-pysrc.html
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
281 # ... if hit_id.startswith('gnl|BL_ORD_ID|'): ...
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
282
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
283 if common.re_default_query_id.match(bline._qseqid):
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
284 #Place holder ID, take the first word of the query definition
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
285 qseqid = bline._qdef.split(None,1)[0]
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
286 else:
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
287 qseqid = bline._qseqid
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
288
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
289 self.record.qseqid = qseqid
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
290
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
291 self.record.evalue = "0.0" if bline._evalue == "0" else "%0.0e" % float(bline._evalue)
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
292
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
293 # NCBI notes:
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
294 # if bline._bitscore < 100:
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
295 # #Seems to show one decimal place for lower scores
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
296 # bitscore = "%0.1f" % bline._bitscore
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
297 # else:
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
298 # #Note BLAST does not round to nearest int, it truncates
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
299 # bitscore = "%i" % bline._bitscore
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
300 bitscore = float(bline._bitscore)
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
301 self.record.bitscore = "%0.1f" % bitscore if bitscore < 100 else "%i" % bitscore
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
302
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
303 self.record.pident = "%0.2f" % (100*float(bline._nident)/float(bline._length))
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
304
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
305 self.record.gapopen = str(len(bline._qseq.replace('-', ' ').split())-1 + \
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
306 len(bline._sseq.replace('-', ' ').split())-1)
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
307
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
308 mismatch = bline._mseq.count(' ') + bline._mseq.count('+') \
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
309 - bline._qseq.count('-') - bline._sseq.count('-')
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
310 #assert len(bline._qseq) == len(bline._sseq) == len(bline._mseq) == int(bline._length)
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
311 self.record.mismatch = str(mismatch)
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
312
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
313 # Extended fields
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
314 #sallseqid gets ";" delimited list of first words in each hit_def "x>y>z" expression.
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
315 #Nov 7 2013 fix: https://github.com/peterjc/galaxy_blast/blob/master/tools/ncbi_blast_plus/blastxml_to_tabular.py
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
316 hit_def_array = hit_def.split(" >") #Note: elem.text below converts escaped "&gt;" back to ">"
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
317 try:
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
318 self.record.sallseqid = ";".join(name.split(None,1)[0] for name in hit_def_array)
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
319 except IndexError as e:
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
320 common.stop_err("Problem splitting multiple hit ids?\n%r\n--> %s" % (hit_def, e))
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
321
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
322 # Calculate accession ids, and check bin(s) for them, update record accordingly.
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
323 self.binManager.setStatus(self.record)
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
324
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
325 self.record.ppos = "%0.2f" % (100*float(bline._positive)/float(bline._length))
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
326 qframe = bline._qframe
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
327 sframe = bline._sframe
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
328 if bline._blast_program == "blastp":
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
329 #Probably a bug in BLASTP that they use 0 or 1 depending on format
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
330 if qframe == "0": qframe = "1"
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
331 if sframe == "0": sframe = "1"
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
332
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
333 self.record.qframe = qframe
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
334 self.record.sframe = sframe
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
335 self.record.slen = str(int(bline._hit_len))
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
336 self.record.qlen = str(int(bline._qlen))
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
337
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
338 #extended+
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
339 self.record.pcov = "%0.2f" % (float(int(bline._qend) - int(bline._qstart) + 1)/int(bline._qlen) * 100)
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
340 sallseqdescr = []
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
341 try:
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
342 for name in hit_def_array:
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
343 id_desc = name.split(None,1)
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
344 if len(id_desc) == 1: sallseqdescr.append('missing description - database issue')
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
345 else: sallseqdescr.append(id_desc[1])
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
346 except IndexError as e:
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
347 common.stop_err("Problem splitting multiple hits?\n%r\n--> %s" % (hit_def, e))
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
348 # Example sallseqdescr is "Mus musculus ribosomal protein S8 (Rps8), mRNA ;Mus musculus ES cells cDNA, RIKEN full-length enriched library, clone:2410041L12 product:ribosomal protein S8, full insert sequence"
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
349
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
350 self.record.sallseqdescr = ";".join(sallseqdescr)
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
351 self.record.sseqdescr = sallseqdescr[0]
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
352
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
353 return True # One may return false anywhere above to filter out current <Hsp> record.
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
354
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
355
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
356 # Tab-delimited order is important, so we can't just cycle through (unordered) self.record attributes.
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
357 #
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
358 # @uses .record object with field attributes
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
359 # @uses .prelim_columns (used before final column selection)
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
360 def outputTabDelimited(self):
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
361 values = []
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
362
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
363 for col in self.columns:
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
364 values.append(getattr(self.record, col['field']))
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
365
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
366 return '\t'.join(values) + '\n'
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
367
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
368
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
369
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
370 class ReportEngine(object):
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
371
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
372 def __init__(self): pass
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
373
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
374 def __main__(self):
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
375
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
376
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
377 ## *************************** Parse Command Line *****************************
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
378 parser = common.MyParser(
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
379 description = 'Generates tab-delimited table report based on BLAST XML results.',
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
380 usage = 'python blast_reporting.py [blastxml_input_file] [out_format] [tabular_output_file] [option: html_output_file] [option: selection_output_file:id_1:id_2:id_3] [options]',
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
381 epilog="""Details:
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
382
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
383 This tool can be used both via command line and via a local Galaxy install.
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
384 Galaxy uses .loc files (blast_reporting_fields.loc, fasta_reference_dbs.loc)
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
385 as indicated by the tool's tool_data_table_conf.xml.sample. The command line script
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
386 uses .tab versions (located in the script's folder) which need to reflect any changes
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
387 made in the .loc versions.
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
388
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
389 Note: the selection file option is used mainly by the galaxy blast reporting tool.
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
390
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
391 [out_format] is one of:
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
392 "std" : standard 12 column
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
393 "std+seqs" : standard 12 column plus search and matched sequences
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
394 "ext" : extended 24 column
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
395 "ext+": 26+ column
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
396 "custom": Use only given field selections.
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
397
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
398 Use -i to see possible field (column) selections as defined by blast_reporting_fields.tab.
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
399
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
400 REFERENCE_BINS: Selected bins have their columns shown in output table for clarity, even when custom fields are selected, unless selecting the bin "exclude" option.
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
401
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
402 FILTERS:
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
403 Format: ([field_name]:[comparator] [value];)*
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
404 e.g. "pident: gt 97; sallseqdescr: excludes bovine|clone|environmental|swine|uncultivated|uncultured|unidentified"
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
405 [comparator] =
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
406 == numeric equal
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
407 != numeric not equal
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
408 gt numeric greater than
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
409 gte numeric greater than or equal to
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
410 lt numeric less than
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
411 lte numeric less than or equal to
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
412 includes (search text fields for included words/phrases)
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
413 excludes (same as above but exclude result if text found)
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
414
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
415 Textual comparisons may have a value consisting of phrases to search for separated by "|" (disjunction).
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
416
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
417
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
418 """)
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
419
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
420 parser.set_defaults(row_limit=0)
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
421 # Don't use "-h" , it is reserved for --help!
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
422
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
423 parser.add_option('-b', '--bins', type='string', dest='reference_bins',
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
424 help='Provide a comma-delimited list of reference databases to check, along with their sort order, and a flag to exclude them if desired, e.g. "16Sncbi desc,euzby desc,16Srdp exclude". See -i option for a list of available databases.')
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
425
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
426 parser.add_option('-c', '--columns', type='string', dest='custom_fields',
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
427 help='To modify sorting and formatting, specify a comma-delimited list of field specifications of the form: "[field_name]:[column|table|section]:[asc|desc|none]:[new label text];..." .')
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
428
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
429 parser.add_option('-f', '--filter', type='string', dest='filters',
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
430 help='Provide a semicolon-delimited list of fields and their criteria to filter by.')
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
431
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
432 parser.add_option('-i', '--info', dest='info', default=False, action='store_true',
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
433 help='Provides list of columns and their descriptions, for use in filter, sort and custom column lists. Shows a list of available sequence type reference bins as well')
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
434
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
435 parser.add_option('-l', '--label', type='string', dest='column_labels',
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
436 help='Include field labels in first row of tab-delimited result table as short names or data field names (or none)')
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
437
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
438 parser.add_option('-n', '--number', type='int', dest='row_limit',
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
439 help='Provide a limit to the number of rows of returned data. The default 0=unlimited.')
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
440
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
441 #TESTING
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
442 parser.add_option('-B', '--refbins', type='string', dest='refbins',
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
443 help='Testing library_data form input.')
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
444
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
445 parser.add_option('-r', '--redundant', dest='drop_redundant_hits', default=False, action='store_true',
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
446 help='Return only first match to a gene bank id result.')
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
447
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
448 parser.add_option('-t', '--tests', dest='test_ids', help='Enter "all" or comma-separated id(s) of tests to run.')
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
449
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
450 options, args = parser.parse_args()
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
451
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
452 if options.test_ids:
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
453
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
454 # Future: read this spec from test-data folder itself?
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
455 tests = {
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
456 '1a': {'input':'blast_reporting_1.blastxml std','outputs':'blast_reporting_1a.tabular','options':''},
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
457 '1a1':{'input':'blast_reporting_1.blastxml std','outputs':'blast_reporting_1a1.tabular blast_reporting_1a1.html','options':'-r'},
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
458 '1b': {'input':'blast_reporting_1.blastxml std','outputs':'blast_reporting_1b.tabular','options':'-r -f "pident:gte 97"'},
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
459 '1c': {'input':'blast_reporting_1.blastxml std','outputs':'blast_reporting_1c.tabular','options':'-r -f "pident:gte 97" -c "pident:column:asc" -l label'},
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
460 '1d': {
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
461 'input':'blast_reporting_1.blastxml ext+',
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
462 'outputs':'blast_reporting_1d.tabular blast_reporting_1d.html blast_reporting_1d1.tabular',
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
463 'options':'-r -f "pident:gte 99" -l label -n 5'
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
464 }
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
465 }
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
466 common.testSuite(options.test_ids, tests, '/tmp/')
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
467
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
468 import time
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
469 time_start = time.time()
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
470
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
471 # "info" command provides a dump of all the fields that can be displayed from the Blast search.
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
472 if options.info:
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
473 # CAN WE LOCATE THIS FILE AS GALAXY SEES IT??????
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
474 print 'FIELDS:\n'
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
475 field_spec_path = os.path.join(os.path.dirname(__file__), 'blast_reporting_fields.tab')
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
476 fields = common.FieldSpec(field_spec_path)
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
477 for field in sorted(fields.dict.keys()):
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
478 print field + "\t" + fields.getAttribute(field,'type') + "\t" + fields.getAttribute(field,'name')
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
479
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
480 print '\nREFERENCE BINS:\n'
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
481 field_spec_path = os.path.join(os.path.dirname(__file__), 'fasta_reference_dbs.tab')
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
482 fields = common.FieldSpec(field_spec_path)
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
483 for field in sorted(fields.dict.keys()):
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
484 print field + "\t" + fields.getAttribute(field, 'path') + field + '/accession_ids.tab' + '\t' + fields.getAttribute(field, 'name')
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
485
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
486 sys.exit(1)
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
487
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
488 try:
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
489 in_file, output_format, out_tabular_file = args[0:3]
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
490
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
491 except:
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
492 common.stop_err("Expecting 3 arguments: input BLAST XML file, out format (std | std+seqs | ext | ext+ | custom), and output tabular file")
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
493
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
494 try:
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
495 # Get an iterable, see http://effbot.org/zone/element-iterparse.htm
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
496 context = ElementTree.iterparse(in_file, events=("start","end")) # By default only does end events.
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
497 context = iter(context)
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
498 event, root = context.next() # Creates reference to root element on 'start' event, for housecleaning below.
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
499 except:
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
500 common.stop_err("Invalid data format. !!")
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
501
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
502 tagGroup = XMLRecordScan(options, output_format)
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
503 fieldFilter = common.FieldFilter(tagGroup, options) # .filter list field names are changed above.
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
504
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
505 if options.reference_bins: print 'Database bins: %s' % str([bin.name for (ptr, bin) in enumerate(tagGroup.binManager.reference_bins) ]).translate(None, "[']")
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
506 if options.custom_fields: print 'Customized Fields: %s' % options.custom_fields
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
507 if options.filters: print 'Filters: ' + options.filters
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
508 if options.drop_redundant_hits: print 'Throwing out redundant hits...'
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
509
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
510 # ************************ FILE OUTPUT *****************************
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
511 # IT IS CRITICAL THAT EVERY <HIT>/<HSP> RETURN A COMPLETE XML SET OF TAGS OTHERWISE PREV. RECORD VALUES PERSIST
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
512 # NOTE: GALAXY 2012 has bug in html data display - it will show duplicate records OCCASIONALLY (at least on some browsers). You have to download data file to verify there are no duplicates
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
513
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
514 row_count = 0
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
515 row_count_filtered = 0
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
516 outfile = open(out_tabular_file, 'w')
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
517 query_stats = []
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
518
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
519 for event, elem in context:
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
520
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
521 # Alternative is to wipe Hit/Hsp fields on event == "start".
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
522 tag = elem.tag
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
523 if event == 'end':
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
524 if tag in tagGroup.tags : #Content of these tags fills a tabular line with column info.
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
525 tagGroup.setRecordAttr(tag, elem.text)
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
526 if tag == 'Iteration_query-def':
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
527 row_count = 0
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
528 row_count_filtered = 0
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
529 query_stats.append({'id':elem.text, 'rows' : 0, 'filtered_rows' : 0})
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
530
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
531 # Process each </hsp> record
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
532 elif tag == 'Hsp':
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
533 row_count += 1
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
534 query_stats[-1]['rows'] = row_count # real rows, not clipped
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
535 if options.row_limit == 0 or row_count_filtered < options.row_limit:
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
536
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
537 # Transform <Hsp> record & add field info.
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
538 if tagGroup.processRecord():
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
539
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
540 #if tagGroup.processFilters():
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
541 if fieldFilter.process(tagGroup.record):
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
542 row_count_filtered +=1
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
543 query_stats[-1]['filtered_rows'] = row_count_filtered
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
544 outfile.write(tagGroup.outputTabDelimited())
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
545
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
546 root.clear() # Clears references from root to (now unused) children to keep iterated datastructure small ???
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
547
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
548 elem.clear() # I think root.clear() cover this case.
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
549
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
550 root.clear()
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
551 outfile.close()
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
552
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
553
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
554 # Use fast Linux "sort" after filtering & file write
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
555 common.fileSort(out_tabular_file, tagGroup.columns)
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
556
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
557 """
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
558 The "Selection file" option is meant for galaxy UI use in conjunction
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
559 with the "Select Subsets on data" tool. If a selection_file is called
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
560 for, then we need to extract its id as well. For that we have to test
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
561 for somewhat odd expression from xml-generated command line, the
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
562 [$selection_file:$selection_file.hid:$selection_file.dataset_id:$selection_file.id]
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
563 Selection list doesn't necessarily need the HTML selectable report template,
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
564 but that template was designed to feed the galaxy "Select subsets" tool with its data.
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
565 """
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
566
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
567 if len(args) > 4 and args[4] != 'None:None:None:None':
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
568 selection_file_data = args[4]
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
569
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
570 #print ('selection file data:' + selection_file_data)
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
571 sel_file_fields = selection_file_data.split(':')
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
572 selection_file = sel_file_fields[0]
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
573 # From galaxy, incoming format is $selection_file:$selection_file.hid:$selection_file.dataset_id:$selection_file.id
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
574 # From command line, user won't have specified any of this, so ignore.
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
575 if len(sel_file_fields) > 3:
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
576 options.dataset_selection_id = sel_file_fields[3]
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
577
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
578 else:
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
579 options.dataset_selection_id = 0
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
580
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
581 common.fileSelections(out_tabular_file, selection_file, tagGroup, options)
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
582
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
583
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
584 """
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
585 We must have a template in order to write anything to above html output file.
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
586 All report templates need to be listed in the module's tabular data "blast_reporting_templates" folder.
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
587 # There are two possible HTML Report template locations:
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
588 # 1) The stock reports included in the module in the "templates/" subfolder, e.g. html_report.py
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
589 # 2) User customized templates. To set this up:
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
590 - add a custom template folder in a location of your choice.
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
591 - Copy this module's templates folder into it.
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
592 - The new folder must be in python's sys.path, which is achieved by adding a .pth file to python's site-packages folder.. E.g. set up /usr/lib/python2.6/site-packages/galaxy-custom-modules.pth to contain "/usr/local/galaxy/shared/python2.6_galaxy_custom_modules"
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
593 , and place 'templates_custom/html_report.py' in there.
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
594 """
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
595 if len(args) > 3:
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
596 out_html_file = args[3] #Galaxy-generated
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
597 # args[5] = html_template, default from galaxy xml is 'templates.html_report', but testing can receive 'None' value
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
598 if len(args) > 5 and len(args[5].strip()) > 0 and not args[5].strip() == 'None':
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
599
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
600 html_template = args[5] #User-selected
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
601 if not html_template.translate(None, "._-" ).isalnum():
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
602 common.stop_err("The HTML Report template name is not correct. It should be a python class path like templates.html_report)! : " + html_template)
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
603
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
604 else:
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
605 html_template = 'templates.html_report'
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
606
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
607 try:
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
608 # See http://stackoverflow.com/questions/769534/dynamic-loading-of-python-modules
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
609 HTMLReportModule = __import__(html_template, fromlist=['does not in fact matter what goes here!'])
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
610 # Now create final tabular, html (or future: xml) data
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
611 htmlManager = HTMLReportModule.HTMLReport(tagGroup, options, query_stats)
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
612 # htmlManager might not be initialized if the caller couldn't provide all the data the particular template needed.
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
613 htmlManager.render(out_tabular_file, out_html_file)
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
614
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
615 except ImportError:
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
616 common.stop_err("Unable to locate HTML Report template! : " + html_template)
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
617
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
618
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
619 common.fileTabular(out_tabular_file, tagGroup, options)
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
620
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
621 print('Execution time (seconds): ' + str(int(time.time()-time_start)))
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
622
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
623
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
624 if __name__ == '__main__':
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
625 # Command line access
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
626 reportEngine = ReportEngine()
7db7ecc78ad6 Uploaded
damion
parents:
diff changeset
627 reportEngine.__main__()