diff tools/mytools/dreme_out/dreme.html @ 0:9071e359b9a3

Uploaded
author xuebing
date Fri, 09 Mar 2012 19:37:19 -0500
parents
children
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tools/mytools/dreme_out/dreme.html	Fri Mar 09 19:37:19 2012 -0500
@@ -0,0 +1,3045 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<title>DREME</title>
+<style type="text/css">
+    
+    /* START INCLUDED FILE "meme.css" */
+        /* The following is the content of meme.css */
+        body { background-color:white; font-size: 12px; font-family: Verdana, Arial, Helvetica, sans-serif;}
+
+        div.help {
+          display: inline-block;
+          margin: 0px;
+          padding: 0px;
+          width: 12px;
+          height: 13px;
+          cursor: pointer;
+          background-image: url("help.gif");
+          background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAwAAAANAQMAAACn5x0BAAAAAXNSR0IArs4c6QAAAAZQTFRFAAAAnp6eqp814gAAAAF0Uk5TAEDm2GYAAAABYktHRACIBR1IAAAACXBIWXMAAAsTAAALEwEAmpwYAAAAB3RJTUUH2gMJBQgGYqhNZQAAACZJREFUCNdj+P+BoUGAoV+AYeYEEGoWYGgTYGgRAAm2gRGQ8f8DAOnhC2lYnqs6AAAAAElFTkSuQmCC");
+        }
+
+        div.help2 {
+          color: #999;
+          display: inline-block;
+          width: 12px;
+          height: 12px;
+          border: 1px solid #999;
+          font-size: 13px;
+          line-height:12px;
+          font-family: Helvetica, sans-serif;
+          font-weight: bold;
+          font-style: normal;
+          cursor: pointer;
+        }
+        div.help2:hover {
+          color: #000;
+          border-color: #000;
+        }
+        
+        p.spaced { line-height: 1.8em;}
+        
+        span.citation { font-family: "Book Antiqua", "Palatino Linotype", serif; color: #004a4d;}
+
+        p.pad { padding-left: 30px; padding-top: 5px; padding-bottom: 10px;}
+
+        td.jump { font-size: 13px; color: #ffffff; background-color: #00666a;
+          font-family: Georgia, "Times New Roman", Times, serif;}
+
+        a.jump { margin: 15px 0 0; font-style: normal; font-variant: small-caps;
+          font-weight: bolder; font-family: Georgia, "Times New Roman", Times, serif;}
+
+        h2.mainh {font-size: 1.5em; font-style: normal; margin: 15px 0 0;
+          font-variant: small-caps; font-family: Georgia, "Times New Roman", Times, serif;}
+
+        h2.line {border-bottom: 1px solid #CCCCCC; font-size: 1.5em; font-style: normal;
+          margin: 15px 0 0; padding-bottom: 3px; font-variant: small-caps;
+          font-family: Georgia, "Times New Roman", Times, serif;}
+
+        h4 {border-bottom: 1px solid #CCCCCC; font-size: 1.2em; font-style: normal;
+          margin: 10px 0 0; padding-bottom: 3px; font-family: Georgia, "Times New Roman", Times, serif;}
+
+        h5 {margin: 0px}
+
+        a.help { font-size: 9px; font-style: normal; text-transform: uppercase;
+          font-family: Georgia, "Times New Roman", Times, serif;}
+
+        div.pad { padding-left: 30px; padding-top: 5px; padding-bottom: 10px;}
+        
+        div.pad1 { margin: 10px 5px;}
+
+        div.pad2 { margin: 25px 5px 5px;}
+        h2.pad2 { padding: 25px 5px 5px;}
+
+        div.pad3 { padding: 5px 0px 10px 30px;}
+
+        div.box { border: 2px solid #CCCCCC; padding:10px;}
+
+        div.bar { border-left: 7px solid #00666a; padding:5px; margin-top:25px; }
+
+        div.subsection {margin:25px 0px;}
+
+        img {border:0px none;}
+
+        th.majorth {text-align:left;}
+        th.minorth {font-weight:normal; text-align:left; width:8em; padding: 3px 0px;}
+        th.actionth {font-weight:normal; text-align:left;}
+
+        .strand_name {text-align:left;}
+        .strand_side {padding:0px 10px;}
+        .strand_start {padding:0px 10px;}
+        .strand_pvalue {text-align:center; padding:0px 10px;}
+        .strand_lflank {text-align:right; padding-right:5px; font-weight:bold; font-size:large; font-family: 'Courier New', Courier, monospace; color:gray;}
+        .strand_seq {text-align:center; font-weight:bold; font-size:large; font-family: 'Courier New', Courier, monospace;}
+        .strand_rflank {text-align:left; padding-left:5px; font-weight:bold; font-size:large; font-family: 'Courier New', Courier, monospace; color:gray;}
+
+        .block_td {height:25px;}
+        .block_container {position:relative; width:99%; height:25px; padding:0px; margin:0px;}
+        .block_motif {position:absolute; z-index:3; height:12px; top:0px; text-align:center; vertical-align:middle; background-color:cyan;}
+        .block_rule {position:absolute; z-index:2; width:100%; height:1px; top:12px; left:0px; background-color:gray;}
+        .block_plus_sym {position:absolute; z-index:4; width:12px; height:12px; top:0px; left:0px; color:gray;}
+        .block_minus_sym {position:absolute; z-index:4; width:12px; height:12px; top:13px; left:0px; color:gray;}
+
+        .tic_major {position:absolute; border-left:2px solid blue; height:0.5em; top:0em;}
+        .tic_minor {position:absolute; border-left:1px solid blue; height:0.2em; top:0em;}
+        .tic_label {position:absolute; top:0.5em;  height: 1em; text-align:center; vertical-align:middle}
+
+        .explain h5 {font-size:1em; margin-left: 1em;}
+
+        div.doc {margin-left: 2em; margin-bottom: 3em;}
+        
+        div.tabArea {
+          font-size: 80%;
+          font-weight: bold;
+        }
+
+        a.tab {
+          background-color: #ddddff;
+          border: 1px solid #000000;
+          padding: 2px 1em 2px 1em;
+          text-decoration: none;
+        }
+        div.tabArea.base a.tab {
+          border-top-width: 0px;
+        }
+        div.tabArea.top a.tab {
+          border-bottom-width: 0px;
+        }
+
+        a.tab, a.tab:visited {
+          color: #808080;
+        }
+
+        a.tab:hover {
+          background-color: #d0d0d0;
+          color: #606060;
+        }
+        a.tab.activeTab, a.tab.activeTab:hover, a.tab.activeTab:visited {
+          background-color: #f0f0f0;
+          color: #000000;
+        }
+        div.tabMain {
+          border: 1px solid #000000;
+          background-color: #ffffff;
+          padding: 5px;
+          margin-right: 5px;
+        }
+        th.trainingset {
+          border-bottom: thin dashed black; 
+          font-weight:normal; 
+          padding:0px 10px;
+        }
+        .dnaseq {
+          font-weight: bold; 
+          font-size: large; 
+          font-family: 'Courier New', Courier, monospace;
+        }
+        .dna_A {
+          color: rgb(204,0,0);
+        }
+        .dna_C {
+          color: rgb(0,0,204);
+        }
+        .dna_G {
+          color: rgb(255,179,0);
+        }
+        .dna_T {
+          color: rgb(0,128,0);
+        }
+    /* END INCLUDED FILE "meme.css" */
+    
+  
+    
+    /* START INCLUDED FILE "dreme-to-html.css" */
+      table.dreme_motifs tr th, table.dreme_motifs tr td {
+        padding: 0px 10px;
+      }
+
+      div.popup_wrapper {
+        position:fixed; 
+        z-index:2;
+        width:100%; 
+        height:0; 
+        top:50%; 
+        left:0;
+      }
+
+      div.popup {
+        width: 400px; 
+        z-index:2;
+        margin-left: auto;
+        margin-right: auto;
+        padding: 5px;
+        background: #FFF;
+        border-style: double;
+        border-width: 5px;
+        border-color: #00666a;
+        position:relative; 
+      }
+
+      div.grey_background {
+        position:fixed; 
+        z-index: 1;
+        background-color: #000;
+        -ms-filter: "progid:DXImageTransform.Microsoft.Alpha(Opacity=50)";
+        filter: alpha(opacity=50);
+        opacity: 0.5;
+        left: 0;
+        top: 0;
+        width: 100%;
+        height: 100%;
+
+      }
+      td.symaction {
+        text-align: center;
+      }
+      *.symaction {
+        font-size: 20px;
+      }
+
+      div.close {
+        cursor: pointer;
+        border: 1px solid black; 
+        width:15px; 
+        height:15px; 
+        line-height:15px; /* this causes vertical centering */
+        text-align:center; 
+        background-color:#FFF; 
+        color:#000; 
+        font-size:15px;
+        font-family:monospace;
+      }
+
+      div.close:hover {
+        color:#FFF;
+        background-color:#000; 
+      }
+
+      div.navnum {
+        width:100%; 
+        height:20px; 
+        line-height:20px; 
+        text-align:center; 
+        font-size:medium;
+      }
+
+      a.navarrow {
+        font-size: 30px;
+        text-decoration:none;
+      }
+
+      a.inactive {
+        color:#CCC;
+      }
+
+      div.actionbutton { 
+        cursor: pointer;
+        font-size: 18px;
+        line-height:20px; 
+        padding: 5px; 
+        margin: 10px 0; 
+        border: 1px solid black;
+      }
+
+      div.actionbutton:hover {
+        color:#FFF;
+        background-color:#000;
+      }
+
+      div.pop_content {
+        position:absolute;
+        z-index:1;
+        width:300px;
+        padding: 5px;
+        background: #E4ECEC;
+        font-size: 12px;
+        font-family: Arial;
+        border-style: double;
+        border-width: 3px;
+        border-color: #AA2244;
+        display:none;
+      }
+      span.sort_dir {
+        text-decoration: none;
+      }
+
+      div.section_title {
+        font-weight: bold;
+        cursor: pointer;
+      }
+
+      div.section_title.inactive {
+        color: #000;
+      }
+
+      div.section_title.inactive:hover {
+        color: #000;
+        text-decoration:underline;
+      }
+
+      div.section_title label {
+        cursor: pointer;
+      }
+
+      span.ellipsis {
+        display: inline-block;
+        border: 1px solid black;
+        padding: 0 2px;
+        margin: 0 2px;
+      }
+
+      div.section_title.inactive:hover span.ellipsis {
+        color: #FFF;
+        background-color: #000;
+      }
+
+      div.section_title.inactive span.toggle {
+        color: #000;
+      }
+
+      div.section_data {
+        margin-left: 20px;
+      }
+      tr.rule td, tr.rule th {
+        border-bottom: 1px solid #CCC;
+      }
+
+      h1.compact, h2.compact, h3.compact, h4.compact, h5.compact, h6.compact {
+        margin:0; 
+        padding:0;
+      }
+
+      ul.programs {
+        margin-top: 0;
+        padding-top: 0;
+        margin-bottom: 0;
+        padding-bottom: 0;
+        margin-left: 0;
+        padding-left: 0;
+        list-style: none;
+        border-bottom: 1px solid black;
+      }
+
+      ul.programs li {
+        border: 1px solid black;
+        border-bottom-width: 0;
+        background-color: #EFE;
+        cursor: default;
+      }
+
+      ul.programs li.active {
+        background-color: #CFC;
+      }
+
+      ul.programs li.selected {
+        background-color: #262;
+        color: #FFF;
+      }
+
+      div.programs_scroll {
+        width: 100%; 
+        height: 90px; 
+        overflow-y: auto; 
+        overflow-x: hidden;
+        margin: 0 auto; 
+      }
+    /* END INCLUDED FILE "dreme-to-html.css" */
+    
+  </style>
+<script type="text/javascript">
+      var pos_count = 3;
+      var neg_count = 3;
+      var motif_seqs = [];
+
+    
+    /* START INCLUDED FILE "delay_draw.js" */
+      //
+      // Functions to measure the position of page elements relative to the size of the page
+      //
+
+      // gets the offset of the top of the page due to scrolling
+      // from: http://www.howtocreate.co.uk/tutorials/javascript/browserwindow
+      function get_scroll_xy() {
+        var scrOfX = 0, scrOfY = 0;
+        if( typeof( window.pageYOffset ) == 'number' ) {
+          //Netscape compliant
+          scrOfY = window.pageYOffset;
+          scrOfX = window.pageXOffset;
+        } else if( document.body && ( document.body.scrollLeft || document.body.scrollTop ) ) {
+          //DOM compliant
+          scrOfY = document.body.scrollTop;
+          scrOfX = document.body.scrollLeft;
+        } else if( document.documentElement && ( document.documentElement.scrollLeft || document.documentElement.scrollTop ) ) {
+          //IE6 standards compliant mode
+          scrOfY = document.documentElement.scrollTop;
+          scrOfX = document.documentElement.scrollLeft;
+        }
+        return [ scrOfX, scrOfY ];
+      }
+
+      // gets the width and height of the visible page
+      // from: http://www.howtocreate.co.uk/tutorials/javascript/browserwindow
+      function get_page_size() {
+        var myWidth = 0, myHeight = 0;
+        if( typeof( window.innerWidth ) == 'number' ) {
+          //Non-IE
+          myWidth = window.innerWidth;
+          myHeight = window.innerHeight;
+        } else if( document.documentElement && ( document.documentElement.clientWidth || document.documentElement.clientHeight ) ) {
+          //IE 6+ in 'standards compliant mode'
+          myWidth = document.documentElement.clientWidth;
+          myHeight = document.documentElement.clientHeight;
+        } else if( document.body && ( document.body.clientWidth || document.body.clientHeight ) ) {
+          //IE 4 compatible
+          myWidth = document.body.clientWidth;
+          myHeight = document.body.clientHeight;
+        }
+        return [myWidth, myHeight];
+      }
+
+      // gets the x and y offset of an element
+      // from http://www.quirksmode.org/js/findpos.html
+      function get_elem_xy(elem) {
+        var myX = myY = 0;
+        if (elem.offsetParent) {
+          do {
+            myX += elem.offsetLeft;
+            myY += elem.offsetTop;
+          } while (elem = elem.offsetParent);
+        }
+        return [myX, myY];
+      }
+
+      //
+      // Functions to delay a drawing task until it is required or it would not lag the display to do so
+      //
+
+      // a list of items still to be drawn
+      var drawable_list = [];
+      // the delay between drawing objects that are not currently visible
+      var draw_delay = 1;
+      // the delay after a user interaction
+      var user_delay = 300;
+      // the delay after a user has stopped scrolling and is viewing the stuff drawn on the current page
+      var stop_delay = 2000;
+      // the timer handle; allows resetting of the timer after user interactions
+      var draw_timer = null;
+
+      //
+      // Drawable
+      //
+      // elem - a page element which defines the position on the page that drawing is to be done
+      // task - an object with the method run which takes care of painting the object
+      //
+      function Drawable(elem, task) {
+        this.elem = elem;
+        this.task = task;
+        this.is_visible = Drawable_is_visible;
+      }
+
+      //
+      // Drawable_is_visible
+      //
+      // Determines if the drawable object is in the visible part of the page.
+      //
+      // page_top - the distance to the top of the page for the visible region
+      // page_height - the height of the visible region
+      function Drawable_is_visible(page_top, page_height) {
+        var elem_top = get_elem_xy(this.elem)[1];
+        var elem_height = this.elem.height;
+        if (typeof (elem_height) != 'number') elem_height = 1;
+        return ((elem_top + elem_height) >= page_top && elem_top <= (page_top + page_height));
+      }
+
+      //
+      // draw_on_screen
+      //
+      // Checks each drawable object and draws those on screen.
+      //
+      function draw_on_screen() {
+        var found = false;
+        var page_top = get_scroll_xy()[1];
+        var page_height = get_page_size()[1];
+        for (var i = 0; i < drawable_list.length; i++) {
+          var drawable = drawable_list[i];
+          if (drawable.is_visible(page_top, page_height)) {
+            drawable.task.run();
+            drawable_list.splice(i--, 1);
+            found = true;
+          }
+        }
+        return found;
+      }
+
+      //
+      // process_draw_tasks
+      //
+      // Called on a delay to process the next avaliable
+      // draw task.
+      //
+      function process_draw_tasks() {
+        var delay = draw_delay;
+        draw_timer = null;
+        if (drawable_list.length == 0) return; //no more tasks
+        if (draw_on_screen()) {
+          delay = stop_delay; //give the user a chance to scroll
+        } else {
+          //get next task
+          var drawable = drawable_list.shift();
+          drawable.task.run();
+        }
+        //allow UI updates between tasks
+        draw_timer = window.setTimeout("process_draw_tasks()", draw_delay);
+      }
+
+      //
+      // delayed_process_draw_tasks
+      //
+      // Call process_draw_tasks after a short delay.
+      // The delay serves to group multiple redundant events.       
+      // Should be set as event handler for onscroll and onresize.
+      //
+      function delayed_process_draw_tasks() {
+        //reset the timer
+        if (drawable_list.length > 0) { 
+          if (draw_timer != null) clearTimeout(draw_timer);
+          draw_timer = window.setTimeout("process_draw_tasks()", user_delay);
+        }
+      }
+
+      //
+      // add_draw_task
+      //
+      // Add a drawing task to be called immediately if it is
+      // visible, or to be called on a delay to reduce stuttering
+      // effect on the web browser.
+      function add_draw_task(elem, task) {
+        var page_top = get_scroll_xy()[1];
+        var page_height = get_page_size()[1];
+        drawable = new Drawable(elem, task);
+        if (drawable.is_visible(page_top, page_height)) {
+          task.run();
+        } else {
+          drawable_list.push(drawable);
+          //reset timer
+          if (draw_timer != null) clearTimeout(draw_timer);
+          draw_timer = window.setTimeout("process_draw_tasks()", user_delay);
+        }
+      }
+
+    /* END INCLUDED FILE "delay_draw.js" */
+    
+  
+    
+    /* START INCLUDED FILE "motif_logo.js" */
+    //======================================================================
+    // start Alphabet object
+    //======================================================================
+    function Alphabet(alphabet, bg) {
+      //variable prototype
+      this.freqs = new Array();
+      this.alphabet = new Array();
+      this.letter_count = 0;
+      //method prototype
+      this.get_ic = Alphabet_get_ic;
+      this.get_size = Alphabet_get_size;
+      this.get_index = Alphabet_get_index;
+      this.get_letter = Alphabet_get_letter;
+      this.get_colour = Alphabet_get_colour;
+      this.get_bg_freq = Alphabet_get_bg_freq;
+      this.is_nucleotide = Alphabet_is_nucleotide;
+      this.is_ambig = Alphabet_is_ambig;
+      this.toString = Alphabet_to_string;
+      //construct
+      var is_letter = /^\w$/;
+      var is_prob = /^((1(\.0+)?)|(0(\.\d+)?))$/;
+      for (var pos = 0; pos < alphabet.length; pos++) {
+        var letter = alphabet.charAt(pos);
+        if (is_letter.test(letter)) {
+          this.alphabet[this.letter_count] = letter.toUpperCase();
+          this.freqs[this.letter_count] = -1;
+          this.letter_count++;
+        }
+      }
+      if (!(bg === undefined)) {
+        var parts = bg.split(/\s+/);
+        for (var i = 0, pos = 0; (i + 1) < parts.length; i += 2) {
+          var letter = parts[i];
+          var freq = parts[i+1];
+          if (is_letter.test(letter) && is_prob.test(freq)) {
+            letter = letter.toUpperCase();          //find the letter it matches
+            for (;pos < this.letter_count; pos++) {
+              if (this.alphabet[pos] == letter) break;
+            }
+            if (pos >= this.letter_count) throw "NOT_IN_ALPHABET";
+            this.freqs[pos] = (+freq);
+          }
+        }
+      } else {
+        //assume uniform background
+        var freq = 1.0 / this.letter_count;
+        for (var pos = 0; pos < this.letter_count; pos++) {
+          this.freqs[pos] = freq;
+        }
+      }
+    }
+
+
+    function Alphabet_get_ic() {
+      if (this.is_nucleotide()) {
+        return 2;
+      } else {
+        return Math.log(20) / Math.LN2;
+      }
+    }
+
+    function Alphabet_get_size() {
+      return this.letter_count;
+    }
+
+    function Alphabet_get_letter(alph_index) {
+      if (alph_index < 0 || alph_index >= this.letter_count) {
+        throw "BAD_ALPHABET_INDEX";
+      }
+      return this.alphabet[alph_index];
+    }
+
+    function Alphabet_get_bg_freq(alph_index) {
+      if (alph_index < 0 || alph_index >= this.letter_count) {
+        throw "BAD_ALPHABET_INDEX";
+      }
+      if (this.freqs[alph_index] == -1) throw "BG_FREQ_NOT_SET";
+      return this.freqs[alph_index];
+    }
+
+    function Alphabet_get_colour(alph_index) {
+      var red = "rgb(204,0,0)";
+      var blue = "rgb(0,0,204)";
+      var orange = "rgb(255,179,0)";
+      var green = "rgb(0,128,0)";
+      var yellow = "rgb(255,255,0)";
+      var purple = "rgb(204,0,204)";
+      var magenta = "rgb(255,0,255)";
+      var pink = "rgb(255,204,204)";
+      var turquoise = "rgb(51,230,204)";
+      if (alph_index < 0 || alph_index >= this.letter_count) {
+        throw "BAD_ALPHABET_INDEX";
+      }
+      if (this.is_nucleotide()) {
+        switch (this.alphabet[alph_index]) {
+          case "A":
+            return red;
+          case "C":
+            return blue;
+          case "G":
+            return orange;
+          case "T":
+            return green;
+        }
+      } else {
+        switch (this.alphabet[alph_index]) {
+          case "A":
+          case "C":
+          case "F":
+          case "I":
+          case "L":
+          case "V":
+          case "W":
+          case "M":
+            return blue;
+          case "N":
+          case "Q":
+          case "S":
+          case "T":
+            return green;
+          case "D":
+          case "E":
+            return magenta;
+          case "K":
+          case "R":
+            return red;
+          case "H":
+            return pink;
+          case "G":
+            return orange;
+          case "P":
+            return yellow;
+          case "Y":
+            return turquoise;
+        }
+      }
+      return "black";
+    }
+
+    function Alphabet_is_ambig(alph_index) {
+      if (alph_index < 0 || alph_index >= this.letter_count) {
+        throw "BAD_ALPHABET_INDEX";
+      }
+      if (this.is_nucleotide()) {
+        return ("ACGT".indexOf(this.alphabet[alph_index]) == -1);
+      } else {
+        return ("ACDEFGHIKLMNPQRSTVWY".indexOf(this.alphabet[alph_index]) == -1);
+      }
+    }
+
+    function Alphabet_get_index(letter) {
+      for (i = 0; i < this.letter_count; i++) {
+        if (this.alphabet[i] == letter.toUpperCase()) return i;
+      }
+      throw "UNKNOWN_LETTER";
+    }
+
+    function Alphabet_is_nucleotide() {
+      //TODO basic method, make better
+      if (this.letter_count < 20) return true;
+      return false;
+    }
+
+    function Alphabet_to_string() {
+      return (this.is_nucleotide() ? "Nucleotide" : "Protein") + " Alphabet " + (this.alphabet.join(""));
+    }
+
+    //======================================================================
+    // end Alphabet object
+    //======================================================================
+
+    //======================================================================
+    // start Symbol object
+    //======================================================================
+    function Symbol(alph_index, scale, alphabet) {
+      //variable prototype
+      this.symbol = alphabet.get_letter(alph_index);
+      this.scale = scale;
+      this.colour = alphabet.get_colour(alph_index);
+      //function prototype
+      this.get_symbol = Symbol_get_symbol;
+      this.get_scale = Symbol_get_scale;
+      this.get_colour = Symbol_get_colour;
+      this.toString = Symbol_to_string;
+    }
+
+    function Symbol_get_symbol() {
+      return this.symbol;
+    }
+
+    function Symbol_get_scale() {
+      return this.scale;
+    }
+
+    function Symbol_get_colour() {
+      return this.colour;
+    }
+
+    function Symbol_to_string() {
+      return this.symbol + " " + (Math.round(this.scale*1000)/10) + "%";
+    }
+
+    function compare_symbol(sym1, sym2) {
+      if (sym1.get_scale() < sym2.get_scale()) {
+        return -1;
+      } else if (sym1.get_scale() > sym2.get_scale()) {
+        return 1;
+      } else {
+        return 0;
+      }
+    }
+    //======================================================================
+    // end Symbol object
+    //======================================================================
+
+    //======================================================================
+    // start Pspm object
+    //======================================================================
+    function Pspm(pspm, name, ltrim, rtrim, nsites, evalue) {
+      if (ltrim === undefined) ltrim = 0;
+      if (rtrim === undefined) rtrim = 0;
+      if (nsites === undefined) nsites = 0;
+      if (evalue === undefined) evalue = 0;
+      //variable prototype
+      this.alph_length = 0;
+      this.motif_length = 0;
+      this.pspm = null;
+      this.name = (typeof name == "string" ? name : "");
+      this.nsites = nsites;
+      this.evalue = evalue;
+      this.ltrim = ltrim;
+      this.rtrim = rtrim;
+      //function prototype
+      this.copy = Pspm_copy;
+      this.reverse_complement = Pspm_reverse_complement;
+      this.get_stack = Pspm_get_stack;
+      this.get_stack_ic = Pspm_get_stack_ic;
+      this.get_motif_length = Pspm_get_motif_length;
+      this.get_alph_length = Pspm_get_alph_length;
+      this.get_left_trim = Pspm_get_left_trim;
+      this.get_right_trim = Pspm_get_right_trim;
+      this.as_pspm = Pspm_as_pspm;
+      this.as_pssm = Pspm_as_pssm;
+      this.toString = Pspm_to_string;
+      //construct
+      if (typeof pspm == "string") {
+        var pspm_header = /letter-probability matrix:\s+alength=\s+(\d+)\s+w=\s+(\d+)(\s+nsites=\s+(\S+))?(\s+E=\s+(\S+))?\s*/;
+        var lines = pspm.split(/\n/);
+        var read_pspm = false;
+        var line_num = 0;
+        var col_num = 0;
+        this.pspm = new Array();
+        for (line_index in lines) {
+          //exclude inherited properties and undefined properties
+          if (!lines.hasOwnProperty(line_index) || lines[line_index] === undefined) continue;
+
+          var line = trim(lines[line_index]);
+          if (line == '') {
+            continue;
+          }
+          if (!read_pspm) {
+            var header_match = pspm_header.exec(line);
+            if (header_match != null) {
+              read_pspm = true;
+              this.alph_length = (+header_match[1]);
+              this.motif_length = (+header_match[2]);
+              if (header_match[4]) this.nsites = parseFloat(header_match[4]);//not always an integer
+              if (header_match[6]) this.evalue = parseFloat(header_match[6]);
+              this.pspm = new Array(this.motif_length);
+            }
+            continue;
+          }
+          if (line_num >= this.motif_length) {
+            throw "TOO_MANY_ROWS";
+          }
+          this.pspm[line_num] = new Array(this.alph_length);
+          col_num = 0;
+          var parts = line.split(/\s+/);
+          for (part_index in parts) {
+            //exclude inherited properties and undefined properties
+            if (!parts.hasOwnProperty(part_index) || parts[part_index] === undefined) continue;
+            
+            var prob = parts[part_index];
+            if (col_num >= this.alph_length) {
+              throw "TOO_MANY_COLS";
+            }
+            this.pspm[line_num][col_num] = (+prob);
+            //check the probability is within bounds
+            if (this.pspm[line_num][col_num] > 1 || this.pspm[line_num][col_num] < 0) {
+              throw "NUM_NOT_PROB";
+            }
+            col_num++;
+          }
+          if (col_num != this.alph_length) {
+            throw "TOO_FEW_COLS";
+          }
+        line_num++;
+        }
+        if (line_num != this.motif_length) {
+          throw "TOO_FEW_ROWS";
+        }
+      } else { 
+        // assume pspm is a nested array
+        this.motif_length = pspm.length;
+        this.alpha_length = (pspm.length > 0 ? pspm[0].length : 0);
+        this.pspm = new Array(this.motif_length);
+        // copy pspm and check
+        for (var row = 0; row < this.motif_length; row++) {
+          if (this.alpha_length != pspm[row].length) throw "COLUMN_MISMATCH";
+          this.pspm[row] = new Array(this.alpha_length);
+          var row_sum = 0;
+          for (var col = 0; col < this.alpha_length; col++) {
+            row_sum += this.pspm[row][col];
+            this.pspm[row][col] = 0 + pspm[row][col];
+          }
+          var delta = 0.1
+          if ((row_sum > 1 && (row_sum - 1) > delta) || 
+              (row_sum < 1 && (1 - row_sum) > delta)) {
+            throw "INVALID_SUM";
+          }
+        }
+      }
+    }
+
+    function Clone() {}
+
+    function Pspm_copy() {
+      Clone.prototype = this;
+      var clone = new Clone();
+      //so far only a shallow copy, need to copy everything
+      clone.alph_length = (0+this.alph_length);
+      clone.motif_length = (0+this.motif_length);
+      clone.name = (""+this.name);
+      clone.nsites = (0+this.nsites);
+      clone.evalue = (0+this.evalue);
+      clone.ltrim = (0+this.ltrim);
+      clone.rtrim = (0+this.rtrim);
+      clone.pspm = new Array(this.motif_length);
+      for (row = 0; row < this.motif_length; row++) {
+        clone.pspm[row] = new Array(this.alph_length);
+        for (col = 0; col < this.alph_length; col++) {
+          clone.pspm[row][col] = (0+this.pspm[row][col]);
+        }
+      }
+      return clone;
+    }
+
+    function Pspm_reverse_complement(alphabet) {
+      if (this.alph_length != alphabet.get_size()) {
+        throw "ALPHABET_MISMATCH";
+      }
+      if (!alphabet.is_nucleotide()) {
+        throw "NO_PROTEIN_RC";
+      }
+      //reverse
+      var x = 0;
+      var y = this.motif_length-1;
+      while (x < y) {
+        var temp = this.pspm[x];
+        this.pspm[x] = this.pspm[y];
+        this.pspm[y] = temp;
+        x++;
+        y--;
+      }
+      //complement
+      var a_index = alphabet.get_index("A");
+      var c_index = alphabet.get_index("C");
+      var g_index = alphabet.get_index("G");
+      var t_index = alphabet.get_index("T");
+      for (i = 0; i < this.motif_length; i++) {
+        var row = this.pspm[i];
+        //swap A and T
+        var temp = row[a_index];
+        row[a_index] = row[t_index];
+        row[t_index] = temp;
+        //swap C and G
+        temp = row[c_index];
+        row[c_index] = row[g_index];
+        row[g_index] = temp;
+      }
+      //swap triming
+      var temp_trim = this.ltrim;
+      this.ltrim = this.rtrim;
+      this.rtrim = temp_trim;
+      //note that ambigs are ignored because they don't effect motifs
+      return this; //allow function chaining...
+    }
+
+    function Pspm_get_stack(position, alphabet) {
+      if (this.alph_length != alphabet.get_size()) {
+        throw "ALPHABET_MISMATCH";
+      }
+      var row = this.pspm[position];
+      var stack_ic = this.get_stack_ic(position, alphabet);
+      var alphabet_ic = alphabet.get_ic();
+      var stack = new Array();
+      for (i = 0; i < this.alph_length; i++) {
+        if (alphabet.is_ambig(i)) continue;
+        var sym = new Symbol(i, row[i]*stack_ic/alphabet_ic, alphabet);
+        if (sym.get_scale() <= 0) continue;
+        stack.push(sym);
+      }
+      stack.sort(compare_symbol);
+      return stack;
+    }
+
+    function Pspm_get_stack_ic(position, alphabet) {
+      if (this.alph_length != alphabet.get_size()) {
+        throw "ALPHABET_MISMATCH";
+      }
+      var row = this.pspm[position];
+      var H = 0;
+      for (var i = 0; i < this.alph_length; i++) {
+        if (alphabet.is_ambig(i)) continue;
+        if (row[i] == 0) continue;
+        H -= (row[i] * (Math.log(row[i]) / Math.LN2));
+      }
+      return alphabet.get_ic() - H;
+    }
+
+    function Pspm_get_error(alphabet) {
+      var asize;
+      if (this.nsites == 0) return 0;
+      if (alphabet.is_nucleotide()) {
+        asize = 4;
+      } else {
+        asize = 20;
+      }
+      return (asize-1) / (2 * Math.log(2)*this.nsites);
+    }
+
+    function Pspm_get_motif_length() {
+      return this.motif_length;
+    }
+
+    function Pspm_get_alph_length() {
+      return this.alph_length;
+    }
+
+    function Pspm_get_left_trim() {
+      return this.ltrim;
+    }
+
+    function Pspm_get_right_trim() {
+      return this.rtrim;
+    }
+
+    function Pspm_as_pspm() {
+      var out = "letter-probability matrix: alength= " + this.alph_length + 
+          " w= " + this.motif_length + " nsites= " + this.nsites + 
+          " E= " + this.evalue.toExponential() + "\n";
+      for (var row = 0; row < this.motif_length; row++) {
+        for (var col = 0; col < this.alph_length; col++) {
+          if (col != 0) out += " ";
+          out += this.pspm[row][col].toFixed(6);
+        }
+        out += "\n";
+      }
+      return out;
+    }
+
+    function Pspm_as_pssm(alphabet, pseudo) {
+      if (typeof pseudo != "number") pseudo = 0.1;
+      var out = "log-odds matrix: alength= " + this.alph_length + 
+          " w= " + this.motif_length + 
+          " E= " + this.evalue.toExponential() + "\n";
+      var log2 = Math.log(2);
+      var total = this.nsites + pseudo;
+      for (var row = 0; row < this.motif_length; row++) {
+        for (var col = 0; col < this.alph_length; col++) {
+          if (col != 0) out += " ";
+          var p = this.pspm[row][col];
+          // to avoid log of zero we add a pseudo count
+          var bg = alphabet.get_bg_freq(col);
+          var p2 = (p * this.nsites + bg * pseudo) / total;
+          // now calculate the score
+          var score = -10000;
+          if (p2 > 0) {
+            score = Math.round((Math.log(p2 / bg) / log2) * 100)
+          }
+          out += score;
+        }
+        out += "\n";
+      }
+      return out;
+    }
+
+    function Pspm_to_string() {
+      var str = "";
+      for (row_index in this.pspm) {
+        //exclude inherited properties and undefined properties
+        if (!this.pspm.hasOwnProperty(row_index) || this.pspm[row_index] === undefined) continue;
+        
+        var row = this.pspm[row_index];
+        str += row.join("\t") + "\n";
+      }
+      return str;
+    }
+    //======================================================================
+    // end Pspm object
+    //======================================================================
+    
+    //======================================================================
+    // start Logo object
+    //======================================================================
+    function Logo(alphabet, fine_text) {
+      this.alphabet = alphabet;
+      this.fine_text = fine_text;
+      this.pspm_list = [];
+      this.pspm_column = [];
+      this.rows = 0;
+      this.columns = 0;
+
+      //functions
+      this.add_pspm = Logo_add_pspm;
+      this.get_columns = Logo_get_columns;
+      this.get_rows = Logo_get_rows;
+      this.get_pspm = Logo_get_pspm;
+      this.get_offset = Logo_get_offset;
+    }
+
+    function Logo_add_pspm(pspm, column) {
+      if (column === undefined) column = 0;
+      else if (column < 0) throw "COLUMN_OUT_OF_BOUNDS";
+      this.pspm_list[this.rows] = pspm;
+      this.pspm_column[this.rows] = column;
+      this.rows++;
+      var col = column + pspm.get_motif_length();
+      if (col > this.columns) this.columns = col;
+    }
+
+    function Logo_get_columns() {
+      return this.columns;
+    }
+
+    function Logo_get_rows() {
+      return this.rows;
+    }
+
+    function Logo_get_pspm(row_index) {
+      if (row_index < 0 || row_index >= this.rows) throw "INDEX_OUT_OF_BOUNDS";
+      return this.pspm_list[row_index];
+    }
+
+    function Logo_get_offset(row_index) {
+      if (row_index < 0 || row_index >= this.rows) throw "INDEX_OUT_OF_BOUNDS";
+      return this.pspm_column[row_index];
+    }
+
+    //======================================================================
+    // end Logo object
+    //======================================================================
+
+    //======================================================================
+    // start RasterizedAlphabet
+    //======================================================================
+
+    // Rasterize Alphabet
+    // 1) Measure width of text at default font for all symbols in alphabet
+    // 2) sort in width ascending
+    // 3) Drop the top and bottom 10% (designed to ignore outliers like 'W' and 'I')
+    // 4) Calculate the average as the maximum scaling factor (designed to stop I becoming a rectangular blob).
+    // 5) Assume scale of zero would result in width of zero, interpolate scale required to make perfect width font
+    // 6) Draw text onto temp canvas at calculated scale
+    // 7) Find bounds of drawn text
+    // 8) Paint on to another canvas at the desired height (but only scaling width to fit if larger).
+    function RasterizedAlphabet(alphabet, font, target_width) {
+      //variable prototypes
+      this.lookup = []; //a map of letter to index
+      this.rasters = []; //a list of rasters
+      this.dimensions = []; //a list of dimensions
+
+      //function prototypes
+      this.draw = RasterizedAlphabet_draw;
+
+      //construct
+      var default_size = 60; // size of square to assume as the default width
+      var safety_pad = 20; // pixels to pad around so we don't miss the edges
+      // create a canvas to do our rasterizing on
+      var canvas = document.createElement("canvas");
+      // assume the default font would fit in a canvas of 100 by 100
+      canvas.width = default_size + 2 * safety_pad;
+      canvas.height = default_size + 2 * safety_pad;
+      // check for canvas support before attempting anything
+      if (!canvas.getContext) throw "NO_CANVAS_SUPPORT";
+      var ctx = canvas.getContext('2d');
+      // check for html5 text drawing support
+      if (!supports_text(ctx)) throw "NO_CANVAS_TEXT_SUPPORT";
+      // calculate the middle
+      var middle = Math.round(canvas.width / 2);
+      // calculate the baseline
+      var baseline = Math.round(canvas.height - safety_pad);
+      // list of widths
+      var widths = [];
+      var count = 0;
+      var letters = [];
+      //now measure each letter in the alphabet
+      for (var i = 0; i < alphabet.get_size(); ++i) {
+        if (alphabet.is_ambig(i)) continue; //skip ambigs as they're never rendered
+        var letter = alphabet.get_letter(i);
+        letters.push(letter);
+        var pos = count++;
+        this.lookup[letter] = pos;
+        //clear the canvas
+        canvas.width = canvas.width;
+        // get the context and prepare to draw our width test
+        var ctx = canvas.getContext('2d');
+        ctx.font = font;
+        ctx.fillStyle = alphabet.get_colour(i);
+        ctx.textAlign = "center";
+        ctx.translate(middle, baseline);
+        // draw the test text
+        ctx.fillText(letter, 0, 0);
+        //measure
+        var size = RasterizedAlphabet_measure(ctx, canvas.width, canvas.height);
+        if (size.width == 0) throw "INVISIBLE_LETTER"; //maybe the fill was white on white?
+        widths.push(size.width);
+        this.dimensions[pos] = size;
+      }
+      //sort the widths
+      widths.sort(function(a,b) {return a - b;});
+      //drop 10% of the items off each end
+      var tenpercent = Math.floor(widths.length / 10);
+      for (var i = 0; i < tenpercent; ++i) {
+        widths.pop();
+        widths.shift();
+      }
+      //calculate average width
+      var avg_width = 0;
+      for (var i = 0; i < widths.length; ++i) avg_width += widths[i];
+      avg_width /= widths.length;
+      // calculate scales
+      for (var i = 0; i < this.dimensions.length; ++i) {
+        var size = this.dimensions[i];
+        // calculate scale
+        var scale = target_width / Math.max(avg_width, size.width);
+        // estimate scaled height
+        var target_height = size.height * scale;
+        // create an approprately sized canvas
+        var raster = document.createElement("canvas");
+        raster.width = target_width; // if it goes over the edge too bad...
+        raster.height = target_height + safety_pad * 2;
+        // calculate the middle
+        middle = Math.round(raster.width / 2);
+        // calculate the baseline
+        baseline = Math.round(raster.height - safety_pad);
+        // get the context and prepare to draw the rasterized text
+        ctx = raster.getContext('2d');
+        ctx.font = font;
+        ctx.fillStyle = alphabet.get_colour(i);
+        ctx.textAlign = "center";
+        ctx.translate(middle, baseline);
+        ctx.save();
+        ctx.scale(scale, scale);
+        // draw the rasterized text
+        ctx.fillText(letters[i], 0, 0);
+        ctx.restore();
+        this.rasters[i] = raster;
+        this.dimensions[i] = RasterizedAlphabet_measure(ctx, raster.width, raster.height);
+      }
+    }
+
+    function RasterizedAlphabet_measure(ctx, cwidth, cheight) {
+      var data = ctx.getImageData(0, 0, cwidth, cheight).data;
+      var r = 0, c = 0;// r: row, c: column
+      var top_line = -1, bottom_line = -1, left_line = -1, right_line = -1;
+      var txt_width = 0, txt_height = 0;
+      // Find the top-most line with a non-white pixel
+      for (r = 0; r < cheight; r++) {
+        for (c = 0; c < cwidth; c++) {
+          if (data[r * cwidth * 4 + c * 4 + 3]) {
+            top_line = r;
+            break;
+          }
+        }
+        if (top_line != -1) break;
+      }
+      
+      //find the last line with a non-white pixel
+      if (top_line != -1) {
+        for (r = cheight-1; r >= top_line; r--) {
+          for(c = 0; c < cwidth; c++) {
+            if(data[r * cwidth * 4 + c * 4 + 3]) {
+              bottom_line = r;
+              break;
+            }
+          }
+          if (bottom_line != -1) break;
+        }
+        txt_height = bottom_line - top_line + 1;
+      }
+
+      // Find the left-most line with a non-white pixel
+      for (c = 0; c < cwidth; c++) {
+        for (r = 0; r < cheight; r++) {
+          if (data[r * cwidth * 4 + c * 4 + 3]) {
+            left_line = c;
+            break;
+          }
+        }
+        if (left_line != -1) break;
+      }
+
+      //find the right most line with a non-white pixel
+      if (left_line != -1) {
+        for (c = cwidth-1; c >= left_line; c--) {
+          for(r = 0; r < cheight; r++) {
+            if(data[r * cwidth * 4 + c * 4 + 3]) {
+              right_line = c;
+              break;
+            }
+          }
+          if (right_line != -1) break;
+        }
+        txt_width = right_line - left_line + 1;
+      }
+
+      //return the bounds
+      return {bound_top: top_line, bound_bottom: bottom_line, bound_left: left_line, bound_right: right_line, width: txt_width, height: txt_height};
+    }
+
+    function RasterizedAlphabet_draw(ctx, letter, dx, dy, dWidth, dHeight) {
+      var index = this.lookup[letter];
+      var raster = this.rasters[index];
+      var size = this.dimensions[index];
+      ctx.drawImage(raster, 0, size.bound_top -1, raster.width, size.height+1, dx, dy, dWidth, dHeight);
+    }
+
+    //======================================================================
+    // end RasterizedAlphabet
+    //======================================================================
+
+    //======================================================================
+    // start LogoMetrics object
+    //======================================================================
+
+    function LogoMetrics(ctx, canvas_width, canvas_height, logo_columns, logo_rows, allow_space_for_names) {
+      if (allow_space_for_names === undefined) allow_space_for_names = false;
+      //variable prototypes
+      this.canvas_width = canvas_width;
+      this.canvas_height = canvas_height;
+      this.scale_x = 1;
+      this.scale_y = 1;
+      this.pad_top = 5;
+      this.pad_left = 10;
+      this.pad_right = 5;
+      this.pad_bottom = 0;
+      this.pad_middle = 20;
+      this.name_height = 14;
+      this.name_font = "bold " + this.name_height + "px Times, sans-serif";
+      this.name_spacer = 0;
+      this.y_label = "bits"
+      this.y_label_height = 12;
+      this.y_label_font = "bold " + this.y_label_height + "px Helvetica, sans-serif";
+      this.y_label_spacer = 3;
+      this.y_num_height = 12;
+      this.y_num_width = 0;
+      this.y_num_font = "bold " + this.y_num_height + "px Helvetica, sans-serif";
+      this.y_tic_width = 5;
+      this.stack_pad_left = 0;
+      this.stack_font = "bold 25px Helvetica, sans-serif";
+      this.stack_height = 90;
+      this.stack_width = 26;
+      this.stacks_pad_right = 5;
+      this.x_num_above = 2;
+      this.x_num_height = 12;
+      this.x_num_width = 0;
+      this.x_num_font = "bold " + this.x_num_height + "px Helvetica, sans-serif";
+      this.fine_txt_height = 6;
+      this.fine_txt_above = 2;
+      this.fine_txt_font = "normal " + this.fine_txt_height + "px Helvetica, sans-serif";
+      this.letter_metrics = new Array();
+      this.summed_width = 0;
+      this.summed_height = 0;
+      //function prototypes
+      //none
+      //calculate the width of the y axis numbers
+      ctx.font = this.y_num_font;
+      for (var i = 0; i <= 2; i++) {
+        this.y_num_width = Math.max(this.y_num_width, ctx.measureText("" + i).width);
+      }
+      //calculate the width of the x axis numbers (but they are rotated so it becomes height)
+      ctx.font = this.x_num_font;
+      for (var i = 1; i <= logo_columns; i++) {
+        this.x_num_width = Math.max(this.x_num_width, ctx.measureText("" + i).width);
+      }
+      
+      //calculate how much vertical space we want to draw this
+      //first we add the padding at the top and bottom since that's always there
+      this.summed_height += this.pad_top + this.pad_bottom;
+      //all except the last row have the same amount of space allocated to them
+      if (logo_rows > 1) {
+        var row_height = this.stack_height + this.pad_middle;
+        if (allow_space_for_names) {
+          row_height += this.name_height;
+          //the label is allowed to overlap into the spacer
+          row_height += Math.max(this.y_num_height/2, this.name_spacer); 
+          //the label is allowed to overlap the space used by the other label
+          row_height += Math.max(this.y_num_height/2, this.x_num_height + this.x_num_above); 
+        } else {
+          row_height += this.y_num_height/2; 
+          //the label is allowed to overlap the space used by the other label
+          row_height += Math.max(this.y_num_height/2, this.x_num_height + this.x_num_above); 
+        }
+        this.summed_height += row_height * (logo_rows - 1);
+      }
+      //the last row has the name and fine text below it but no padding
+      this.summed_height += this.stack_height + this.y_num_height/2;
+      if (allow_space_for_names) {
+        this.summed_height += this.fine_txt_height + this.fine_txt_above + this.name_height;
+        this.summed_height += Math.max(this.y_num_height/2, this.x_num_height + this.x_num_above + this.name_spacer);
+      } else {
+        this.summed_height += Math.max(this.y_num_height/2, this.x_num_height + this.x_num_above + this.fine_txt_height + this.fine_txt_above);
+      }
+
+      //calculate how much horizontal space we want to draw this
+      //first add the padding at the left and right since that's always there
+      this.summed_width += this.pad_left + this.pad_right;
+      //add on the space for the y-axis label
+      this.summed_width += this.y_label_height + this.y_label_spacer;
+      //add on the space for the y-axis
+      this.summed_width += this.y_num_width + this.y_tic_width;
+      //add on the space for the stacks
+      this.summed_width += (this.stack_pad_left + this.stack_width) * logo_columns;
+      //add on the padding after the stacks (an offset from the fine text)
+      this.summed_width += this.stacks_pad_right;
+
+      //calculate scaling factors
+      this.scale_y = this.canvas_height / this.summed_height;
+      this.scale_x = this.canvas_width / this.summed_width;
+
+      //maintain aspect ratio
+      if (this.scale_y > this.scale_x) {
+        this.scale_y = this.scale_x;
+      } else {
+        this.scale_x = this.scale_y;
+      }
+
+
+    }
+
+    //======================================================================
+    // end LogoMetrics object
+    //======================================================================
+
+
+    //found this trick at http://talideon.com/weblog/2005/02/detecting-broken-images-js.cfm
+    function image_ok(img) {
+      // During the onload event, IE correctly identifies any images that
+      // weren't downloaded as not complete. Others should too. Gecko-based
+      // browsers act like NS4 in that they report this incorrectly.
+      if (!img.complete) {
+        return false;
+      }
+      // However, they do have two very useful properties: naturalWidth and
+      // naturalHeight. These give the true size of the image. If it failed
+      // to load, either of these should be zero.
+      if (typeof img.naturalWidth != "undefined" && img.naturalWidth == 0) {
+        return false;
+      }
+      // No other way of checking: assume it's ok.
+      return true;
+    }
+      
+    function supports_text(ctx) {
+      if (!ctx.fillText) return false;
+      if (!ctx.measureText) return false;
+      return true;
+    }
+
+    //draws the scale, returns the width
+    function draw_scale(ctx, metrics, alphabet_ic) {
+      var tic_height = metrics.stack_height / alphabet_ic;
+      ctx.save();
+      ctx.lineWidth = 1.5;
+      ctx.translate(metrics.y_label_height, metrics.y_num_height/2);
+      //draw the axis label
+      ctx.save();
+      ctx.font = metrics.y_label_font;
+      ctx.translate(0, metrics.stack_height/2);
+      ctx.save();
+      ctx.rotate(-(Math.PI / 2));
+      ctx.textAlign = "center";
+      ctx.fillText("bits", 0, 0);
+      ctx.restore();
+      ctx.restore();
+
+      ctx.translate(metrics.y_label_spacer + metrics.y_num_width, 0);
+
+      //draw the axis tics
+      ctx.save();
+      ctx.translate(0, metrics.stack_height);
+      ctx.font = metrics.y_num_font;
+      ctx.textAlign = "right";
+      ctx.textBaseline = "middle";
+      for (var i = 0; i <= alphabet_ic; i++) {
+        //draw the number
+        ctx.fillText("" + i, 0, 0);
+        //draw the tic
+        ctx.beginPath();
+        ctx.moveTo(0, 0);
+        ctx.lineTo(metrics.y_tic_width, 0);
+        ctx.stroke();
+        //prepare for next tic
+        ctx.translate(0, -tic_height);
+      }
+      ctx.restore();
+
+      ctx.translate(metrics.y_tic_width, 0);
+
+      ctx.beginPath();
+      ctx.moveTo(0, 0);
+      ctx.lineTo(0, metrics.stack_height);
+      ctx.stroke();
+
+      ctx.restore();
+    }
+
+    function draw_stack_num(ctx, metrics, row_index) {
+      ctx.save();
+      ctx.font = metrics.x_num_font;
+      ctx.translate(metrics.stack_width / 2, metrics.stack_height + metrics.x_num_above);
+      ctx.save();
+      ctx.rotate(-(Math.PI / 2));
+      ctx.textBaseline = "middle"
+      ctx.textAlign = "right"
+      ctx.fillText("" + (row_index + 1), 0, 0);
+      ctx.restore();
+      ctx.restore();
+    }
+
+    function draw_stack(ctx, metrics, symbols, raster) {
+      var preferred_pad = 0;
+      var sym_min = 5;
+
+      ctx.save();//1
+      ctx.translate(0, metrics.stack_height);
+      for (var i in symbols) {
+        //exclude inherited properties and undefined properties
+        if (!symbols.hasOwnProperty(i) || symbols[i] === undefined) continue;
+        
+        var sym = symbols[i];
+        var sym_height = metrics.stack_height * sym.get_scale();
+        
+        var pad = preferred_pad;
+        if (sym_height - pad < sym_min) {
+          pad = Math.min(pad, Math.max(0, sym_height - sym_min));
+        }
+        sym_height -= pad;
+
+        //translate to the correct position
+        ctx.translate(0, -(pad/2 + sym_height));
+        //draw
+        raster.draw(ctx, sym.get_symbol(), 0, 0, metrics.stack_width, sym_height);
+        //translate past the padding
+        ctx.translate(0, -(pad/2));
+      }
+      ctx.restore();//1
+    }
+
+    //draws a stack of symbols
+    function draw_stack_old(ctx, metrics, symbols) {
+      var lpad = 2;
+      var sym_min = 5;
+      var pos = metrics.stack_height;
+      for (var i in symbols) {
+        //exclude inherited properties and undefined properties
+        if (!symbols.hasOwnProperty(i) || symbols[i] === undefined) continue;
+        
+        var sym = symbols[i];
+        var sym_height = metrics.stack_height*sym.get_scale();
+        var letter = metrics.get_letter_metrics(sym.get_symbol());
+        //attempting to draw something smaller than a pixel causes display corruption
+        if (sym_height >= 1) {
+          //it's better to see the letter than to pad it
+          var pad = lpad;
+          if (sym_height - pad < sym_min) {
+            pad = Math.min(pad, Math.max(0, sym_height - sym_min));
+          }
+          //move to the correct drawing position
+          ctx.save();//s1
+          ctx.translate(0, pos);
+          //create a clipping rectangle to ensure the letter doesn't overlap when it's distorted
+          ctx.save();//s2
+          //ctx.beginPath(); //disabled clipping because after the improvements in the text metrics it looks better without
+          //ctx.moveTo(-metrics.stack_width/2,0);
+          //ctx.lineTo(metrics.stack_width/2, 0);
+          //ctx.lineTo(metrics.stack_width/2, -sym_height);
+          //ctx.lineTo(-metrics.stack_width/2, -sym_height);
+          //ctx.lineTo(-metrics.stack_width/2,0);
+          //ctx.clip();
+          //now draw
+          ctx.translate(0, -(pad/2));
+          ctx.translate(0, -letter.get_descent(sym_height - pad));
+          ctx.fillStyle = sym.get_colour();
+          ctx.textAlign = "center";
+          ctx.save();//s3
+          ctx.scale(letter.wscale, letter.get_hscale(sym_height - pad));
+          ctx.fillText(sym.get_symbol(), 0, 0);
+          ctx.restore();//s3
+
+          ctx.restore();//s2
+          ctx.restore();//s1
+        }
+
+        pos = pos - sym_height;
+      }
+    }
+    
+    function draw_dashed_line(ctx, pattern, start, x1, y1, x2, y2) {
+        var x, y, len, i;
+        var dx = x2 - x1;
+        var dy = y2 - y1;
+        var tlen = Math.pow(dx*dx + dy*dy, 0.5);
+        var theta = Math.atan2(dy,dx);
+        var mulx = Math.cos(theta);
+        var muly = Math.sin(theta);
+        var lx = [];
+        var ly = [];
+        for (i = 0; i < pattern; ++i) {
+          lx.push(pattern[i] * mulx);
+          ly.push(pattern[i] * muly);
+        }
+        i = start;
+        x = x1;
+        y = y1;
+        len = 0;
+        ctx.beginPath();
+        while (len + pattern[i] < tlen) {
+          ctx.moveTo(x, y);
+          x += lx[i];
+          y += ly[i];
+          ctx.lineTo(x, y);
+          len += pattern[i];
+          i = (i + 1) % pattern.length;
+          x += lx[i];
+          y += ly[i];
+          len += pattern[i];
+          i = (i + 1) % pattern.length;
+        }
+        if (len < tlen) {
+          ctx.moveTo(x, y);
+          x += mulx * (tlen - len);
+          y += muly * (tlen - len);
+          ctx.lineTo(x, y);
+        }
+        ctx.stroke();
+    }
+
+    function draw_trim_background(ctx, metrics, pspm, offset) {
+      var lwidth = metrics.stack_width * pspm.get_left_trim();
+      var rwidth = metrics.stack_width * pspm.get_right_trim();
+      var mwidth = metrics.stack_width * pspm.get_motif_length();
+      var rstart = mwidth - rwidth;
+      ctx.save();//s8
+      ctx.translate(offset * metrics.stack_width, 0);
+      ctx.fillStyle = "rgb(240, 240, 240)";
+      if (pspm.get_left_trim() > 0) ctx.fillRect(0, 0, lwidth, metrics.stack_height);
+      if (pspm.get_right_trim() > 0) ctx.fillRect(rstart, 0, rwidth, metrics.stack_height);
+      ctx.fillStyle = "rgb(51, 51, 51)";
+      if (pspm.get_left_trim() > 0) draw_dashed_line(ctx, [3], 0, lwidth-0.5, 0, lwidth-0.5,  metrics.stack_height);
+      if (pspm.get_right_trim() > 0) draw_dashed_line(ctx, [3], 0, rstart+0.5, 0, rstart+0.5,  metrics.stack_height);
+      ctx.restore();//s8
+    }
+
+    function draw_logo_on_canvas(logo, canvas, show_names, scale) {
+      var draw_name = (typeof show_names == "boolean" ? show_names : (logo.get_rows() > 1));
+      var cwidth = canvas.width;
+      var cheight = canvas.height;
+      //need a minimum 46 x 120 canvas to draw the font size checks on
+      if (canvas.width < 46) canvas.width = 46;
+      if (canvas.height < 120) canvas.height = 120;
+      var ctx = canvas.getContext('2d');
+      //assume that the user wants the canvas scaled equally so calculate what the best width for this image should be
+      var metrics = new LogoMetrics(ctx, canvas.width, canvas.height, logo.get_columns(), logo.get_rows(), draw_name);
+      ctx.save();//s1
+      if (typeof scale == "number") {
+        //resize the canvas to fit the scaled logo
+        cwidth = metrics.summed_width * scale;
+        cheight = metrics.summed_height * scale;
+      } else {
+        if (cwidth == 0 && cheight == 0) {
+          throw "CANVAS_MUST_HAVE_DIMENSIONS";
+        } else if (cwidth == 0) {
+          scale = cheight / metrics.summed_height;
+          cwidth = metrics.summed_width * scale;
+        } else if (cheight == 0) {
+          scale = cwidth / metrics.summed_width;
+          cheight = metrics.summed_height * scale;
+        } else {
+          scale = Math.min(cwidth / metrics.summed_width, cheight / metrics.summed_height);
+        }
+      }
+      var raster = new RasterizedAlphabet(logo.alphabet, metrics.stack_font, metrics.stack_width * scale * 2);
+      if (cwidth != canvas.width || cheight != canvas.height) {
+        canvas.width = cwidth;
+        canvas.height = cheight;
+        //as the canvas has been resized the context is now out of date
+        ctx = canvas.getContext('2d');
+      }
+      ctx.scale(scale, scale);
+      ctx.save();//s2
+      ctx.save();//s7
+      //create margin
+      ctx.translate(metrics.pad_left, metrics.pad_top);
+      for (var pspm_i = 0; pspm_i < logo.get_rows(); ++pspm_i) {
+        var pspm = logo.get_pspm(pspm_i);
+        var offset = logo.get_offset(pspm_i);
+        //optionally draw name if this isn't the last row or is the only row 
+        if (draw_name && (logo.get_rows() == 1 || pspm_i != (logo.get_rows()-1))) {
+          ctx.save();//s4
+          ctx.translate(metrics.summed_width/2, metrics.name_height);
+          ctx.font = metrics.name_font;
+          ctx.textAlign = "center";
+          ctx.fillText(pspm.name, 0, 0);
+          ctx.restore();//s4
+          ctx.translate(0, metrics.name_height + Math.min(0, metrics.name_spacer - metrics.y_num_height/2));
+        }
+        //draw scale
+        draw_scale(ctx, metrics, logo.alphabet.get_ic());
+        ctx.save();//s5
+        //translate across past the scale
+        ctx.translate(metrics.y_label_height + metrics.y_label_spacer + 
+            metrics.y_num_width + metrics.y_tic_width, 0);
+        //draw the trimming background
+        if (pspm.get_left_trim() > 0 || pspm.get_right_trim() > 0) {
+          draw_trim_background(ctx, metrics, pspm, offset);
+        }
+        //draw letters
+        ctx.translate(0, metrics.y_num_height / 2);
+        for (var col_index = 0; col_index < logo.get_columns(); col_index++) {
+          ctx.translate(metrics.stack_pad_left,0);
+          if (col_index >= offset && col_index < (offset + pspm.get_motif_length())) {
+            var motif_position = col_index - offset;
+            draw_stack_num(ctx, metrics, motif_position);
+            draw_stack(ctx, metrics, pspm.get_stack(motif_position, logo.alphabet), raster);
+          }
+          ctx.translate(metrics.stack_width, 0);
+        }
+        ctx.restore();//s5
+        ////optionally draw name if this is the last row but isn't the only row 
+        if (draw_name && (logo.get_rows() != 1 && pspm_i == (logo.get_rows()-1))) {
+          //translate vertically past the stack and axis's        
+          ctx.translate(0, metrics.y_num_height/2 + metrics.stack_height + 
+              Math.max(metrics.y_num_height/2, metrics.x_num_above + metrics.x_num_width + metrics.name_spacer));
+
+          ctx.save();//s6
+          ctx.translate(metrics.summed_width/2, metrics.name_height);
+          ctx.font = metrics.name_font;
+          ctx.textAlign = "center";
+          ctx.fillText(pspm.name, 0, 0);
+          ctx.restore();//s6
+          ctx.translate(0, metrics.name_height);
+        } else {
+          //translate vertically past the stack and axis's        
+          ctx.translate(0, metrics.y_num_height/2 + metrics.stack_height + Math.max(metrics.y_num_height/2, metrics.x_num_above + metrics.x_num_width));
+        }
+        //if not the last row then add middle padding
+        if (pspm_i != (logo.get_rows() -1)) {
+          ctx.translate(0, metrics.pad_middle);
+        }
+      }
+      ctx.restore();//s7
+      ctx.translate(metrics.summed_width - metrics.pad_right, metrics.summed_height - metrics.pad_bottom);
+      ctx.font = metrics.fine_txt_font;
+      ctx.textAlign = "right";
+      ctx.fillText(logo.fine_text, 0,0);
+      ctx.restore();//s2
+      ctx.restore();//s1
+    }
+
+    function create_canvas(c_width, c_height, c_id, c_title, c_display) {
+      var canvas = document.createElement("canvas");
+      //check for canvas support before attempting anything
+      if (!canvas.getContext) return null;
+      var ctx = canvas.getContext('2d');
+      //check for html5 text drawing support
+      if (!supports_text(ctx)) return null;
+      //size the canvas
+      canvas.width = c_width;
+      canvas.height = c_height;
+      canvas.id = c_id;
+      canvas.title = c_title;
+      canvas.style.display = c_display;
+      return canvas;
+    }
+
+    function logo_1(alphabet, fine_text, pspm) {
+      var logo = new Logo(alphabet, fine_text);
+      logo.add_pspm(pspm);
+      return logo;
+    }
+    
+    function logo_2(alphabet, fine_text, target, query, query_offset) {
+      var logo = new Logo(alphabet, fine_text);
+      if (query_offset < 0) {
+        logo.add_pspm(target, -query_offset);
+        logo.add_pspm(query);
+      } else {
+        logo.add_pspm(target);
+        logo.add_pspm(query, query_offset);
+      }      
+      return logo;
+    }
+
+    /*
+     * Specifies an alternate source for an image.
+     * If the image with the image_id specified has
+     * not loaded then a generated logo will be used 
+     * to replace it.
+     *
+     * Note that the image must either have dimensions
+     * or a scale must be set.
+     */
+    function alternate_logo(logo, image_id, scale) {
+      var image = document.getElementById(image_id);
+      if (!image) {
+        alert("Can't find specified image id (" +  image_id + ")");
+        return;
+      }
+      //if the image has loaded then there is no reason to use the canvas
+      if (image_ok(image)) return;
+      //the image has failed to load so replace it with a canvas if we can.
+      var canvas = create_canvas(image.width, image.height, image_id, image.title, image.style.display);
+      if (canvas == null) return;
+      //draw the logo on the canvas
+      draw_logo_on_canvas(logo, canvas, undefined, scale);
+      //replace the image with the canvas
+      image.parentNode.replaceChild(canvas, image);
+    }
+
+    /*
+     * Specifes that the element with the specified id
+     * should be replaced with a generated logo.
+     */
+    function replace_logo(logo, replace_id, scale, title_txt, display_style) {
+      var element = document.getElementById(replace_id);
+      if (!replace_id) {
+        alert("Can't find specified id (" + replace_id + ")");
+        return;
+      }
+      //found the element!
+      var canvas = create_canvas(50, 120, replace_id, title_txt, display_style);
+      if (canvas == null) return;
+      //draw the logo on the canvas
+      draw_logo_on_canvas(logo, canvas, undefined, scale);
+      //replace the element with the canvas
+      element.parentNode.replaceChild(canvas, element);
+    }
+
+    /*
+     * Fast string trimming implementation found at
+     * http://blog.stevenlevithan.com/archives/faster-trim-javascript
+     *
+     * Note that regex is good at removing leading space but
+     * bad at removing trailing space as it has to first go through
+     * the whole string.
+     */
+    function trim (str) {
+      str = str.replace(/^\s\s*/, '');
+      var ws = /\s/, i = str.length;
+      while (ws.test(str.charAt(--i)));
+      return str.slice(0, i + 1);
+    }
+    /* END INCLUDED FILE "motif_logo.js" */
+    
+  
+    
+    /* START INCLUDED FILE "dreme-to-html.js" */
+      var expansion_lookup = [];
+
+      /*
+       * show_hidden
+       *
+       * Looks for specially named elements and switches to the shown view
+       */
+      function show_hidden(prefix) {
+        document.getElementById(prefix + '_activator').style.display = 'none';
+        document.getElementById(prefix + '_deactivator').style.display = 'block';
+        document.getElementById(prefix + '_data').style.display = 'block';
+      }
+      /*
+       * hide_shown
+       *
+       * Looks for specially named elements and switches to the hidden view
+       */
+      function hide_shown(prefix) {
+        document.getElementById(prefix + '_activator').style.display = 'block';
+        document.getElementById(prefix + '_deactivator').style.display = 'none';
+        document.getElementById(prefix + '_data').style.display = 'none';
+      }
+
+      function click_download_tab(tab) {
+        document.getElementById("download_tab_num").value = tab;
+        for (var i = 1; i <= 3; i++) {
+          document.getElementById('download_tab_'+i).className = "tab" + (i==tab ? " activeTab" : "");
+          document.getElementById('download_pnl_'+i).style.display = (i==tab ? "block" : "none");
+        }
+        document.getElementById('download_button').style.visibility = (tab==3 ? "visible" : "hidden");
+      }
+
+
+      /*
+       * searches child nodes in depth first order and returns the
+       * first it finds with the className specified.
+       */
+      function find_child_element_by_class(node, className) {
+        var patt = new RegExp("\\b" + className + "\\b");
+
+        if (node.nodeType == Node.ELEMENT_NODE && 
+            patt.test(node.className)) {
+          return node;
+        } else {
+          var result = null;
+          for (var i = 0; i < node.childNodes.length; i++) {
+            result = find_child_element_by_class(node.childNodes[i], className);
+            if (result != null) break;
+          }
+          return result;
+        }
+      }
+
+      function find_parent_element_by_class(node, className) {
+        var patt = new RegExp("\\b" + className + "\\b");
+        if (node.nodeType == Node.ELEMENT_NODE && 
+            patt.test(node.className)) {
+          return node;
+        } else if (node.parentNode != null) {
+          return find_parent_element_by_class(node.parentNode, className);
+        }
+        return null;
+      }
+
+      /*
+       * expand
+       *
+       * Expand the extra data section for a motif.
+       */
+      function expand(num) {
+        // get motif data
+        var motif_info = motif_seqs[num];
+        var motif_id = motif_info[0];
+        var seq = motif_info[1];
+        var rcseq = motif_info[2];
+        var length = motif_info[3];
+        var nsites = motif_info[4];
+        var p_hits = motif_info[5];
+        var n_hits = motif_info[6];
+        var pvalue = motif_info[7];
+        var evalue = motif_info[8];
+        var uevalue = motif_info[9];
+        var matches = motif_info[10];
+        // find the location to insert the expanded motif data
+        var table = document.getElementById('dreme_motifs');
+        var motif_row = document.getElementById('motif_row_' + num);
+        var exp_row = table.insertRow(motif_row.rowIndex + 1);
+        exp_row.id = 'exp_row_' + num;
+        var cell = exp_row.insertCell(0);
+        cell.colSpan = 9;
+        // create the DOM to insert
+        var exp = document.getElementById('expanded_motif').firstChild.cloneNode(true);
+        // update fields
+        set_content_to_text(find_child_element_by_class(exp, 'name'), seq);
+        set_content_to_text(find_child_element_by_class(exp, 'num'), num);
+        var img = find_child_element_by_class(exp, 'img_nc');
+        img.src = motif_id + "nc_" + seq + ".png";
+        var imgrc = find_child_element_by_class(exp, 'img_rc');
+        imgrc.src = motif_id + "rc_" + rcseq + ".png";
+        // fill in the details
+        var details = find_child_element_by_class(exp, 'details');
+        set_content_to_text(find_child_element_by_class(details, 'positives'), p_hits);
+        set_content_to_text(find_child_element_by_class(details, 'negatives'), n_hits);
+        set_content_to_text(find_child_element_by_class(details, 'pvalue'), pvalue);
+        set_content_to_text(find_child_element_by_class(details, 'evalue'), evalue);
+        set_content_to_text(find_child_element_by_class(details, 'uevalue'), uevalue);
+        
+        // fill in match table
+        var match_row = find_child_element_by_class(exp, 'match');
+        var tbody = match_row.parentNode;
+        for (var i = 0; i < matches.length; i++) {
+          var match = matches[i];
+          var cseq = match[0];
+          var cpos = match[1];
+          var cneg = match[2];
+          var cpval = match[3].toExponential(1);
+          var ceval = match[4].toExponential(1);
+          var row = match_row.cloneNode(true);
+          var td_cseq = find_child_element_by_class(row, 'dnaseq');
+          set_content_to_text(td_cseq, cseq);
+          colour_dna_seq(td_cseq);
+          set_content_to_text(find_child_element_by_class(row, 'positives'), cpos);
+          set_content_to_text(find_child_element_by_class(row, 'negatives'), cneg);
+          set_content_to_text(find_child_element_by_class(row, 'pvalue'), cpval);
+          set_content_to_text(find_child_element_by_class(row, 'evalue'), ceval);
+          tbody.appendChild(row);
+        }
+        tbody.removeChild(match_row);
+        // append the expanded information
+        cell.appendChild(exp);
+        // hide the old row
+        motif_row.style.display = 'none';
+        update_headers();
+      }
+
+      function expanded_num(elem) {
+        var exp = find_parent_element_by_class(elem, 'expanded_motif');
+        var num = parseInt(nodes_text(text_nodes(find_child_element_by_class(exp, 'num'))));
+        return num;
+      }
+
+      function contract(contained_node) {
+        var table = document.getElementById('dreme_motifs');
+        var num = expanded_num(contained_node);
+        var motif_row = document.getElementById('motif_row_' + num);
+        var exp_row = document.getElementById('exp_row_' + num);
+
+        motif_row.style.display = 'table-row';
+        table.deleteRow(exp_row.rowIndex);
+        update_headers();
+      }
+
+      function update_headers() {
+        var motif_row_patt = new RegExp("\\bmotif_row\\b");
+        var motif_head_patt = new RegExp("\\bmotif_head\\b");
+        var table = document.getElementById('dreme_motifs');
+        var header = table.tHead.getElementsByTagName('tr')[0];
+        header.style.display = 'none';
+        var trs = table.tBodies[0].getElementsByTagName('tr');
+        var needHeader = true;
+        for (var i = 0; i < trs.length; i++) {
+          var row = trs[i];
+          if (row.style.display == 'none') continue;
+          if (motif_row_patt.test(row.className)) {
+            if (needHeader) {
+              var dupHeader = header.cloneNode(true);
+              dupHeader.style.display = 'table-row';
+              row.parentNode.insertBefore(dupHeader, row);
+              needHeader = false;
+              i++;
+            }
+          } else if (motif_head_patt.test(row.className)) {
+            table.deleteRow(row.rowIndex);
+            i--;
+          } else {
+            needHeader = true;
+          }
+        }
+      }
+
+      function set_content_to_text(ele, text) {
+        while(ele.hasChildNodes()) {
+          ele.removeChild(ele.firstChild);
+        }
+        ele.appendChild(document.createTextNode(text));
+      }
+
+      function both_setup(pos) {
+        // get the total number of motifs
+        var nmotifs = parseInt(document.getElementById('nmotifs').value, 10);
+        // set the motif that we're submitting
+        document.getElementById('submit_motif').value = (pos == 0 ? 'all' : pos);
+        document.getElementById('send_to_selector').style.display = (pos == 0 ? 'none' : 'block');
+        document.getElementById('send_to_title_1').style.display = (pos == 0 ? 'none' : 'block');
+        document.getElementById('send_to_title_2').style.display = (pos == 0 ? 'block' : 'none');
+
+        if (pos != 0) {
+          // get the information for the position
+          var motif_seq = motif_seqs[pos];
+          var motif_id = motif_seq[0];
+          var seq = motif_seq[1];
+          var rcseq = motif_seq[2];
+          // set the motif number
+          // set the titles of both popups
+          set_content_to_text(document.getElementById('send_to_name'), seq);
+          set_content_to_text(document.getElementById('download_name'), seq);
+          // set the images
+          var nc_img = "" + motif_id + "nc_" + seq + ".png";
+          var rc_img = "" + motif_id + "rc_" + rcseq + ".png";
+          var img;
+          img = document.getElementById('send_to_img');
+          img.src = nc_img;
+          img.style.display = "inline";
+          img = document.getElementById('send_to_rcimg');
+          img.src = rc_img;
+          img.style.display = "inline";
+          img = document.getElementById('download_img');
+          img.src = nc_img;
+          img.style.display = "inline";
+          img = document.getElementById('download_rcimg');
+          img.src = rc_img;
+          img.style.display = "inline";
+          // hide the canvas
+          document.getElementById('send_to_can').style.display = "none";
+          document.getElementById('send_to_rccan').style.display = "none";
+          document.getElementById('download_can').style.display = "none";
+          document.getElementById('download_rccan').style.display = "none";
+          // get some motif details
+          var pspm_text = document.getElementById("pspm"+ pos).value;
+          var pspm = new Pspm(pspm_text);
+          var alpha = new Alphabet(document.getElementById("alphabet").value, 
+              document.getElementById("bgfreq").value);
+          document.getElementById('download_pspm').value = pspm.as_pspm();
+          document.getElementById('download_pssm').value = pspm.as_pssm(alpha);
+          // set the width and height defaults
+          document.getElementById('logo_width').value = pspm.get_motif_length();
+          document.getElementById('logo_height').value = 7.5;
+          // hide and show the arrows
+          var prevclass = (pos == 1 ? "navarrow inactive" : "navarrow");
+          var nextclass = (pos == nmotifs ? "navarrow inactive" : "navarrow");
+          document.getElementById('prev_arrow_1').className = prevclass;
+          document.getElementById('prev_arrow_2').className = prevclass;
+          document.getElementById('next_arrow_1').className = nextclass;
+          document.getElementById('next_arrow_2').className = nextclass;
+          set_content_to_text(document.getElementById('pop_num_1'), pos);
+          set_content_to_text(document.getElementById('pop_num_2'), pos);
+        }
+      }
+
+      function both_change(inc) {
+        var motif_num = parseInt(document.getElementById('submit_motif').value, 10);
+        var nmotifs = parseInt(document.getElementById('nmotifs').value, 10);
+        var orig = motif_num;
+        motif_num += inc;
+        if (motif_num > nmotifs) motif_num = nmotifs;
+        else if (motif_num < 1) motif_num = 1;
+        if (orig != motif_num) both_setup(motif_num);
+      }
+
+      function both_hide() {
+        document.getElementById('grey_out_page').style.display = 'none';
+        document.getElementById('download').style.display = 'none';
+        document.getElementById('send_to').style.display = 'none';
+      }
+
+      /*
+       * lookup the information on a motif and prepare the
+       * popup for sending it to another program
+       */
+      function send_to_popup(pos) {
+        both_setup(pos);
+        var program = find_child_element_by_class(document.getElementById('programs'), 'selected').id;
+        var task = highlight_submit_task(null, submit_programs[program]);
+        highlight_submit_program(program, submit_tasks[task]);
+        update_submit_text(task, program);
+        // show the send to page
+        var grey_out = document.getElementById('grey_out_page');
+        grey_out.style.display = 'block';
+        var send_to_pop = document.getElementById('send_to');
+        send_to_pop.style.display = 'block';
+      }
+
+      function send_to_popup2(elem) {
+        send_to_popup(expanded_num(elem));
+      }
+
+      function send_to_submit() {
+        var program = find_child_element_by_class(document.getElementById('programs'), 'selected').id;
+        // set the hidden fields on the form
+        document.getElementById('submit_program').value = program;
+        // send the form
+        document.getElementById('submit_form').submit();
+        both_hide();
+      }
+
+      function download_popup(pos) {
+        both_setup(pos);
+        click_download_tab(document.getElementById("download_tab_num").value);
+        document.getElementById('submit_program').value = "LOGO";
+        // show the download page
+        var grey_out = document.getElementById('grey_out_page');
+        grey_out.style.display = 'block';
+        var download_pop = document.getElementById('download');
+        download_pop.style.display = 'block';
+      }
+
+      function download_popup2(elem) {
+        download_popup(expanded_num(elem));
+      }
+
+      function download_submit() {
+        var format = document.getElementById('logo_format').value;
+        var orient = document.getElementById('logo_rc').value;
+        var ssc = document.getElementById('logo_ssc').value;
+        var width = document.getElementById('logo_width').value;
+        var height = document.getElementById('logo_height').value;
+        document.getElementById('submit_format').value = format;
+        document.getElementById('submit_rc').value = orient;
+        document.getElementById('submit_ssc').value = ssc;
+        document.getElementById('submit_width').value = width;
+        document.getElementById('submit_height').value = height;
+        document.getElementById('submit_form').submit();
+        both_hide();
+      }
+
+      function FixLogoTask(num, rc) {
+        this.num = num;
+        this.rc = rc;
+        this.run = FixLogoTask_run;
+      }
+
+      function FixLogoTask_run() {
+        var pspm_text = document.getElementById("pspm" + this.num).value;
+        var alpha = new Alphabet("ACGT");
+        var pspm = new Pspm(pspm_text);
+        if (this.rc) pspm = pspm.reverse_complement(alpha);
+        var imgid = "small_" + (this.rc ? "rc_" : "") + "logo_" + this.num;
+
+        var image = document.getElementById(imgid);
+
+        var canvas = create_canvas(pspm.get_motif_length() *15, 50, image.id, 
+            image.title, image.style.display);
+        if (canvas == null) return;
+
+        var logo = logo_1(alpha, "DREME", pspm);
+        draw_logo_on_canvas(logo, canvas);
+        image.parentNode.replaceChild(canvas, image);
+      }
+
+      function fix_popup_logo(image, canvasid, rc) {
+        var motif_num = parseInt(document.getElementById('submit_motif').value, 10);
+        var pspm_text = document.getElementById("pspm" + motif_num).value;
+        var alpha = new Alphabet("ACGT");
+        var pspm = new Pspm(pspm_text);
+        if (rc) pspm = pspm.reverse_complement(alpha);
+        image.style.display = "none";
+        //check for canvas support before attempting anything
+        var canvas = document.getElementById(canvasid);
+        if (!canvas.getContext) return;
+        if (!supports_text(canvas.getContext('2d'))) return;
+        canvas.height = 90;
+        canvas.width = 170;
+        canvas.style.display = "inline";
+        var logo = logo_1(alpha, "DREME", pspm);
+        draw_logo_on_canvas(logo, canvas, false);
+      }
+
+      function fix_expanded_logo(image, rc) {
+        var motif_num = expanded_num(image);
+        var pspm_text = document.getElementById("pspm" + motif_num).value;
+        var alpha = new Alphabet("ACGT");
+        var pspm = new Pspm(pspm_text);
+        if (rc) pspm = pspm.reverse_complement(alpha);
+        //check for canvas support before attempting anything
+        var canvas = document.createElement('canvas');
+        if (!canvas.getContext) return;
+        if (!supports_text(canvas.getContext('2d'))) return;
+        canvas.height = 150;
+        canvas.width = 0;
+        draw_logo_on_canvas(logo_1(alpha, "DREME", pspm), canvas, false);
+        image.parentNode.replaceChild(canvas, image);
+      }
+
+      function text_nodes(container) {
+        var textNodes = [];
+        var stack = [container];
+        // depth first search to maintain ordering when flattened 
+        while (stack.length > 0) {
+          var node = stack.pop();
+          if (node.nodeType == Node.TEXT_NODE) {
+            textNodes.push(node);
+          } else {
+            for (var i = node.childNodes.length-1; i >= 0; i--) {
+              stack.push(node.childNodes[i]);
+            }
+          }
+        }
+        return textNodes;
+      }
+
+      function node_text(node) {
+        if (node === undefined) {
+          return '';
+        } else if (node.textContent) {
+          return node.textContent;
+        } else if (node.innerText) {
+          return node.innerText;
+        } else {
+          return '';
+        }
+      }
+
+      function nodes_text(nodes, separator) {
+        if (separator === undefined) separator = '';
+        var text = '';
+        if (nodes.length > 0) {
+          text += node_text(nodes[0]);
+        }
+        for (var i = 1; i < nodes.length; i++) {
+          text += separator + node_text(nodes[i]);
+        }
+        return text;
+      }
+
+      function colour_dna_seq(container) {
+        var textnodes = text_nodes(container);
+        for (var i = 0; i < textnodes.length; i++) {
+          var node = textnodes[i];
+          container.replaceChild(create_dna_seq(node_text(node)), node);
+        }
+      }
+
+      function create_dna_seq(seq) {
+        var out = document.createElement('span');
+        var last = 0;
+        for (var i = 0; i < seq.length; i++) {
+          var letter = seq.charAt(i);
+          if (letter == 'A' || letter == 'C' || letter == 'G' || letter == 'T') { 
+            if (last < i) {
+              out.appendChild(document.createTextNode(seq.substring(last, i)));
+            }
+            var coloured_letter = document.createElement('span');
+            coloured_letter.className = "dna_" + letter;
+            coloured_letter.appendChild(document.createTextNode(letter));
+            out.appendChild(coloured_letter);
+            last = i + 1;
+          }
+        }
+        if (last < seq.length) {
+          out.appendChild(document.createTextNode(seq.substring(last)));
+        }
+        return out;
+      }
+
+      function sort_table(colEle, compare_function) {
+        //find the parent of colEle that is either a td or th
+        var cell = colEle;
+        while (true) {
+          if (cell == null) return;
+          if (cell.nodeType == Node.ELEMENT_NODE && 
+              (cell.tagName.toLowerCase() == "td" || cell.tagName.toLowerCase() == "th")) {
+            break;
+          }
+          cell = cell.parentNode;
+        }
+        //find the parent of cell that is a tr
+        var row = cell;
+        while (true) {
+          if (row == null) return;
+          if (row.nodeType == Node.ELEMENT_NODE && row.tagName.toLowerCase() == "tr") {
+            break;
+          }
+          row = row.parentNode;
+        }
+        //find the parent of row that is a table
+        var table = row;
+        while (true) {
+          if (table == null) return;
+          if (table.nodeType == Node.ELEMENT_NODE && table.tagName.toLowerCase() == "table") {
+            break;
+          }
+          table = table.parentNode;
+        }
+        var column_index = cell.cellIndex;
+        // do a bubble sort, because the tables are so small it doesn't matter
+        var change;
+        var trs = table.tBodies[0].getElementsByTagName('tr');
+        var already_sorted = true;
+        var reverse = false;
+        while (true) {
+          do {
+            change = false;
+            for (var i = 0; i < trs.length -1; i++) {
+              var v1 = nodes_text(text_nodes(trs[i].cells[column_index]));
+              var v2 = nodes_text(text_nodes(trs[i+1].cells[column_index]));
+              if (reverse) {
+                var tmp = v1;
+                v1 = v2;
+                v2 = tmp;
+              }
+              if (compare_function(v1, v2) > 0) {
+                exchange(trs[i], trs[i+1], table);
+                change = true;
+                already_sorted = false;
+                trs = table.tBodies[0].getElementsByTagName('tr');
+              }
+            }
+          } while (change);
+          if (reverse) break;// we've sorted twice so exit
+          if (!already_sorted) break;// sort did something so exit
+          // when it's sorted one way already then sort the opposite way
+          reverse = true;
+        }
+        update_sort_arrows(row, column_index, reverse);
+      }
+
+      function update_sort_arrows(row, column_index, reverse) {
+        var ascending = "\u25BC";
+        var descending = "\u25B2";
+        var dir = (reverse ? descending : ascending);
+        for (var i = 0; i < row.cells.length; i++) {
+          var arrow = find_child_element_by_class(row.cells[i], "sort_dir");
+          if (arrow == null) continue;
+          if (i == column_index) {
+            set_content_to_text(arrow, dir);
+          } else {
+            set_content_to_text(arrow, "");
+          }
+        }
+      }
+    
+      function exchange(oRowI, oRowJ, oTable) {
+        var i = oRowI.rowIndex;
+        var j = oRowJ.rowIndex;
+         if (i == j+1) {
+          oTable.tBodies[0].insertBefore(oRowI, oRowJ);
+        } if (j == i+1) {
+          oTable.tBodies[0].insertBefore(oRowJ, oRowI);
+        } else {
+            var tmpNode = oTable.tBodies[0].replaceChild(oRowI, oRowJ);
+            if(typeof(oRowI) != "undefined") {
+              oTable.tBodies[0].insertBefore(tmpNode, oRowI);
+            } else {
+              oTable.appendChild(tmpNode);
+            }
+        }
+      }
+
+      function compare_numbers(v1, v2) {
+        var f1 = parseFloat(v1);
+        var f2 = parseFloat(v2);
+        if (f1 < f2) {
+          return -1;
+        } else if (f1 > f2) {
+          return 1;
+        } else {
+          return 0;
+        }
+      }
+
+      function compare_counts(v1, v2) {
+        var re = /(\d+)\/\d+/;
+        var m1 = re.exec(v1);
+        var m2 = re.exec(v2);
+        if (m1 == null && m2 == null) return 0;
+        if (m1 == null) return -1;
+        if (m2 == null) return 1;
+        return compare_numbers(m1[1], m2[1]);
+      }
+
+      function compare_strings(v1, v2) {
+        return v1.localeCompare(v2);
+      }
+      /*
+       * help
+       *
+       * Moves around help pop-ups so they appear
+       * below an activator.
+       */
+      function help(activator, popup_id) {
+        if (help.popup === undefined) {
+          help.popup = null;
+        }
+        if (help.activator === undefined) {
+          help.activator = null;
+        }
+
+        if (typeof(activator) == 'undefined') { // no activator so hide
+          help.popup.style.display = 'none';
+          help.popup = null;
+          return;
+        }
+        var pop = document.getElementById(popup_id);
+        if (pop == help.popup) {
+          if (activator == help.activator) {
+            //hide popup (as we've already shown it for the current help button)
+            help.popup.style.display = 'none';
+            help.popup = null;
+            return; // toggling complete!
+          }
+        } else if (help.popup != null) {
+          //activating different popup so hide current one
+          help.popup.style.display = 'none';
+        }
+        help.popup = pop;
+        help.activator = activator;
+
+        //must make the popup visible to measure it or it has zero width
+        pop.style.display = 'block';
+        var xy = get_elem_xy(activator);
+        var padding = 10;
+        var edge_padding = 15;
+        var scroll_padding = 15;
+
+        var pop_left = (xy[0] + (activator.offsetWidth / 2)  - (pop.offsetWidth / 2));
+        var pop_top = (xy[1] + activator.offsetHeight + padding);
+
+        // ensure the box is not past the top or left of the page
+        if (pop_left < 0) pop_left = edge_padding;
+        if (pop_top < 0) pop_top = edge_padding;
+        // ensure the box does not cause horizontal scroll bars
+        var page_width = null;
+        if (window.innerWidth) {
+          page_width = window.innerWidth;
+        } else if (document.body) {
+          page_width = document.body.clientWidth;
+        }
+        if (page_width) {
+          if (pop_left + pop.offsetWidth > page_width) {
+            pop_left = page_width - pop.offsetWidth - edge_padding - scroll_padding; //account for scrollbars
+          }
+        }
+
+        pop.style.left = pop_left + "px";
+        pop.style.top = pop_top + "px";
+      }
+
+      var submit_tasks = [];
+      submit_tasks['search_motifs'] = ['TOMTOM'];
+      submit_tasks['search_sequences'] = ['FIMO'];
+      submit_tasks['rank_sequences'] = ['MAST'];
+      submit_tasks['predict_go'] = ['GOMO'];
+      submit_tasks['infer_tf'] = ['SPAMO'];
+      var submit_programs = [];
+      submit_programs['TOMTOM'] = ['search_motifs'];
+      submit_programs['FIMO'] = ['search_sequences'];
+      submit_programs['MAST'] = ['rank_sequences'];
+      submit_programs['GOMO'] = ['predict_go'];
+      submit_programs['SPAMO'] = ['infer_tf'];
+      var submit_descriptions = [];
+      submit_descriptions['TOMTOM'] = "Find similar motifs in published " + 
+          "libraries or a library you supply.";
+      submit_descriptions['FIMO'] = "Find motif occurences in sequence data.";
+      submit_descriptions['MAST'] = "Rank sequences by affinity to groups " + 
+          "of motifs.";
+      submit_descriptions['GOMO'] = "Identify possible roles (Gene Ontology " + 
+          "terms) for motifs.";
+      submit_descriptions['SPAMO'] = "Find other motifs that are enriched at " +
+          "specific close spacings which might imply the existance of a complex.";
+
+
+      function click_submit_task(ele) {
+        var task = ele.id;
+        var program = highlight_submit_program(null, submit_tasks[task]);
+        highlight_submit_task(task, submit_programs[program]);
+        update_submit_text(task, program);
+      }
+
+      function click_submit_program(ele) {
+        var program = ele.id;
+        var task = highlight_submit_task(null, submit_programs[program]);
+        highlight_submit_program(program, submit_tasks[task]);
+        update_submit_text(task, program);
+      }
+
+      function update_submit_text(task, program) {
+        var task_ele = document.getElementById(task);
+        var program_ele = document.getElementById(program);
+        set_content_to_text(document.getElementById('program_action'), 
+            nodes_text(text_nodes(task_ele)));
+        set_content_to_text(document.getElementById('program_name'), 
+            nodes_text(text_nodes(program_ele)));
+        set_content_to_text(document.getElementById('program_desc'), 
+            submit_descriptions[program]);
+      }
+
+      function highlight_submit_task(select, highlights) {
+        var tasks_ul = document.getElementById('tasks');
+        var all_tasks = tasks_ul.getElementsByTagName('li');
+        var li;
+        var originally_selected = null;
+        // deselect everything in the tasks list
+        for (var i = 0; i < all_tasks.length; i++) {
+          li = all_tasks[i];
+          if (li.className == "selected") {
+            originally_selected = li;
+          }
+          li.className = "";
+        }
+        // highlight everything in the highlights list
+        for (var i = 0; i < highlights.length; i++) {
+          var li = document.getElementById(highlights[i]);
+          li.className = "active";
+        }
+        // check if we're setting the selected item specifically
+        if (select != null) {
+          li = document.getElementById(select);
+          li.className = "selected";
+          return select;
+        } else {
+          // if the originally selected item is allowed then keep it
+          // otherwise move to the first element of the highlight list
+          if (originally_selected != null && 
+              originally_selected.className == "active") {
+            originally_selected.className = "selected";
+            return originally_selected.id;
+          } else if (highlights.length > 0) {
+            li = document.getElementById(highlights[0]);
+            li.className = "selected";
+            return highlights[0];
+          }
+          return null;
+        }
+      }
+
+
+      function highlight_submit_program(select, highlights) {
+        var programs_ul = document.getElementById('programs');
+        var all_programs = programs_ul.getElementsByTagName('li');
+        var li;
+        var originally_selected = null;
+        // deselect everything in the programs list
+        for (var i = 0; i < all_programs.length; i++) {
+          li = all_programs[i];
+          if (li.className == "selected") {
+            originally_selected = li;
+          }
+          li.className = "";
+        }
+        // highlight everything in the highlights list
+        for (var i = 0; i < highlights.length; i++) {
+          var li = document.getElementById(highlights[i]);
+          li.className = "active";
+        }
+        // check if we're setting the selected item specifically
+        if (select != null) {
+          li = document.getElementById(select);
+          li.className = "selected";
+          return select;
+        } else {
+          // if the originally selected item is allowed then keep it
+          // otherwise move to the first element of the highlight list
+          if (originally_selected != null && 
+              originally_selected.className == "active") {
+            originally_selected.className = "selected";
+            return originally_selected.id;
+          } else if (highlights.length > 0) {
+            li = document.getElementById(highlights[0]);
+            li.className = "selected";
+            return highlights[0];
+          }
+          return null;
+        }
+      }
+    /* END INCLUDED FILE "dreme-to-html.js" */
+    
+  </script>
+</head>
+<body>
+<form id="submit_form" method="post" action="http://Sharplab-G4-1.local/meme/cgi-bin/meme_request.cgi" target="_blank">
+<!--+++++++++++++++START DATA+++++++++++++++-->
+<input type="hidden" name="version" value="MEME version 4.7.0">
+<input type="hidden" name="alphabet" id="alphabet" value="ACGT">
+<input type="hidden" name="strands" value="+ -">
+<input type="hidden" name="bgsrc" value="dataset">
+<input type="hidden" name="bgfreq" id="bgfreq" value="A 0.243 C 0.270 G 0.243 T 0.243">
+<input type="hidden" name="name" value="test">
+<input type="hidden" name="nmotifs" id="nmotifs" value="0">
+<!--+++++++++++++++FINISHED DATA++++++++++++-->
+<input type="hidden" name="program" id="submit_program" value="TOMTOM"><input type="hidden" name="motif" id="submit_motif" value="all"><input type="hidden" name="logoformat" id="submit_format" value="png"><input type="hidden" name="logorc" id="submit_rc" value="false"><input type="hidden" name="logossc" id="submit_ssc" value="false"><input type="hidden" name="logowidth" id="submit_width" value=""><input type="hidden" name="logoheight" id="submit_height" value="7.5">
+</form>
+<div class="pop_content" id="pop_motifs_name">
+<p>
+        The name of the motif uses the IUPAC codes for nucleotides which has 
+        a different letter to represent each of the 15 possible combinations.
+      </p>
+<p>
+        The name is itself a representation of the motif though the position
+        weight matrix is not directly equalivant as it is generated from the
+        sites found that matched the letters given in the name.
+      </p>
+<p><a href="http://meme.nbcr.net/meme/doc/alphabets.html">
+        Read more about the MEME suite's use of the IUPAC alphabets.
+        </a></p>
+<div style="float:right; bottom:0px;">[<a href="javascript:help()">close</a> ]</div>
+</div>
+<div class="pop_content" id="pop_motifs_logo">
+<p>The logo of the motif.</p>
+<div style="float:right; bottom:0px;">[<a href="javascript:help()">close</a> ]</div>
+</div>
+<div class="pop_content" id="pop_motifs_rc_logo">
+<p>The logo of the reverse complement motif.</p>
+<div style="float:right; bottom:0px;">[<a href="javascript:help()">close</a> ]</div>
+</div>
+<div class="pop_content" id="pop_motifs_evalue">
+<p>The E-value is the enrichment p-value times the number of candidate 
+        motifs tested.</p>
+<p>The enrichment p-value is calculated using the Fisher Exact Test for 
+        enrichment of the motif in the positive sequences.</p>
+<p>Note that the counts used in the Fisher Exact Test are made after 
+        erasing sites that match previously found motifs.</p>
+<div style="float:right; bottom:0px;">[<a href="javascript:help()">close</a> ]</div>
+</div>
+<div class="pop_content" id="pop_motifs_uevalue">
+<p>The E-value of the motif calculated without erasing the sites of 
+        previously found motifs.</p>
+<div style="float:right; bottom:0px;">[<a href="javascript:help()">close</a> ]</div>
+</div>
+<div class="pop_content" id="pop_more">
+<p>Show more information on the motif.</p>
+<div style="float:right; bottom:0px;">[<a href="javascript:help()">close</a> ]</div>
+</div>
+<div class="pop_content" id="pop_submit">
+<p>Submit your motif to another MEME Suite program.</p>
+<h5>Supported Programs</h5>
+<dl>
+<dt>Tomtom</dt>
+<dd>Tomtom is a tool for searching for similar known motifs. 
+          [<a href="http://meme.nbcr.net/meme/tomtom-intro.html">manual</a>]</dd>
+<dt>MAST</dt>
+<dd>MAST is a tool for searching biological sequence databases for 
+          sequences that contain one or more of a group of known motifs.
+          [<a href="http://meme.nbcr.net/meme/mast-intro.html">manual</a>]</dd>
+<dt>FIMO</dt>
+<dd>FIMO is a tool for searching biological sequence databases for 
+          sequences that contain one or more known motifs.
+          [<a href="http://meme.nbcr.net/meme/fimo-intro.html">manual</a>]</dd>
+<dt>GOMO</dt>
+<dd>GOMO is a tool for identifying possible roles (Gene Ontology 
+          terms) for DNA binding motifs.
+          [<a href="http://meme.nbcr.net/meme/gomo-intro.html">manual</a>]</dd>
+<dt>SpaMo</dt>
+<dd>SpaMo is a tool for inferring possible transcription factor
+          complexes by finding motifs with enriched spacings.
+          [<a href="http://meme.nbcr.net/meme/spamo-intro.html">manual</a>]</dd>
+</dl>
+<div style="float:right; bottom:0px;">[<a href="javascript:help()">close</a> ]</div>
+</div>
+<div class="pop_content" id="pop_download">
+<p>Download your motif as a position weight matrix or a custom logo.</p>
+<div style="float:right; bottom:0px;">[<a href="javascript:help()">close</a> ]</div>
+</div>
+<div class="pop_content" id="pop_motif_positives">
+<p># positive sequences matching the motif / # positive sequences.</p>
+<p>Note these counts are made after erasing sites that match previously
+        found motifs.</p>
+<div style="float:right; bottom:0px;">[<a href="javascript:help()">close</a> ]</div>
+</div>
+<div class="pop_content" id="pop_motif_negatives">
+<p># negative sequences matching the motif / # negative sequences.</p>
+<p>Note these counts are made after erasing sites that match previously
+        found motifs.</p>
+<div style="float:right; bottom:0px;">[<a href="javascript:help()">close</a> ]</div>
+</div>
+<div class="pop_content" id="pop_motif_pvalue">
+<p>The p-value of the Fisher Exact Test for enrichment of the motif in 
+        the positive sequences.</p>
+<p>Note that the counts used in the Fisher Exact Test are made after 
+        erasing sites that match previously found motifs.</p>
+<div style="float:right; bottom:0px;">[<a href="javascript:help()">close</a> ]</div>
+</div>
+<div class="pop_content" id="pop_motif_evalue">
+<p>The E-value is the motif p-value times the number of candidate motifs 
+        tested.</p>
+<p>Note that the p-value was calculated with counts made after 
+        erasing sites that match previously found motifs.</p>
+<div style="float:right; bottom:0px;">[<a href="javascript:help()">close</a> ]</div>
+</div>
+<div class="pop_content" id="pop_motif_uevalue">
+<p>The E-value of the motif calculated without erasing the sites of 
+        previously found motifs.</p>
+<div style="float:right; bottom:0px;">[<a href="javascript:help()">close</a> ]</div>
+</div>
+<div class="pop_content" id="pop_match_word">
+<p>All words matching the motif whose uncorrected p-value is less than
+        0.01.</p>
+<div style="float:right; bottom:0px;">[<a href="javascript:help()">close</a> ]</div>
+</div>
+<div class="pop_content" id="pop_match_pos">
+<p># positive sequences with matches to the word / # positive sequences.</p>
+<p>Note these counts are made after erasing sites that match previously
+        found motifs.</p>
+<div style="float:right; bottom:0px;">[<a href="javascript:help()">close</a> ]</div>
+</div>
+<div class="pop_content" id="pop_match_neg">
+<p># negative sequences with matches to the word / # negative sequences.</p>
+<p>Note these counts are made after erasing sites that match previously
+        found motifs.</p>
+<div style="float:right; bottom:0px;">[<a href="javascript:help()">close</a> ]</div>
+</div>
+<div class="pop_content" id="pop_match_pval">
+<p>The p-value of the Fisher Exact Test for enrichment of the word in 
+        the positive sequences.</p>
+<p>Note that the counts used in the Fisher Exact Test are made after 
+        erasing sites that match previously found motifs.</p>
+<div style="float:right; bottom:0px;">[<a href="javascript:help()">close</a> ]</div>
+</div>
+<div class="pop_content" id="pop_match_eval">
+<p>The word p-value times the number of candidates tested.</p>
+<p>Note that the p-value was calculated with counts made after 
+        erasing sites that match previously found motifs.</p>
+<div style="float:right; bottom:0px;">[<a href="javascript:help()">close</a> ]</div>
+</div>
+<div id="expanded_motif" style="display:none"><div class="box expanded_motif" style="margin-bottom:5px;">
+<div>
+<div style="float:left"><h2 class="mainh" style="margin:0; padding:0;">
+<span class="num"></span>.  
+              <span class="name"></span>
+</h2></div>
+<div style="float:right; "><div class="close" onclick="contract(this);" title="Show less information.">↥</div></div>
+<div style="clear:both"></div>
+</div>
+<div style="padding:0 5px;">
+<div style="float:left;">
+<img class="img_nc" onerror="fix_expanded_logo(this, false)"><img class="img_rc" onerror="fix_expanded_logo(this, true)">
+</div>
+<div style="float:right; height:100px;">
+<div onclick="send_to_popup2(this);" class="actionbutton" title="Submit this motif to another MEME Suite program.">
+<div style="float:left; margin-right:1em;">Submit</div>
+<div style="float:right">⇢</div>
+<div style="clear:both;"></div>
+</div>
+<div onclick="download_popup2(this);" class="actionbutton" title="Download this motif as a position weight matrix or a custom logo.">
+<div style="float:left; margin-right:1em;">Download</div>
+<div style="float:right">⟱</div>
+<div style="clear:both;"></div>
+</div>
+</div>
+<div style="clear:both;"></div>
+</div>
+<h4>Details</h4>
+<table class="details">
+<thead><tr>
+<th>Positives <div class="help2" onclick="help(this,'pop_motif_positives')">?</div>
+</th>
+<th>Negatives <div class="help2" onclick="help(this,'pop_motif_negatives')">?</div>
+</th>
+<th>P-value <div class="help2" onclick="help(this,'pop_motif_pvalue')">?</div>
+</th>
+<th>E-value <div class="help2" onclick="help(this,'pop_motif_evalue')">?</div>
+</th>
+<th>Unerased E-value <div class="help2" onclick="help(this,'pop_motif_uevalue')">?</div>
+</th>
+</tr></thead>
+<tbody><tr>
+<td>
+<span class="positives"></span>/3</td>
+<td>
+<span class="negatives"></span>/3</td>
+<td class="pvalue"></td>
+<td class="evalue"></td>
+<td class="uevalue"></td>
+</tr></tbody>
+</table>
+<h4>Enriched Matching Words</h4>
+<table>
+<thead><tr>
+<th>
+<a href="javascript:;" onclick="sort_table(this, compare_strings)"><span class="sort_dir"></span>Word</a> 
+                <div class="help2" onclick="help(this,'pop_match_word')">?</div>
+</th>
+<th>
+<a href="javascript:;" onclick="sort_table(this, compare_counts)"><span class="sort_dir"></span>Positives</a> 
+                <div class="help2" onclick="help(this,'pop_match_pos')">?</div>
+</th>
+<th>
+<a href="javascript:;" onclick="sort_table(this, compare_counts)"><span class="sort_dir"></span>Negatives</a> 
+                <div class="help2" onclick="help(this,'pop_match_neg')">?</div>
+</th>
+<th>
+<a href="javascript:;" onclick="sort_table(this, compare_numbers)"><span class="sort_dir"></span>P-value</a> 
+                <div class="help2" onclick="help(this,'pop_match_pval')">?</div>
+</th>
+<th>
+<a href="javascript:;" onclick="sort_table(this, compare_numbers)"><span class="sort_dir">▼</span>E-value</a> 
+                <div class="help2" onclick="help(this,'pop_match_eval')">?</div>
+</th>
+</tr></thead>
+<tbody><tr class="match">
+<td class="dnaseq"></td>
+<td>
+<span class="positives"></span>/3</td>
+<td>
+<span class="negatives"></span>/3</td>
+<td class="pvalue"></td>
+<td class="evalue"></td>
+</tr></tbody>
+</table>
+</div></div>
+<div id="grey_out_page" class="grey_background" style="display:none;"></div>
+<div class="popup_wrapper"><div id="send_to" class="popup" style="top:-150px; display:none">
+<div>
+<div style="float:left" id="send_to_title_1"><h2 class="mainh compact">Submit "<span id="send_to_name"></span>"</h2></div>
+<div style="float:left" id="send_to_title_2"><h2 class="mainh compact">Submit All Motifs</h2></div>
+<div style="float:right; "><div class="close" onclick="both_hide();">x</div></div>
+<div style="clear:both"></div>
+</div>
+<div style="padding:0 5px 5px 5px;">
+<div id="send_to_selector" style="height:100px;">
+<img id="send_to_img" height="90" style="max-width:170px;" onerror="fix_popup_logo(this, 'send_to_can', false)"><canvas id="send_to_can" width="10" height="100" style="display:none;"></canvas><img id="send_to_rcimg" height="90" style="max-width:170px;" onerror="fix_popup_logo(this, 'send_to_rccan', true);"><canvas id="send_to_rccan" width="10" height="100" style="display:none"></canvas><div style="float:right;">
+<a id="prev_arrow_2" href="javascript:both_change(-1)" class="navarrow">⇧</a><div id="pop_num_2" class="navnum"></div>
+<a id="next_arrow_2" href="javascript:both_change(1)" class="navarrow">⇩</a>
+</div>
+</div>
+<form>
+<div style="">
+<div style="float:left;">
+<h4 class="compact">Select what you want to do</h4>
+<div class="programs_scroll"><ul id="tasks" class="programs">
+<li id="search_motifs" onclick="click_submit_task(this)" class="selected">Search Motifs</li>
+<li id="search_sequences" onclick="click_submit_task(this)">Search Sequences</li>
+<li id="rank_sequences" onclick="click_submit_task(this)">Rank Sequences</li>
+<li id="predict_go" onclick="click_submit_task(this)">Predict Gene Ontology terms</li>
+<li id="infer_tf" onclick="click_submit_task(this)">Infer TF Complexes</li>
+</ul></div>
+</div>
+<div style="float:right;">
+<h4 class="compact">Select a program</h4>
+<div class="programs_scroll"><ul id="programs" class="programs">
+<li id="TOMTOM" onclick="click_submit_program(this)" class="selected">Tomtom</li>
+<li id="FIMO" onclick="click_submit_program(this)">FIMO</li>
+<li id="MAST" onclick="click_submit_program(this)">MAST</li>
+<li id="GOMO" onclick="click_submit_program(this)">GOMO</li>
+<li id="SPAMO" onclick="click_submit_program(this)">SpaMo</li>
+</ul></div>
+</div>
+<div style="font-weight:bold; display:inline-block; text-align:center; width:60px; height:100px; line-height:100px">Or</div>
+<div style="clear:both;"></div>
+</div>
+<h4>
+<span id="program_action">Search Motifs</span> with <span id="program_name">Tomtom</span>
+</h4>
+<p><span id="program_desc">Find similar motifs in published 
+                libraries or a library you supply.</span></p>
+<div style="margin-top:10px; height: 2em;">
+<div style="float:left;"><input type="button" value="Send" onclick="javascript:send_to_submit()"></div>
+<div style="float:right;"><input type="button" value="Cancel" onclick="javascript:both_hide()"></div>
+</div>
+</form>
+</div>
+</div></div>
+<div class="popup_wrapper"><div id="download" class="popup" style="top:-150px; display:none">
+<div>
+<div style="float:left"><h2 class="mainh" style="margin:0; padding:0;">Download "<span id="download_name"></span>"</h2></div>
+<div style="float:right; "><div class="close" onclick="both_hide();">x</div></div>
+<div style="clear:both"></div>
+</div>
+<div style="padding:0 5px 5px 5px;">
+<div style="height:100px">
+<img id="download_img" height="90" style="max-width:170px;" onerror="fix_popup_logo(this, 'download_can', false)"><canvas id="download_can" width="10" height="100" style="display:none;"></canvas><img id="download_rcimg" height="90" style="max-width:170px;" onerror="fix_popup_logo(this, 'download_rccan', true)"><canvas id="download_rccan" width="10" height="100" style="display:none;"></canvas><div style="float:right;">
+<a id="prev_arrow_1" href="javascript:both_change(-1)" class="navarrow">⇧</a><div id="pop_num_1" class="navnum"></div>
+<a id="next_arrow_1" href="javascript:both_change(1)" class="navarrow">⇩</a>
+</div>
+</div>
+<form>
+<input type="hidden" id="download_tab_num" value="1"><div style="padding:5px 0;">
+<div class="tabArea top">
+<a id="download_tab_1" href="javascript:click_download_tab(1)" class="tab activeTab">PSPM Format</a><a id="download_tab_2" href="javascript:click_download_tab(2)" class="tab">PSSM Format</a><a id="download_tab_3" href="javascript:click_download_tab(3)" class="tab">Logo</a>
+</div>
+<div class="tabMain">
+<div id="download_pnl_1"><textarea id="download_pspm" style="width:99%" rows="10" readonly></textarea></div>
+<div id="download_pnl_2"><textarea id="download_pssm" style="width:99%" rows="10" readonly></textarea></div>
+<div id="download_pnl_3"><table>
+<tr>
+<td><label for="logo_format">Format:</label></td>
+<td><select id="logo_format"><option value="png">PNG (for web)</option>
+<option value="eps">EPS (for publication)</option></select></td>
+</tr>
+<tr>
+<td><label for="logo_rc">Orientation:</label></td>
+<td><select id="logo_rc"><option value="false">Normal</option>
+<option value="true">Reverse Complement</option></select></td>
+</tr>
+<tr>
+<td><label for="logo_ssc">Small Sample Correction:</label></td>
+<td><select id="logo_ssc"><option value="false">Off</option>
+<option value="true">On</option></select></td>
+</tr>
+<tr>
+<td><label for="logo_width">Width:</label></td>
+<td>
+<input type="text" id="logo_width" size="4"> cm
+                      </td>
+</tr>
+<tr>
+<td><label for="logo_height">Height:</label></td>
+<td>
+<input type="text" id="logo_height" size="4"> cm
+                      </td>
+</tr>
+</table></div>
+<div style="margin-top:10px;">
+<div style="float:left;"><input type="button" id="download_button" value="Download" style="visibility:hidden;" onclick="javascript:download_submit()"></div>
+<div style="float:right;"><input type="button" value="Cancel" onclick="javascript:both_hide()"></div>
+<div style="clear:both;"></div>
+</div>
+</div>
+</div>
+</form>
+</div>
+</div></div>
+<a name="top"></a><div class="pad1">
+<h1><img src="http://Sharplab-G4-1.local/meme/doc/images/dreme_logo.png" alt="Discriminative Regular Expression Motif Elicitation (DREME)"></h1>
+<p class="spaced">
+        For further information on how to interpret these results or to get a 
+        copy of the MEME software please access 
+        <a href="http://meme.nbcr.net/">http://meme.nbcr.net</a>. 
+      </p>
+<p>
+        If you use DREME in your research please cite the following paper:<br><span class="citation">
+          Timothy L. Bailey, "DREME: Motif discovery in transcription factor ChIP-seq data", <i>Bioinformatics</i>, <b>27</b>(12):1653-1659, 2011.
+        </span></p>
+</div>
+<div class="pad2">
+<a class="jump" href="#description">Description</a>  |  <a class="jump" href="#motifs">Discovered motifs</a>  |  <a class="jump" href="#program">Program information</a>
+</div>
+<a name="description"></a><table width="100%" border="0" cellspacing="1" cellpadding="4" bgcolor="#FFFFFF"><tr>
+<td><h2 class="mainh">Description</h2></td>
+<td align="right" valign="bottom">
+<a href="#motifs">Next</a> <a href="#top">Top</a>
+</td>
+</tr></table>
+<div class="box"><p>xxxx</p></div>
+<a name="motifs"></a><table width="100%" border="0" cellspacing="1" cellpadding="4" bgcolor="#FFFFFF"><tr>
+<td><h2 class="mainh">Discovered Motifs</h2></td>
+<td align="right" valign="bottom">
+<a href="#description">Previous</a> <a href="#program">Next</a> <a href="#top">Top</a>
+</td>
+</tr></table>
+<div class="box">
+<p><b>Click on the ↧</b> under the <b>More</b> column to show more 
+        information about the motif.<br><b>Click on the ⇢</b> under the <b>Submit</b> column to send the 
+        motif to another MEME suite program. Eg. Tomtom<br><b>Click on the ⟱</b> under the <b>Download</b> column to get 
+        the position weight matrix of a motif or to download the logo image with
+        your chosen options.
+      </p>
+<table id="dreme_motifs" class="dreme_motifs">
+<thead><tr class="motif_head">
+<td> </td>
+<th>Motif <div class="help2" onclick="help(this,'pop_motifs_name')">?</div>
+</th>
+<th>Logo <div class="help2" onclick="help(this,'pop_motifs_logo')">?</div>
+</th>
+<th>RC Logo <div class="help2" onclick="help(this,'pop_motifs_rc_logo')">?</div>
+</th>
+<th>E-value <div class="help2" onclick="help(this,'pop_motifs_evalue')">?</div>
+</th>
+<th>Unerased E-value <div class="help2" onclick="help(this,'pop_motifs_uevalue')">?</div>
+</th>
+<th>More <div class="help2" onclick="help(this,'pop_more')">?</div>
+</th>
+<th>Submit <div class="help2" onclick="help(this,'pop_submit')">?</div>
+</th>
+<th>Download <div class="help2" onclick="help(this,'pop_download')">?</div>
+</th>
+</tr></thead>
+<tbody></tbody>
+<tfoot><tr class="rule">
+<td> </td>
+<td> </td>
+<td> </td>
+<td> </td>
+<td> </td>
+<td> </td>
+<td> </td>
+<td> </td>
+<td> </td>
+</tr></tfoot>
+</table>
+<div style="float:left"><div onclick="send_to_popup(0);" class="actionbutton" title="Submit all motifs to another program.">
+<div style="float:left; margin-right:1em;">Submit All</div>
+<div style="float:right">⇢</div>
+<div style="clear:both;"></div>
+</div></div>
+<div style="clear:both;"></div>
+</div>
+<a name="program"></a><div class="bar">
+<div style="text-align:right;">
+<a href="#motifs">Previous</a> <a href="#top">Top</a>
+</div>
+<div class="subsection">
+<a name="version"></a><h5>DREME version</h5>4.7.0 (Release date: Wed Sep 28 17:30:10 EST 2011)
+      </div>
+<div class="subsection">
+<a name="reference"></a><h5>Reference</h5>
+<span class="citation">
+          Timothy L. Bailey, "DREME: Motif discovery in transcription factor ChIP-seq data", <i>Bioinformatics</i>, <b>27</b>(12):1653-1659, 2011.
+        </span>
+</div>
+<div class="subsection">
+<a name="command"></a><h5>Command line summary</h5>
+<textarea rows="1" style="width:100%;" readonly>dreme -p test.fa -desc xxxx</textarea><br>Result calculation took 0.01 seconds<br>
+</div>
+<a href="javascript:show_hidden('model')" id="model_activator">show model parameters...</a><div class="subsection" id="model_data" style="display:none;">
+<h5>Model parameters</h5>
+<textarea style="width:100%;" rows="10" readonly>
+positives             = name: "test", count: "3", file: "test.fa", last_mod_date: "Sat Dec 10 12:52:18 EST 2011"
+negatives             = name: "shuffled positive sequences", count: "3", from: "shuffled"
+background            = type: "dna", A: "0.243", C: "0.270", G: "0.243", T: "0.243", from: "dataset"
+stop                  = evalue: "0.05"
+ngen                  = 100
+add_pv_thresh         = 0.01
+seed                  = 1
+host                  = SHARPLAB.MIT.EDU
+when                  = Sun Dec 11 09:26:43 EST 2011
+</textarea>
+</div>
+<a href="javascript:hide_shown('model')" style="display:none;" id="model_deactivator">hide model parameters...</a>
+</div>
+</body>
+</html>