changeset 7:1df2bfce5c24 draft

first features are working, partial match table
author Jan Kanis <jan.code@jankanis.nl>
date Wed, 07 May 2014 18:49:54 +0200
parents 34211f5b83fd
children d20ce91e1297
files visualise.html.jinja visualise.py
diffstat 2 files changed, 235 insertions(+), 0 deletions(-) [+]
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/visualise.html.jinja	Wed May 07 18:49:54 2014 +0200
@@ -0,0 +1,149 @@
+<!DOCTYPE html>
+<html>
+  <head>
+    <meta charset="UTF-8">
+    
+    <title>Blast output</title>
+
+    <style>
+      body {
+      color: #33333;
+      font-family: Verdana,Arial,Sans-Serif;
+      }
+
+      
+      #content {
+      margin: 0 2em;
+      padding: 0.5em;
+      border: 1px solid #888888;
+      background-color: #d3dff5;
+      }
+
+      h1, h2, h3, h4, h5, h6 {
+      color: #2A6979;
+      font-family: arial,verdana,sans-serif;
+      letter-spacing: -1px;
+      margin: 1.2em 0 0.3em;
+      }
+
+      h1 {
+      border-bottom: 1px solid #CCCCCC;
+      font-size: 150%;
+      padding-bottom: 0.1em;
+      }
+
+      h2 {
+      font-size: 120%;
+      font-weight: bold;
+      }
+
+      h4.graphicHeader {
+      color: black;
+      letter-spacing: 0;
+      font-style: bold;
+      }
+
+      .headerdata {
+      font-size: 90%;
+      }
+      .headerdata .param {
+      font-weight: bold;
+      text-align: right;
+      padding: 0 1em;
+      }
+
+      .graphicInfo {
+      background-color: #eeeeee;
+      border: 1px solid #cccccc;
+      padding: 1em;
+      text-align: center;
+      }
+
+      .graphic {
+      background-color: white;
+      border: 2px solid black;
+      padding: .5em;
+      align: center;
+      margin: auto;
+      }
+
+      .centered {
+      align: center;
+      margin-left: auto;
+      margin-right: auto;
+      }
+
+      table.legend {
+      color: white;
+      font-weight: bold;
+      align: center;
+      margin: 0 auto;
+      width: 40em;
+      border-spacing: 0;
+      }
+      table.legend td {
+      width: 20%;
+      padding: 0;
+      margin: 0;
+      border: none;
+      }
+
+      table.matchresult {
+      height: 5px;
+      width: 40em;
+      align: center;
+      margin: 5px auto;
+      }
+    </style>
+
+  </head>
+
+  <body>
+    <div id=content>
+      <h1>Nucleotide Sequence ({{blast["BlastOutput_query-len"]}} letters)</h1>
+
+      <div id=header>
+
+	<table class=headerdata>
+	  {% for param, value in params %}
+   	    <tr><td class=param>{{param}}</td><td>{{value}}</td></tr>
+	  {% endfor %}
+	</table>
+	  
+      </div>
+
+      <div id=graphics>
+	<h2>Graphic Summary</h2>
+
+	<div class=graphicInfo>
+	  <h3 class=centered>Distribution of {{hits|length}} Blast Hits on the Query Sequence</h3>
+	  <div class=graphic>
+	    <h4 class=graphicHeader>Color key for alignment scores</h4>
+	    <table class=legend><tr>
+		<td style="background-color: {{colors[0]}}">&lt;40</td>
+		<td style="background-color: {{colors[1]}}">40-50</td>
+		<td style="background-color: {{colors[2]}}">50-80</td>
+		<td style="background-color: {{colors[3]}}">80-200</td>
+		<td style="background-color: {{colors[4]}}">&gt;=200</td>
+	    </tr></table>
+
+	    {% for line in match_colors %}
+	    <table class=matchresult><tr>
+		{% for match in line.colors %}
+		<td width={{match[0]}} style="background-color: {{match[1]}}">&nbsp</td>
+		{% endfor %}
+	    </tr></table>
+	    {% endfor %}
+	    
+	    <p>hoi</p>
+
+	  </div>
+	</div>
+
+
+      </div>
+
+    </div>
+  </body>
+</html>
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/visualise.py	Wed May 07 18:49:54 2014 +0200
@@ -0,0 +1,86 @@
+#!/usr/bin/env python3
+
+# Copyright The Hyve B.V. 2014
+# License: GPL version 3 or higher
+
+import sys
+import warnings
+from itertools import repeat
+from lxml import objectify
+import jinja2
+
+
+def color_idx(length):
+    if length < 40:
+        return 0
+    elif length < 50:
+        return 1
+    elif length < 80:
+        return 2
+    elif length < 200:
+        return 3
+    return 4
+
+
+colors = ['black', 'blue', 'green', 'magenta', 'red']
+
+blast = objectify.parse('blast xml example1.xml').getroot()
+loader = jinja2.FileSystemLoader(searchpath='.')
+environment = jinja2.Environment(loader=loader)
+environment.filters['color'] = lambda length: match_colors[color_idx(length)]
+
+def match_colors():
+    """
+    An iterator that yields lists of length-color pairs. 
+    """
+    
+    hits = blast.BlastOutput_iterations.Iteration.Iteration_hits.Hit
+    query_length = blast["BlastOutput_query-len"]
+    # sort hits by longest hotspot first
+    hits = sorted(hits, key=lambda h: max(hsp['Hsp_align-len'] for hsp in h.Hit_hsps.Hsp), reverse=True)
+
+    for hit in hits:
+        # sort hotspots from short to long, so we can overwrite index colors of
+        # short matches with those of long ones.
+        hotspots = sorted(hit.Hit_hsps.Hsp, key=lambda hsp: hsp['Hsp_align-len'])
+        table = bytearray([255]) * query_length
+        for hsp in hotspots:
+            frm = hsp['Hsp_query-from'] - 1
+            to = hsp['Hsp_query-to'] - 1
+            table[frm:to] = repeat(color_idx(hsp['Hsp_align-len']), to - frm)
+
+        matches = []
+        last = table[0]
+        count = 0
+        for i in range(int(query_length)):
+            if table[i] == last:
+                count += 1
+                continue
+            matches.append((count, colors[last] if last != 255 else 'none'))
+            last = table[i]
+            count = 1
+        matches.append((count, colors[last] if last != 255 else 'none'))
+
+        yield dict(colors=matches, link="#hit"+hit.Hit_num.text)
+
+
+def main():
+    template = environment.get_template('visualise.html.jinja')
+
+    params = (('Query ID', blast["BlastOutput_query-ID"]),
+              ('Query definition', blast["BlastOutput_query-def"]),
+              ('Query length', blast["BlastOutput_query-len"]),
+              ('Program', blast.BlastOutput_version),
+              ('Database', blast.BlastOutput_db),
+            )
+
+    if len(blast.BlastOutput_iterations.Iteration) > 1:
+        warnings.warn("Multiple 'Iteration' elements found, showing only the first")
+
+    sys.stdout.write(template.render(blast=blast,
+                                     hits=blast.BlastOutput_iterations.Iteration.Iteration_hits.Hit,
+                                     colors=colors,
+                                     match_colors=match_colors(),
+                                     params=params))
+
+main()