view 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 source

<!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>