comparison blast2html.py @ 75:4d2c25baf5a3 py2.6

Fix rounding errors
author Jan Kanis <jan.code@jankanis.nl>
date Wed, 18 Jun 2014 17:50:32 +0200
parents 03e044b5bcc2
children 7d0d46168fd5
comparison
equal deleted inserted replaced
74:03e044b5bcc2 75:4d2c25baf5a3
1 #!/usr/bin/env python3 1 #!/usr/bin/env python3
2 # -*- coding: utf-8 -*- 2 # -*- coding: utf-8 -*-
3 3
4 # Actually this program works with both python 2 and 3 4 # Actually this program works with both python 2 and 3, tested against python 2.6
5 5
6 # Copyright The Hyve B.V. 2014 6 # Copyright The Hyve B.V. 2014
7 # License: GPL version 3 or (at your option) any higher version 7 # License: GPL version 3 or (at your option) any higher version
8 8
9 from __future__ import unicode_literals, division 9 from __future__ import unicode_literals, division
10 10
11 import sys 11 import sys
12 import math 12 import math
13 import warnings 13 import warnings
14 import six, codecs 14 import six, codecs
15 from six.moves import builtins
15 from os import path 16 from os import path
16 from itertools import repeat 17 from itertools import repeat
17 import argparse 18 import argparse
18 from lxml import objectify 19 from lxml import objectify
19 import jinja2 20 import jinja2
20 21
21 22
22 23
23 _filters = dict() 24 _filters = dict(int='int', float='float')
24 def filter(func_or_name): 25 def filter(func_or_name):
25 "Decorator to register a function as filter in the current jinja environment" 26 "Decorator to register a function as filter in the current jinja environment"
26 if isinstance(func_or_name, six.string_types): 27 if isinstance(func_or_name, six.string_types):
27 def inner(func): 28 def inner(func):
28 _filters[func_or_name] = func.__name__ 29 _filters[func_or_name] = func.__name__
239 def _addfilters(self, environment): 240 def _addfilters(self, environment):
240 for filtername, funcname in _filters.items(): 241 for filtername, funcname in _filters.items():
241 try: 242 try:
242 environment.filters[filtername] = getattr(self, funcname) 243 environment.filters[filtername] = getattr(self, funcname)
243 except AttributeError: 244 except AttributeError:
244 environment.filters[filtername] = globals()[funcname] 245 try:
246 environment.filters[filtername] = globals()[funcname]
247 except KeyError:
248 environment.filters[filtername] = getattr(builtins, funcname)
245 249
246 def render(self, output): 250 def render(self, output):
247 template = self.environment.get_template(self.templatename) 251 template = self.environment.get_template(self.templatename)
248 252
249 params = (('Query ID', self.blast["BlastOutput_query-ID"]), 253 params = (('Query ID', self.blast["BlastOutput_query-ID"]),
254 ) 258 )
255 259
256 result = template.render(blast=self.blast, 260 result = template.render(blast=self.blast,
257 iterations=self.blast.BlastOutput_iterations.Iteration, 261 iterations=self.blast.BlastOutput_iterations.Iteration,
258 colors=self.colors, 262 colors=self.colors,
259 # match_colors=self.match_colors(),
260 # hit_info=self.hit_info(),
261 genelink=genelink, 263 genelink=genelink,
262 params=params) 264 params=params)
263 if six.PY2: 265 if six.PY2:
264 result = result.encode('utf-8') 266 result = result.encode('utf-8')
265 output.write(result) 267 output.write(result)
325 327
326 def hsp_val(path): 328 def hsp_val(path):
327 return (float(hsp[path]) for hsp in hsps) 329 return (float(hsp[path]) for hsp in hsps)
328 330
329 yield dict(hit = hit, 331 yield dict(hit = hit,
330 title = firsttitle(hit), 332 title = firsttitle(hit),
331 maxscore = "{0:.1f}".format(max(hsp_val('Hsp_bit-score'))), 333 maxscore = "{0:.1f}".format(max(hsp_val('Hsp_bit-score'))),
332 totalscore = "{0:.1f}".format(sum(hsp_val('Hsp_bit-score'))), 334 totalscore = "{0:.1f}".format(sum(hsp_val('Hsp_bit-score'))),
333 cover = "{0:.0%}".format(cover_count / query_length), 335 cover = "{0:.0%}".format(cover_count / query_length),
334 e_value = "{0:.4g}".format(min(hsp_val('Hsp_evalue'))), 336 e_value = "{0:.4g}".format(min(hsp_val('Hsp_evalue'))),
335 # FIXME: is this the correct formula vv? 337 # FIXME: is this the correct formula vv?
336 ident = "{0:.0%}".format(float(min(hsp.Hsp_identity / blastxml_len(hsp) for hsp in hsps))), 338 # float(...) because non-rounding division doesn't work with lxml elements in python 2.6
339 ident = "{0:.0%}".format(float(min(float(hsp.Hsp_identity) / blastxml_len(hsp) for hsp in hsps))),
337 accession = hit.Hit_accession) 340 accession = hit.Hit_accession)
338 341
339 342
340 def main(): 343 def main():
341 default_template = path.join(path.dirname(__file__), 'blast2html.html.jinja') 344 default_template = path.join(path.dirname(__file__), 'blast2html.html.jinja')