Mercurial > repos > jankanis > blast2html
changeset 53:4217bb9cf1d3
depend on python 3; fix internal links with multiple iterations
author | Jan Kanis <jan.code@jankanis.nl> |
---|---|
date | Mon, 26 May 2014 13:07:13 +0200 |
parents | d6c7b5de2833 |
children | 6d96d48a10f8 |
files | blast2html.html.jinja blast2html.py blast2html.xml tool_dependencies.xml |
diffstat | 4 files changed, 63 insertions(+), 72 deletions(-) [+] |
line wrap: on
line diff
--- a/blast2html.html.jinja Wed May 21 18:39:51 2014 +0200 +++ b/blast2html.html.jinja Mon May 26 13:07:13 2014 +0200 @@ -126,7 +126,7 @@ max-width: 50em; text-align: left; height: 2.8em; - overflow-y: hidden; + overflow: hidden; } div.legend { @@ -400,7 +400,7 @@ <h1>Queries</h1> {% for result in blast.BlastOutput_iterations.Iteration %} - <div class=indexentry><a href="#match{{result['Iteration_iter-num']}}"> + <div class=indexentry><a href="#match{{result|nodeid}}"> {% set hits = result|hits %} {{result['Iteration_query-ID']}}: {{result['Iteration_query-def']}} ({{result|len}} letters, {{hits|length}} hits) @@ -412,7 +412,7 @@ {% for result in blast.BlastOutput_iterations.Iteration %} - <section class=match id=match{{result['Iteration_iter-num']}}> + <section class=match id=match{{result|nodeid}}> <h1>Nucleotide Sequence ({{result|len}} letters)</h1> @@ -444,7 +444,7 @@ <div class=grey> <h3 class=centered>Distribution of {{result|length}} Blast Hits on the Query Sequence</h3> - <div class=defline id=defline{{result['Iteration_iter-num']}}> + <div class=defline id=defline{{result|nodeid}}> Mouse-over to show defline and scores, click to show alignments </div> @@ -482,9 +482,9 @@ {% for line in result|match_colors %} <a class=matchresult - href="{{line.link}}" - onmouseover='document.getElementById("defline{{result['Iteration_iter-num']}}").innerHTML="{{line.defline|js_string_escape}}"' - onmouseout='document.getElementById("defline{{result['Iteration_iter-num']}}").innerHTML="Mouse-over to show defline and scores, click to show alignments"' + href="#hit{{line.hit|nodeid}}" + onmouseover='document.getElementById("defline{{result|nodeid}}").innerHTML="{{line.defline|js_string_escape}}"' + onmouseout='document.getElementById("defline{{result|nodeid}}").innerHTML="Mouse-over to show defline and scores, click to show alignments"' title="{{line.defline}}"> <div class="matchrow graphicrow"> {% for hit in line.colors %} @@ -521,9 +521,9 @@ </tr> {% for hit in result|hit_info %} <tr> - <td><div><a href="#hit{{hit.link_id}}" + <td><div><a href="#hit{{hit.hit|nodeid}}" title="{{hit.title}}" - id="description{{hit.link_id}}"> + id="description{{hit.hit|nodeid}}"> {{hit.title}} </a></div></td> <td>{{hit.maxscore}}</td> @@ -546,10 +546,10 @@ <div class=grey><div class=white> {% for hit in hits %} - <div class=alignment id=hit{{hit.Hit_num}}> + <div class=alignment id=hit{{hit|nodeid}}> <div class=linkheader> - <div class=right><a href="#description{{hit.Hit_num}}">Descriptions</a></div> + <div class=right><a href="#description{{hit|nodeid}}">Descriptions</a></div> <a class=linkheader href="{{genelink(hit|hitid)}}">GenBank</a> <a class=linkheader href="{{genelink(hit|hitid, 'graph')}}">Graphics</a> </div> @@ -564,11 +564,11 @@ </div> {% if hit|othertitles|length %} - <a class=showmoretitles onclick="toggle_visibility('moretitles{{hit.Hit_num|js_string_escape}}'); return false;" href=''> + <a class=showmoretitles onclick="toggle_visibility('moretitles{{hit|nodeid|js_string_escape}}'); return false;" href=''> See {{hit|othertitles|length}} more title(s) </a> - <div class=moretitles id=moretitles{{hit.Hit_num}} style="display: none"> + <div class=moretitles id=moretitles{{hit|nodeid}} style="display: none"> {% for title in hit|othertitles %} <div class=title> <p class=hittitle>{{title.title}}</p> @@ -581,7 +581,7 @@ {% endif %} {% for hsp in hit.Hit_hsps.Hsp %} - <div class=hotspot> + <div class=hotspot id=hotspot{{hsp|nodeid}}> <p class=range> <span class=range>Range {{hsp.Hsp_num}}: {{hsp['Hsp_hit-from']}} to {{hsp['Hsp_hit-to']}}</span> <a class=range href="{{genelink(hit|hitid, 'genbank', hsp)}}">GenBank</a>
--- a/blast2html.py Wed May 21 18:39:51 2014 +0200 +++ b/blast2html.py Mon May 26 13:07:13 2014 +0200 @@ -1,7 +1,5 @@ #!/usr/bin/env python3 # -*- coding: utf-8 -*- -# -# Actually runs under either python 2 or 3 # Copyright The Hyve B.V. 2014 # License: GPL version 3 or higher @@ -13,7 +11,6 @@ import warnings from os import path from itertools import repeat -import six import argparse from lxml import objectify import jinja2 @@ -23,7 +20,7 @@ _filters = {} def filter(func_or_name): "Decorator to register a function as filter in the current jinja environment" - if isinstance(func_or_name, six.string_types): + if isinstance(func_or_name, str): def inner(func): _filters[func_or_name] = func.__name__ return func @@ -99,9 +96,25 @@ elif node.tag == 'Iteration': return int(node['Iteration_query-len']) raise Exception("Unknown XML node type: "+node.tag) - @filter +def nodeid(node): + id = [] + if node.tag == 'Hsp': + id.insert(0, node.Hsp_num.text) + node = node.getparent().getparent() + assert node.tag == 'Hit' + if node.tag == 'Hit': + id.insert(0, node.Hit_num.text) + node = node.getparent().getparent() + assert node.tag == 'Iteration' + if node.tag == 'Iteration': + id.insert(0, node['Iteration_iter-num'].text) + return '-'.join(id) + raise ValueError("The nodeid filter can only be applied to Hsp, Hit or Iteration nodes in a BlastXML document") + + +@filter def asframe(frame): if frame == 1: return 'Plus' @@ -174,7 +187,7 @@ self.templatename = templatename self.blast = objectify.parse(self.input).getroot() - self.loader = jinja2.FileSystemLoader(searchpath=templatedir, encoding='utf-8') + self.loader = jinja2.FileSystemLoader(searchpath=templatedir) self.environment = jinja2.Environment(loader=self.loader, lstrip_blocks=True, trim_blocks=True, autoescape=True) @@ -238,7 +251,7 @@ count = 1 matches.append((count * percent_multiplier, self.colors[last] if last != 255 else 'transparent')) - yield dict(colors=matches, link="#hit"+hit.Hit_num.text, defline=firsttitle(hit)) + yield dict(colors=matches, hit=hit, defline=firsttitle(hit)) @filter def queryscale(self, result): @@ -269,8 +282,7 @@ return (float(hsp[path]) for hsp in hsps) yield dict(hit = hit, - title = firsttitle(hit), - link_id = hit.Hit_num, + title = firsttitle(hit), maxscore = "{:.1f}".format(max(hsp_val('Hsp_bit-score'))), totalscore = "{:.1f}".format(sum(hsp_val('Hsp_bit-score'))), cover = "{:.0%}".format(cover_count / query_length), @@ -288,16 +300,16 @@ input_group = parser.add_mutually_exclusive_group(required=True) input_group.add_argument('positional_arg', metavar='INPUT', nargs='?', type=argparse.FileType(mode='r'), help='The input Blast XML file, same as -i/--input') - input_group.add_argument('-i', '--input', type=argparse.FileType(mode='r', encoding='utf-8'), + input_group.add_argument('-i', '--input', type=argparse.FileType(mode='r'), help='The input Blast XML file') - parser.add_argument('-o', '--output', type=argparse.FileType(mode='w', encoding='utf-8'), default=sys.stdout, + parser.add_argument('-o', '--output', type=argparse.FileType(mode='w'), default=sys.stdout, help='The output html file') # We just want the file name here, so jinja can open the file # itself. But it is easier to just use a FileType so argparse can # handle the errors. This introduces a small race condition when # jinja later tries to re-open the template file, but we don't # care too much. - parser.add_argument('--template', type=argparse.FileType(mode='r', encoding='utf-8'), default=default_template, + parser.add_argument('--template', type=argparse.FileType(mode='r'), default=default_template, help='The template file to use. Defaults to blast_html.html.jinja') args = parser.parse_args()
--- a/blast2html.xml Wed May 21 18:39:51 2014 +0200 +++ b/blast2html.xml Mon May 26 13:07:13 2014 +0200 @@ -1,13 +1,11 @@ -<tool id="blast2html" name="blast2html" version="0.0.7"> +<tool id="blast2html" name="blast2html" version="0.0.8"> <description>Convert BLAST XML to HTML</description> <requirements> <requirement type="package" version="v0.0.18">blast_datatypes</requirement> - <requirement name="package" version="1.3.0">python_six</requirement> - <requirement name="package" version="1.2.1">argparse</requirement> - <requirement name="package" version="2.2.3">lxml</requirement> - <requirement name="package" version="2.7.2">jinja2</requirement> + <requirement name="package" version="3.4.1">python3</requirement> + <requirement name="package" version="0.1">blast2html_venv</requirement> </requirements> <command interpreter="python">blast2html.py -i "${input}" -o "${output}"</command>
--- a/tool_dependencies.xml Wed May 21 18:39:51 2014 +0200 +++ b/tool_dependencies.xml Mon May 26 13:07:13 2014 +0200 @@ -15,29 +15,12 @@ toolshed="http://toolshed.g2.bx.psu.edu" changeset_revision="039b04adcfee" /> </package> - <package name="argparse" version="1.2.1"> - <install version="1.0"> - <actions> - <action type="setup_virtualenv"> - argparse == 1.2.1 - </action> - </actions> - </install> - <readme>The Python argparse library. This is included in the stdlib for python 2.7 and up, but not for 2.6</readme> + <package name="python3" version="3.4.1"> + <repository name="package_python3_4" owner="jankanis" prior_installation_required="True" + toolshed="http://toolshed.g2.bx.psu.edu" changeset_revision="9dbfc4fcef0a" /> </package> - - <package name="python_six" version="1.3.0"> - <install version="1.0"> - <actions> - <action type="setup_virtualenv"> - six >= 1.3.0 - </action> - </actions> - </install> - <readme>The Python six library for python 2/3 compatibility</readme> - </package> - - <package name="lxml" version="2.2.3"> + + <package name="blast2html_venv" version="0.1"> <install version="1.0"> <actions> <action type="set_environment_for_install"> @@ -53,29 +36,27 @@ toolshed="http://toolshed.g2.bx.psu.edu" changeset_revision="039b04adcfee"> <package name="libxslt" version="1.1.28" /> </repository> + <repository name="python3" owner="jankanis"> + <package name="python3" version="3.4.1" /> + </repository> </action> - <action type="shell_command"> - echo '*******************************************************************************' - echo $PATH - echo xslt-config at: `which -a xslt-config` - </action> - <action type="setup_virtualenv"> - lxml == 2.2.3 + + <action type="shell_command"> + # Unset any saved environment settings from parent virtual + # environments, e.g. for python 2 or if Galaxy itself is running + # from within a virtual environment. + unset _OLD_VIRTUAL_PATH; unset _OLD_VIRTUAL_PYTHONHOME + pyvenv blast2html_venv + . blast2html_venv/bin/activate + pip3 install lxml jinja2 + </action> + + <action type="set_environment"> + <environment_variable name="PYTHONPATH" action="prepend_to">$INSTALL_DIR/lib/python3.4/site-packages</environment_variable> </action> </actions> </install> - <readme>The Python lxml library</readme> - </package> - - <package name="jinja2" version="2.7.2"> - <install version="1.0"> - <actions> - <action type="setup_virtualenv"> - jinja2 == 2.7.2 - </action> - </actions> - </install> - <readme>The Jinja 2 template engine for Python</readme> + <readme>A Python 3 virtual environment that includes the python packages blast2html depends on, which are lxml and jinja2.</readme> </package> </tool_dependency>