changeset 20:613c75eee7bd draft default tip

planemo upload for repository https://github.com/galaxyproject/tools-iuc/tree/master/tools/meme commit 89ee0af6e955ff964b7984d77ad536e0a9154278
author iuc
date Mon, 14 Jul 2025 21:33:56 +0000
parents 01f5d04846c4
children
files macros.xml test-data/alphabet.txt test-data/meme_input_m.fasta test-data/meme_output_custom.html test-data/meme_output_custom.txt test-data/meme_output_custom.xml test-data/meme_output_test1.html test-data/meme_output_test1.txt test-data/meme_output_test1.xml test-data/meme_output_test2.html test-data/meme_output_test2.txt test-data/meme_output_test2.xml test-data/streme_input_neg2.fasta test-data/streme_input_pos.fasta test-data/streme_input_pos2.fasta test-data/streme_output_test1.html test-data/streme_output_test1.txt test-data/streme_output_test1.xml test-data/streme_output_test2.html test-data/streme_output_test2.txt test-data/streme_output_test2.xml test-data/streme_output_test3.html test-data/streme_output_test3.txt test-data/streme_output_test3.xml
diffstat 24 files changed, 13648 insertions(+), 140 deletions(-) [+]
line wrap: on
line diff
--- a/macros.xml	Thu Aug 29 10:19:40 2024 +0000
+++ b/macros.xml	Mon Jul 14 21:33:56 2025 +0000
@@ -1,6 +1,6 @@
 <macros>
     <token name="@VERSION_SUFFIX@">0</token>
-    <token name="@TOOL_VERSION@">5.5.6</token>
+    <token name="@TOOL_VERSION@">5.5.8</token>
     <token name="@PROFILE@">23.0</token>
     <xml name="requirements">
         <requirements>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test-data/alphabet.txt	Mon Jul 14 21:33:56 2025 +0000
@@ -0,0 +1,13 @@
+ALPHABET "DNA with covalent modifications" DNA-LIKE
+
+# Core uppercase symbols
+A "Adenine" 8510A8 ~ T "Thymine" A89610
+C "Cytosine" A50026 ~ G "Guanine" 313695
+
+# Covalent modifications
+m "5-Methylcytosine" D73027 ~ 1 "Guanine:5-Methylcytosine" 4575B4
+h "5-Hydroxymethylcytosine" F46D43 ~ 2 "Guanine:5-Hydroxymethylcytosine" 74ADD1
+f "5-Formylcytosine" FDAE61 ~ 3 "Guanine:5-Formylcytosine" ABD9E9
+c "5-Carboxylcytosine" FEE090 ~ 4 "Guanine:5-Carboxylcytosine" E0F3F8
+a "N6-methyladenine" 8510A8 ~ t "Thymine_lowercase" 756BB1
+g "modified_g" 00897B ~ 5 "cytosine_lowercase" 53698A
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test-data/meme_input_m.fasta	Mon Jul 14 21:33:56 2025 +0000
@@ -0,0 +1,66 @@
+>chr21_19617074_19617124_+
+AAAAATTATTACTAGGGAGGGGGCCGGAACCTCGGGACGTGGGTATATAA
+>chr21_26934381_26934431_+
+GCGCCTGGTCGGTTATGAGTCACAAGTGAGTTATAAAAGGGTCGCACGTT
+>chr21_28217753_28217803_-
+CAAAGGGGAGGAGTGGGGTGGGGGTGGGGGTTTCACTGGTmCACTATAAA
+>chr21_31710037_31710087_-
+AACACCCAGGTTTCTGAGTATATAATCGCCGCACCAAAGAATTTAATTTT
+>chr21_31744582_31744632_-
+CCmAGGTCTAAGAGCATATATAACTTGGAGTCCAGACTATGACATTCAAA
+>chr21_31768316_31768366_+
+AACGTATATAAATGGTCCTGTCCAGATGTGGCATGCAAACTmAGAATCTT
+>chr21_31914206_31914256_-
+TGACACCCACTACTTAGAGTATAAAATCATTCTGAGAAGTTAGAGACACC
+>chr21_31933633_31933683_-
+TCAGAGTATATATAAATGTTCCTGTCCAGTCACAGTCACCAAACTGACCT
+>chr21_31962741_31962791_-
+ACATATAACTCAGGTTGGATAAAATAATTTGTACAAATCAGGAGAGTCAA
+>chr21_31964683_31964733_+
+TCTGATTCACTGAGGCATATAAAAGGCCCTCTGCGGAGAAGTGTCCATAC
+>chr21_31973364_31973414_+
+aaacttaaaactctataaacttaaaactCTAGAATCTGATCCTGCTATAC
+>chr21_31992870_31992920_+
+CTCATACACTATTGAAGATGTATAAAATTTCATTTGCAGATGGTGACATT
+>chr21_32185595_32185645_-
+TCACCACCCACCAGAGCTGGGATATATAAAGAAGGTTCTGAGACTAGGAA
+>chr21_32202076_32202126_-
+TGCCCACCAGCTTGAGGTATAAAAAGCCCTGTACGGGAAGAGACCTTCAT
+>chr21_32253899_32253949_-
+AGCCCCACCCACCAGCAAGGATATATAAAAGCTCAGGAGTCTGGAGTGAC
+>chr21_32410820_32410870_-
+TCTACCCCACTAATCACTGAGGATGTATAAAAGTCCCAGGGAAGCTGGTG
+>chr21_36411748_36411798_-
+ATAGTTCTGTATAGTTTCAGTTGGCATCtaaaaattatataactttattt
+>chr21_37838750_37838800_-
+gatggttttataaggggcctcaccctcggctcagccctcattcttctcct
+>chr21_45705687_45705737_+
+CCGGGGCGGAGCGGCCTTTGCTCTTTGCGTGGTCGCGGGGGTATAACAGC
+>chr21_45971413_45971463_-
+CAGGCCCTGGGCATATAAAAGCCCCAGCAGCCAACAGGctcacacacaca
+>chr21_45978668_45978718_-
+CAGAGGGGTATAAAGGTTCCGACCACTCAGAGGCCTGGCACGAtcactca
+>chr21_45993530_45993580_+
+CCAAGGAGGAGTATAAAAGCCCCACAAACCCGAGCACCTCACTCACTCGC
+>chr21_46020421_46020471_+
+GAGACATATAAAAGCCAACATCCCTGAGCACCTAACACACGGactcactc
+>chr21_46031920_46031970_+
+GGAAAATACCCAGGGAGGGTATAAAACCTCAGCAGCCAGGGCACACAAAC
+>chr21_46046964_46047014_+
+ACAAGGCCAGGAGGGGTATAAAAGCCTGAGAGCCCCAAGAACctcacaca
+>chr21_46057197_46057247_+
+ATTGCTGAGTCTCCTGCTGGGAAAACACAGGCCCTGGGCATATAAAAGCC
+>chr21_46086869_46086919_-
+GACAGGTGTGCTTCTGTGCTGTGGGGATGCCTGGGCCCAGGTATAAAGGC
+>chr21_46102103_46102153_-
+AGGTGTGTGCTTCTGTGCTGTGGGGATGCCTGGGTCCAGGTATAAAGGCT
+>chr21_47517957_47518007_+
+CCTGGCGGCGGGGCGGGTCAGGCCGGCGGGGCGGGGTATAAAGGGGGmGG
+>chr21_47517957_47518007_+
+CCTGGCGGCGGGGCGGGTCAGGCCGGCGGGGCGGGGTATAAAGGGGGCGG
+>chr21_47517957_47518007_+
+CCTGGCGGCGGGGCGGGTCAGGCCGGCGGGGCGGGGTATAAAGGGGGCGG
+>chr21_47575506_47575556_-
+TGAGAAGCCGGTGGGGAGGTGmTGCCGGTGAGCGTATAAAGGCCCTGGCG
+>chr21_47575506_47575556_-
+TGAGAAGCmGGTGGGGAGGTGCTGCCGGTGAGCGTATAAAGGCCCTGGCG
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test-data/meme_output_custom.html	Mon Jul 14 21:33:56 2025 +0000
@@ -0,0 +1,276 @@
+        "options": {
+          "mod": "zoops",
+          "revcomp": false,
+          "nmotifs": 1,
+          "objfun": "E-value of product of p-values",
+          "spfun": "E-value of product of p-values",
+          "minw": 8,
+          "maxw": 50,
+          "minsites": 2,
+          "maxsites": 30,
+          "wnsites": 0.8,
+          "spmap": "uni",
+          "spfuzz": 0.5,
+          "searchsize": 1500,
+          "maxsize": 1000000,
+          "norand": "no",
+          "csites": 1000,
+          "hsfrac": 0,
+          "prior": "dirichlet",
+          "b": 0.01,
+          "maxiter": 50,
+          "distance": 0.001,
+          "wg": 11,
+          "ws": 1,
+          "noendgaps": false,
+          "substring": true,
+          "seed": 0,
+          "brief": 1000
+        },
+        "alphabet": {
+          "name": "DNA with covalent modifications",
+          "like": "dna",
+          "ncore": 16,
+          "symbols": [
+            {
+              "symbol": "A",
+              "name": "Adenine",
+              "colour": "8510A8",
+              "complement": "T"
+            }, {
+              "symbol": "C",
+              "name": "Cytosine",
+              "colour": "A50026",
+              "complement": "G"
+            }, {
+              "symbol": "G",
+              "name": "Guanine",
+              "colour": "313695",
+              "complement": "C"
+            }, {
+              "symbol": "T",
+              "name": "Thymine",
+              "colour": "A89610",
+              "complement": "A"
+            }, {
+              "symbol": "a",
+              "name": "N6-methyladenine",
+              "colour": "8510A8",
+              "complement": "t"
+            }, {
+              "symbol": "c",
+              "name": "5-Carboxylcytosine",
+              "colour": "FEE090",
+              "complement": "4"
+            }, {
+              "symbol": "f",
+              "name": "5-Formylcytosine",
+              "colour": "FDAE61",
+              "complement": "3"
+            }, {
+              "symbol": "g",
+              "name": "modified_g",
+              "colour": "00897B",
+              "complement": "5"
+            }, {
+              "symbol": "h",
+              "name": "5-Hydroxymethylcytosine",
+              "colour": "F46D43",
+              "complement": "2"
+            }, {
+              "symbol": "m",
+              "name": "5-Methylcytosine",
+              "colour": "D73027",
+              "complement": "1"
+            }, {
+              "symbol": "t",
+              "name": "Thymine_lowercase",
+              "colour": "756BB1",
+              "complement": "a"
+            }, {
+              "symbol": "1",
+              "name": "Guanine:5-Methylcytosine",
+              "colour": "4575B4",
+              "complement": "m"
+            }, {
+              "symbol": "2",
+              "name": "Guanine:5-Hydroxymethylcytosine",
+              "colour": "74ADD1",
+              "complement": "h"
+            }, {
+              "symbol": "3",
+              "name": "Guanine:5-Formylcytosine",
+              "colour": "ABD9E9",
+              "complement": "f"
+            }, {
+              "symbol": "4",
+              "name": "Guanine:5-Carboxylcytosine",
+              "colour": "E0F3F8",
+              "complement": "c"
+            }, {
+              "symbol": "5",
+              "name": "cytosine_lowercase",
+              "colour": "53698A",
+              "complement": "g"
+            }, {
+              "symbol": "?",
+              "equals": "ACGTacfghmt12345"
+            }
+          ]
+        },
+        "background": {
+          "source": "--sequences--",
+          "order": 0,
+          "freqs": [
+            0.263, 0.2, 0.249, 0.189, 0.0297, 0.027, 0.00066, 0.00726,
+            0.00066, 0.00396, 0.0277, 0.00066, 0.00066, 0.00066, 0.00066,
+            0.00066
+          ]
+        },
+        "sequence_db": {
+          "primary_source": "Galaxy_FASTA_Input",
+          "primary_count": 30,
+          "primary_positions": 1500,
+          "control_source": "--none--",
+          "control_count": 0,
+          "control_positions": 0,
+          "freqs": [
+            0.265, 0.201, 0.251, 0.19, 0.0293, 0.0267, 0, 0.00667, 0, 0.00333,
+            0.0273, 0, 0, 0, 0, 0
+          ],
+          "sequences": [
+            {
+              "name": "chr21_19617074_19617124_+",
+              "length": 50,
+              "weight": 1.000000
+            }, {
+              "name": "chr21_26934381_26934431_+",
+              "length": 50,
+              "weight": 1.000000
+            }, {
+              "name": "chr21_28217753_28217803_-",
+              "length": 50,
+              "weight": 1.000000
+            }, {
+              "name": "chr21_31710037_31710087_-",
+              "length": 50,
+              "weight": 1.000000
+            }, {
+              "name": "chr21_31744582_31744632_-",
+              "length": 50,
+              "weight": 1.000000
+            }, {
+              "name": "chr21_31768316_31768366_+",
+              "length": 50,
+              "weight": 1.000000
+            }, {
+              "name": "chr21_31914206_31914256_-",
+              "length": 50,
+              "weight": 1.000000
+            }, {
+              "name": "chr21_31933633_31933683_-",
+              "length": 50,
+              "weight": 1.000000
+            }, {
+              "name": "chr21_31962741_31962791_-",
+              "length": 50,
+              "weight": 1.000000
+            }, {
+              "name": "chr21_31964683_31964733_+",
+              "length": 50,
+              "weight": 1.000000
+            }, {
+              "name": "chr21_31973364_31973414_+",
+              "length": 50,
+              "weight": 1.000000
+            }, {
+              "name": "chr21_31992870_31992920_+",
+              "length": 50,
+              "weight": 1.000000
+            }, {
+              "name": "chr21_32185595_32185645_-",
+              "length": 50,
+              "weight": 1.000000
+            }, {
+              "name": "chr21_32202076_32202126_-",
+              "length": 50,
+              "weight": 1.000000
+            }, {
+              "name": "chr21_32253899_32253949_-",
+              "length": 50,
+              "weight": 1.000000
+            }, {
+              "name": "chr21_32410820_32410870_-",
+              "length": 50,
+              "weight": 1.000000
+            }, {
+              "name": "chr21_36411748_36411798_-",
+              "length": 50,
+              "weight": 1.000000
+            }, {
+              "name": "chr21_37838750_37838800_-",
+              "length": 50,
+              "weight": 1.000000
+            }, {
+              "name": "chr21_45705687_45705737_+",
+              "length": 50,
+              "weight": 1.000000
+            }, {
+              "name": "chr21_45971413_45971463_-",
+              "length": 50,
+              "weight": 1.000000
+            }, {
+              "name": "chr21_45978668_45978718_-",
+              "length": 50,
+              "weight": 1.000000
+            }, {
+              "name": "chr21_45993530_45993580_+",
+              "length": 50,
+              "weight": 1.000000
+            }, {
+              "name": "chr21_46020421_46020471_+",
+              "length": 50,
+              "weight": 1.000000
+            }, {
+              "name": "chr21_46031920_46031970_+",
+              "length": 50,
+              "weight": 1.000000
+            }, {
+              "name": "chr21_46046964_46047014_+",
+              "length": 50,
+              "weight": 1.000000
+            }, {
+              "name": "chr21_46057197_46057247_+",
+              "length": 50,
+              "weight": 1.000000
+            }, {
+              "name": "chr21_46086869_46086919_-",
+              "length": 50,
+              "weight": 1.000000
+            }, {
+              "name": "chr21_46102103_46102153_-",
+              "length": 50,
+              "weight": 1.000000
+            }, {
+              "name": "chr21_47517957_47518007_+",
+              "length": 50,
+              "weight": 1.000000
+            }, {
+              "name": "chr21_47575506_47575556_-",
+              "length": 50,
+              "weight": 1.000000
+            }
+          ]
+        },
+        "motifs": [
+          {
+            "db": 0,
+            "id": "taCaaACAGtataactctcac",
+            "alt": "MEME-1",
+            "len": 21,
+            "nsites": 5,
+            "evalue": "4.6e-028",
+            "ic": 55.7,
+            "re": 68.0,
+            "llr": 236,
+            "bt": 7.73664,
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test-data/meme_output_custom.txt	Mon Jul 14 21:33:56 2025 +0000
@@ -0,0 +1,61 @@
+********************************************************************************
+MEME - Motif discovery tool
+********************************************************************************
+MEME version 5.5.8 (Release date: Thu May 15 15:01:46 2025 -0700)
+
+For further information on how to interpret these results please access https://meme-suite.org/meme.
+To get a copy of the MEME Suite software please access https://meme-suite.org.
+
+********************************************************************************
+
+
+********************************************************************************
+REFERENCE
+********************************************************************************
+If you use this program in your research, please cite:
+
+Timothy L. Bailey and Charles Elkan,
+"Fitting a mixture model by expectation maximization to
+discover motifs in biopolymers",
+Proceedings of the Second International Conference on Intelligent Systems
+for Molecular Biology, pp. 28-36, AAAI Press, Menlo Park, California, 1994.
+********************************************************************************
+
+
+********************************************************************************
+ALPHABET "DNA with covalent modifications" DNA-LIKE
+********************************************************************************
+A "Adenine" 8510A8 ~ T "Thymine" A89610
+C "Cytosine" A50026 ~ G "Guanine" 313695
+a "N6-methyladenine" 8510A8 ~ t "Thymine_lowercase" 756BB1
+c "5-Carboxylcytosine" FEE090 ~ 4 "Guanine:5-Carboxylcytosine" E0F3F8
+f "5-Formylcytosine" FDAE61 ~ 3 "Guanine:5-Formylcytosine" ABD9E9
+g "modified_g" 00897B ~ 5 "cytosine_lowercase" 53698A
+h "5-Hydroxymethylcytosine" F46D43 ~ 2 "Guanine:5-Hydroxymethylcytosine" 74ADD1
+m "5-Methylcytosine" D73027 ~ 1 "Guanine:5-Methylcytosine" 4575B4
+? = ACGTacfghmt12345
+********************************************************************************
+
+********************************************************************************
+TRAINING SET
+********************************************************************************
+PRIMARY SEQUENCES= Galaxy_FASTA_Input
+CONTROL SEQUENCES= --none--
+Sequence name            Weight Length  Sequence name            Weight Length  
+-------------            ------ ------  -------------            ------ ------  
+chr21_19617074_19617124_ 1.0000     50  chr21_26934381_26934431_ 1.0000     50  
+chr21_28217753_28217803_ 1.0000     50  chr21_31710037_31710087_ 1.0000     50  
+chr21_31744582_31744632_ 1.0000     50  chr21_31768316_31768366_ 1.0000     50  
+chr21_31914206_31914256_ 1.0000     50  chr21_31933633_31933683_ 1.0000     50  
+chr21_31962741_31962791_ 1.0000     50  chr21_31964683_31964733_ 1.0000     50  
+chr21_31973364_31973414_ 1.0000     50  chr21_31992870_31992920_ 1.0000     50  
+chr21_32185595_32185645_ 1.0000     50  chr21_32202076_32202126_ 1.0000     50  
+chr21_32253899_32253949_ 1.0000     50  chr21_32410820_32410870_ 1.0000     50  
+chr21_36411748_36411798_ 1.0000     50  chr21_37838750_37838800_ 1.0000     50  
+chr21_45705687_45705737_ 1.0000     50  chr21_45971413_45971463_ 1.0000     50  
+chr21_45978668_45978718_ 1.0000     50  chr21_45993530_45993580_ 1.0000     50  
+chr21_46020421_46020471_ 1.0000     50  chr21_46031920_46031970_ 1.0000     50  
+chr21_46046964_46047014_ 1.0000     50  chr21_46057197_46057247_ 1.0000     50  
+chr21_46086869_46086919_ 1.0000     50  chr21_46102103_46102153_ 1.0000     50  
+chr21_47517957_47518007_ 1.0000     50  chr21_47575506_47575556_ 1.0000     50  
+********************************************************************************
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test-data/meme_output_custom.xml	Mon Jul 14 21:33:56 2025 +0000
@@ -0,0 +1,946 @@
+<alphabet_matrix>
+<alphabet_array>
+<value letter_id="A">61</value>
+<value letter_id="C">-897</value>
+<value letter_id="G">-897</value>
+<value letter_id="T">-897</value>
+<value letter_id="a">-897</value>
+<value letter_id="c">-897</value>
+<value letter_id="f">-897</value>
+<value letter_id="g">-897</value>
+<value letter_id="h">-897</value>
+<value letter_id="m">-897</value>
+<value letter_id="t">443</value>
+<value letter_id="n1">-897</value>
+<value letter_id="n2">-897</value>
+<value letter_id="n3">-897</value>
+<value letter_id="n4">-897</value>
+<value letter_id="n5">-897</value>
+</alphabet_array>
+<alphabet_array>
+<value letter_id="A">-897</value>
+<value letter_id="C">0</value>
+<value letter_id="G">-31</value>
+<value letter_id="T">-897</value>
+<value letter_id="a">375</value>
+<value letter_id="c">-897</value>
+<value letter_id="f">-897</value>
+<value letter_id="g">-897</value>
+<value letter_id="h">-897</value>
+<value letter_id="m">-897</value>
+<value letter_id="t">285</value>
+<value letter_id="n1">-897</value>
+<value letter_id="n2">-897</value>
+<value letter_id="n3">-897</value>
+<value letter_id="n4">-897</value>
+<value letter_id="n5">-897</value>
+</alphabet_array>
+<alphabet_array>
+<value letter_id="A">-897</value>
+<value letter_id="C">100</value>
+<value letter_id="G">-897</value>
+<value letter_id="T">-897</value>
+<value letter_id="a">375</value>
+<value letter_id="c">-897</value>
+<value letter_id="f">-897</value>
+<value letter_id="g">-897</value>
+<value letter_id="h">-897</value>
+<value letter_id="m">-897</value>
+<value letter_id="t">285</value>
+<value letter_id="n1">-897</value>
+<value letter_id="n2">-897</value>
+<value letter_id="n3">-897</value>
+<value letter_id="n4">-897</value>
+<value letter_id="n5">-897</value>
+</alphabet_array>
+<alphabet_array>
+<value letter_id="A">-897</value>
+<value letter_id="C">0</value>
+<value letter_id="G">-897</value>
+<value letter_id="T">8</value>
+<value letter_id="a">433</value>
+<value letter_id="c">-897</value>
+<value letter_id="f">-897</value>
+<value letter_id="g">-897</value>
+<value letter_id="h">-897</value>
+<value letter_id="m">-897</value>
+<value letter_id="t">-897</value>
+<value letter_id="n1">-897</value>
+<value letter_id="n2">-897</value>
+<value letter_id="n3">-897</value>
+<value letter_id="n4">-897</value>
+<value letter_id="n5">-897</value>
+</alphabet_array>
+<alphabet_array>
+<value letter_id="A">61</value>
+<value letter_id="C">-897</value>
+<value letter_id="G">-897</value>
+<value letter_id="T">-897</value>
+<value letter_id="a">433</value>
+<value letter_id="c">-897</value>
+<value letter_id="f">-897</value>
+<value letter_id="g">-897</value>
+<value letter_id="h">-897</value>
+<value letter_id="m">-897</value>
+<value letter_id="t">-897</value>
+<value letter_id="n1">-897</value>
+<value letter_id="n2">-897</value>
+<value letter_id="n3">-897</value>
+<value letter_id="n4">-897</value>
+<value letter_id="n5">-897</value>
+</alphabet_array>
+<alphabet_array>
+<value letter_id="A">61</value>
+<value letter_id="C">-897</value>
+<value letter_id="G">-897</value>
+<value letter_id="T">-897</value>
+<value letter_id="a">375</value>
+<value letter_id="c">-897</value>
+<value letter_id="f">-897</value>
+<value letter_id="g">478</value>
+<value letter_id="h">-897</value>
+<value letter_id="m">-897</value>
+<value letter_id="t">-897</value>
+<value letter_id="n1">-897</value>
+<value letter_id="n2">-897</value>
+<value letter_id="n3">-897</value>
+<value letter_id="n4">-897</value>
+<value letter_id="n5">-897</value>
+</alphabet_array>
+<alphabet_array>
+<value letter_id="A">-897</value>
+<value letter_id="C">100</value>
+<value letter_id="G">-897</value>
+<value letter_id="T">-897</value>
+<value letter_id="a">-897</value>
+<value letter_id="c">288</value>
+<value letter_id="f">-897</value>
+<value letter_id="g">478</value>
+<value letter_id="h">-897</value>
+<value letter_id="m">-897</value>
+<value letter_id="t">285</value>
+<value letter_id="n1">-897</value>
+<value letter_id="n2">-897</value>
+<value letter_id="n3">-897</value>
+<value letter_id="n4">-897</value>
+<value letter_id="n5">-897</value>
+</alphabet_array>
+<alphabet_array>
+<value letter_id="A">61</value>
+<value letter_id="C">-897</value>
+<value letter_id="G">-897</value>
+<value letter_id="T">-897</value>
+<value letter_id="a">-897</value>
+<value letter_id="c">-897</value>
+<value letter_id="f">-897</value>
+<value letter_id="g">478</value>
+<value letter_id="h">-897</value>
+<value letter_id="m">-897</value>
+<value letter_id="t">385</value>
+<value letter_id="n1">-897</value>
+<value letter_id="n2">-897</value>
+<value letter_id="n3">-897</value>
+<value letter_id="n4">-897</value>
+<value letter_id="n5">-897</value>
+</alphabet_array>
+<alphabet_array>
+<value letter_id="A">-897</value>
+<value letter_id="C">0</value>
+<value letter_id="G">-31</value>
+<value letter_id="T">-897</value>
+<value letter_id="a">275</value>
+<value letter_id="c">288</value>
+<value letter_id="f">-897</value>
+<value letter_id="g">478</value>
+<value letter_id="h">-897</value>
+<value letter_id="m">-897</value>
+<value letter_id="t">-897</value>
+<value letter_id="n1">-897</value>
+<value letter_id="n2">-897</value>
+<value letter_id="n3">-897</value>
+<value letter_id="n4">-897</value>
+<value letter_id="n5">-897</value>
+</alphabet_array>
+<alphabet_array>
+<value letter_id="A">-39</value>
+<value letter_id="C">-897</value>
+<value letter_id="G">-31</value>
+<value letter_id="T">-897</value>
+<value letter_id="a">-897</value>
+<value letter_id="c">288</value>
+<value letter_id="f">-897</value>
+<value letter_id="g">-897</value>
+<value letter_id="h">-897</value>
+<value letter_id="m">-897</value>
+<value letter_id="t">385</value>
+<value letter_id="n1">-897</value>
+<value letter_id="n2">-897</value>
+<value letter_id="n3">-897</value>
+<value letter_id="n4">-897</value>
+<value letter_id="n5">-897</value>
+</alphabet_array>
+<alphabet_array>
+<value letter_id="A">-897</value>
+<value letter_id="C">0</value>
+<value letter_id="G">-897</value>
+<value letter_id="T">-897</value>
+<value letter_id="a">375</value>
+<value letter_id="c">388</value>
+<value letter_id="f">-897</value>
+<value letter_id="g">-897</value>
+<value letter_id="h">-897</value>
+<value letter_id="m">-897</value>
+<value letter_id="t">-897</value>
+<value letter_id="n1">-897</value>
+<value letter_id="n2">-897</value>
+<value letter_id="n3">-897</value>
+<value letter_id="n4">-897</value>
+<value letter_id="n5">-897</value>
+</alphabet_array>
+<alphabet_array>
+<value letter_id="A">-897</value>
+<value letter_id="C">-897</value>
+<value letter_id="G">-31</value>
+<value letter_id="T">-897</value>
+<value letter_id="a">-897</value>
+<value letter_id="c">-897</value>
+<value letter_id="f">-897</value>
+<value letter_id="g">-897</value>
+<value letter_id="h">-897</value>
+<value letter_id="m">-897</value>
+<value letter_id="t">485</value>
+<value letter_id="n1">-897</value>
+<value letter_id="n2">-897</value>
+<value letter_id="n3">-897</value>
+<value letter_id="n4">-897</value>
+<value letter_id="n5">-897</value>
+</alphabet_array>
+<alphabet_array>
+<value letter_id="A">-897</value>
+<value letter_id="C">-897</value>
+<value letter_id="G">-31</value>
+<value letter_id="T">-897</value>
+<value letter_id="a">375</value>
+<value letter_id="c">388</value>
+<value letter_id="f">-897</value>
+<value letter_id="g">-897</value>
+<value letter_id="h">-897</value>
+<value letter_id="m">-897</value>
+<value letter_id="t">-897</value>
+<value letter_id="n1">-897</value>
+<value letter_id="n2">-897</value>
+<value letter_id="n3">-897</value>
+<value letter_id="n4">-897</value>
+<value letter_id="n5">-897</value>
+</alphabet_array>
+<alphabet_array>
+<value letter_id="A">-897</value>
+<value letter_id="C">-897</value>
+<value letter_id="G">-897</value>
+<value letter_id="T">-897</value>
+<value letter_id="a">507</value>
+<value letter_id="c">-897</value>
+<value letter_id="f">-897</value>
+<value letter_id="g">-897</value>
+<value letter_id="h">-897</value>
+<value letter_id="m">-897</value>
+<value letter_id="t">-897</value>
+<value letter_id="n1">-897</value>
+<value letter_id="n2">-897</value>
+<value letter_id="n3">-897</value>
+<value letter_id="n4">-897</value>
+<value letter_id="n5">-897</value>
+</alphabet_array>
+<alphabet_array>
+<value letter_id="A">-897</value>
+<value letter_id="C">-897</value>
+<value letter_id="G">-897</value>
+<value letter_id="T">-897</value>
+<value letter_id="a">275</value>
+<value letter_id="c">488</value>
+<value letter_id="f">-897</value>
+<value letter_id="g">-897</value>
+<value letter_id="h">-897</value>
+<value letter_id="m">-897</value>
+<value letter_id="t">-897</value>
+<value letter_id="n1">-897</value>
+<value letter_id="n2">-897</value>
+<value letter_id="n3">-897</value>
+<value letter_id="n4">-897</value>
+<value letter_id="n5">-897</value>
+</alphabet_array>
+<alphabet_array>
+<value letter_id="A">-897</value>
+<value letter_id="C">-897</value>
+<value letter_id="G">-897</value>
+<value letter_id="T">-897</value>
+<value letter_id="a">275</value>
+<value letter_id="c">388</value>
+<value letter_id="f">-897</value>
+<value letter_id="g">-897</value>
+<value letter_id="h">-897</value>
+<value letter_id="m">-897</value>
+<value letter_id="t">385</value>
+<value letter_id="n1">-897</value>
+<value letter_id="n2">-897</value>
+<value letter_id="n3">-897</value>
+<value letter_id="n4">-897</value>
+<value letter_id="n5">-897</value>
+</alphabet_array>
+<alphabet_array>
+<value letter_id="A">-897</value>
+<value letter_id="C">-897</value>
+<value letter_id="G">-897</value>
+<value letter_id="T">-897</value>
+<value letter_id="a">-897</value>
+<value letter_id="c">447</value>
+<value letter_id="f">-897</value>
+<value letter_id="g">-897</value>
+<value letter_id="h">-897</value>
+<value letter_id="m">-897</value>
+<value letter_id="t">385</value>
+<value letter_id="n1">-897</value>
+<value letter_id="n2">-897</value>
+<value letter_id="n3">-897</value>
+<value letter_id="n4">-897</value>
+<value letter_id="n5">-897</value>
+</alphabet_array>
+<alphabet_array>
+<value letter_id="A">-897</value>
+<value letter_id="C">-897</value>
+<value letter_id="G">-897</value>
+<value letter_id="T">-897</value>
+<value letter_id="a">375</value>
+<value letter_id="c">-897</value>
+<value letter_id="f">-897</value>
+<value letter_id="g">-897</value>
+<value letter_id="h">-897</value>
+<value letter_id="m">-897</value>
+<value letter_id="t">443</value>
+<value letter_id="n1">-897</value>
+<value letter_id="n2">-897</value>
+<value letter_id="n3">-897</value>
+<value letter_id="n4">-897</value>
+<value letter_id="n5">-897</value>
+</alphabet_array>
+<alphabet_array>
+<value letter_id="A">-897</value>
+<value letter_id="C">-897</value>
+<value letter_id="G">-897</value>
+<value letter_id="T">-897</value>
+<value letter_id="a">375</value>
+<value letter_id="c">447</value>
+<value letter_id="f">-897</value>
+<value letter_id="g">-897</value>
+<value letter_id="h">-897</value>
+<value letter_id="m">-897</value>
+<value letter_id="t">-897</value>
+<value letter_id="n1">-897</value>
+<value letter_id="n2">-897</value>
+<value letter_id="n3">-897</value>
+<value letter_id="n4">-897</value>
+<value letter_id="n5">-897</value>
+</alphabet_array>
+<alphabet_array>
+<value letter_id="A">-897</value>
+<value letter_id="C">-897</value>
+<value letter_id="G">-897</value>
+<value letter_id="T">-897</value>
+<value letter_id="a">375</value>
+<value letter_id="c">-897</value>
+<value letter_id="f">-897</value>
+<value letter_id="g">478</value>
+<value letter_id="h">-897</value>
+<value letter_id="m">-897</value>
+<value letter_id="t">385</value>
+<value letter_id="n1">-897</value>
+<value letter_id="n2">-897</value>
+<value letter_id="n3">-897</value>
+<value letter_id="n4">-897</value>
+<value letter_id="n5">-897</value>
+</alphabet_array>
+<alphabet_array>
+<value letter_id="A">-897</value>
+<value letter_id="C">-897</value>
+<value letter_id="G">-897</value>
+<value letter_id="T">-897</value>
+<value letter_id="a">275</value>
+<value letter_id="c">388</value>
+<value letter_id="f">-897</value>
+<value letter_id="g">478</value>
+<value letter_id="h">-897</value>
+<value letter_id="m">-897</value>
+<value letter_id="t">285</value>
+<value letter_id="n1">-897</value>
+<value letter_id="n2">-897</value>
+<value letter_id="n3">-897</value>
+<value letter_id="n4">-897</value>
+<value letter_id="n5">-897</value>
+</alphabet_array>
+</alphabet_matrix>
+</scores>
+<probabilities>
+<alphabet_matrix>
+<alphabet_array>
+<value letter_id="A">0.400000</value>
+<value letter_id="C">0.000000</value>
+<value letter_id="G">0.000000</value>
+<value letter_id="T">0.000000</value>
+<value letter_id="a">0.000000</value>
+<value letter_id="c">0.000000</value>
+<value letter_id="f">0.000000</value>
+<value letter_id="g">0.000000</value>
+<value letter_id="h">0.000000</value>
+<value letter_id="m">0.000000</value>
+<value letter_id="t">0.600000</value>
+<value letter_id="n1">0.000000</value>
+<value letter_id="n2">0.000000</value>
+<value letter_id="n3">0.000000</value>
+<value letter_id="n4">0.000000</value>
+<value letter_id="n5">0.000000</value>
+</alphabet_array>
+<alphabet_array>
+<value letter_id="A">0.000000</value>
+<value letter_id="C">0.200000</value>
+<value letter_id="G">0.200000</value>
+<value letter_id="T">0.000000</value>
+<value letter_id="a">0.400000</value>
+<value letter_id="c">0.000000</value>
+<value letter_id="f">0.000000</value>
+<value letter_id="g">0.000000</value>
+<value letter_id="h">0.000000</value>
+<value letter_id="m">0.000000</value>
+<value letter_id="t">0.200000</value>
+<value letter_id="n1">0.000000</value>
+<value letter_id="n2">0.000000</value>
+<value letter_id="n3">0.000000</value>
+<value letter_id="n4">0.000000</value>
+<value letter_id="n5">0.000000</value>
+</alphabet_array>
+<alphabet_array>
+<value letter_id="A">0.000000</value>
+<value letter_id="C">0.400000</value>
+<value letter_id="G">0.000000</value>
+<value letter_id="T">0.000000</value>
+<value letter_id="a">0.400000</value>
+<value letter_id="c">0.000000</value>
+<value letter_id="f">0.000000</value>
+<value letter_id="g">0.000000</value>
+<value letter_id="h">0.000000</value>
+<value letter_id="m">0.000000</value>
+<value letter_id="t">0.200000</value>
+<value letter_id="n1">0.000000</value>
+<value letter_id="n2">0.000000</value>
+<value letter_id="n3">0.000000</value>
+<value letter_id="n4">0.000000</value>
+<value letter_id="n5">0.000000</value>
+</alphabet_array>
+<alphabet_array>
+<value letter_id="A">0.000000</value>
+<value letter_id="C">0.200000</value>
+<value letter_id="G">0.000000</value>
+<value letter_id="T">0.200000</value>
+<value letter_id="a">0.600000</value>
+<value letter_id="c">0.000000</value>
+<value letter_id="f">0.000000</value>
+<value letter_id="g">0.000000</value>
+<value letter_id="h">0.000000</value>
+<value letter_id="m">0.000000</value>
+<value letter_id="t">0.000000</value>
+<value letter_id="n1">0.000000</value>
+<value letter_id="n2">0.000000</value>
+<value letter_id="n3">0.000000</value>
+<value letter_id="n4">0.000000</value>
+<value letter_id="n5">0.000000</value>
+</alphabet_array>
+<alphabet_array>
+<value letter_id="A">0.400000</value>
+<value letter_id="C">0.000000</value>
+<value letter_id="G">0.000000</value>
+<value letter_id="T">0.000000</value>
+<value letter_id="a">0.600000</value>
+<value letter_id="c">0.000000</value>
+<value letter_id="f">0.000000</value>
+<value letter_id="g">0.000000</value>
+<value letter_id="h">0.000000</value>
+<value letter_id="m">0.000000</value>
+<value letter_id="t">0.000000</value>
+<value letter_id="n1">0.000000</value>
+<value letter_id="n2">0.000000</value>
+<value letter_id="n3">0.000000</value>
+<value letter_id="n4">0.000000</value>
+<value letter_id="n5">0.000000</value>
+</alphabet_array>
+<alphabet_array>
+<value letter_id="A">0.400000</value>
+<value letter_id="C">0.000000</value>
+<value letter_id="G">0.000000</value>
+<value letter_id="T">0.000000</value>
+<value letter_id="a">0.400000</value>
+<value letter_id="c">0.000000</value>
+<value letter_id="f">0.000000</value>
+<value letter_id="g">0.200000</value>
+<value letter_id="h">0.000000</value>
+<value letter_id="m">0.000000</value>
+<value letter_id="t">0.000000</value>
+<value letter_id="n1">0.000000</value>
+<value letter_id="n2">0.000000</value>
+<value letter_id="n3">0.000000</value>
+<value letter_id="n4">0.000000</value>
+<value letter_id="n5">0.000000</value>
+</alphabet_array>
+<alphabet_array>
+<value letter_id="A">0.000000</value>
+<value letter_id="C">0.400000</value>
+<value letter_id="G">0.000000</value>
+<value letter_id="T">0.000000</value>
+<value letter_id="a">0.000000</value>
+<value letter_id="c">0.200000</value>
+<value letter_id="f">0.000000</value>
+<value letter_id="g">0.200000</value>
+<value letter_id="h">0.000000</value>
+<value letter_id="m">0.000000</value>
+<value letter_id="t">0.200000</value>
+<value letter_id="n1">0.000000</value>
+<value letter_id="n2">0.000000</value>
+<value letter_id="n3">0.000000</value>
+<value letter_id="n4">0.000000</value>
+<value letter_id="n5">0.000000</value>
+</alphabet_array>
+<alphabet_array>
+<value letter_id="A">0.400000</value>
+<value letter_id="C">0.000000</value>
+<value letter_id="G">0.000000</value>
+<value letter_id="T">0.000000</value>
+<value letter_id="a">0.000000</value>
+<value letter_id="c">0.000000</value>
+<value letter_id="f">0.000000</value>
+<value letter_id="g">0.200000</value>
+<value letter_id="h">0.000000</value>
+<value letter_id="m">0.000000</value>
+<value letter_id="t">0.400000</value>
+<value letter_id="n1">0.000000</value>
+<value letter_id="n2">0.000000</value>
+<value letter_id="n3">0.000000</value>
+<value letter_id="n4">0.000000</value>
+<value letter_id="n5">0.000000</value>
+</alphabet_array>
+<alphabet_array>
+<value letter_id="A">0.000000</value>
+<value letter_id="C">0.200000</value>
+<value letter_id="G">0.200000</value>
+<value letter_id="T">0.000000</value>
+<value letter_id="a">0.200000</value>
+<value letter_id="c">0.200000</value>
+<value letter_id="f">0.000000</value>
+<value letter_id="g">0.200000</value>
+<value letter_id="h">0.000000</value>
+<value letter_id="m">0.000000</value>
+<value letter_id="t">0.000000</value>
+<value letter_id="n1">0.000000</value>
+<value letter_id="n2">0.000000</value>
+<value letter_id="n3">0.000000</value>
+<value letter_id="n4">0.000000</value>
+<value letter_id="n5">0.000000</value>
+</alphabet_array>
+<alphabet_array>
+<value letter_id="A">0.200000</value>
+<value letter_id="C">0.000000</value>
+<value letter_id="G">0.200000</value>
+<value letter_id="T">0.000000</value>
+<value letter_id="a">0.000000</value>
+<value letter_id="c">0.200000</value>
+<value letter_id="f">0.000000</value>
+<value letter_id="g">0.000000</value>
+<value letter_id="h">0.000000</value>
+<value letter_id="m">0.000000</value>
+<value letter_id="t">0.400000</value>
+<value letter_id="n1">0.000000</value>
+<value letter_id="n2">0.000000</value>
+<value letter_id="n3">0.000000</value>
+<value letter_id="n4">0.000000</value>
+<value letter_id="n5">0.000000</value>
+</alphabet_array>
+<alphabet_array>
+<value letter_id="A">0.000000</value>
+<value letter_id="C">0.200000</value>
+<value letter_id="G">0.000000</value>
+<value letter_id="T">0.000000</value>
+<value letter_id="a">0.400000</value>
+<value letter_id="c">0.400000</value>
+<value letter_id="f">0.000000</value>
+<value letter_id="g">0.000000</value>
+<value letter_id="h">0.000000</value>
+<value letter_id="m">0.000000</value>
+<value letter_id="t">0.000000</value>
+<value letter_id="n1">0.000000</value>
+<value letter_id="n2">0.000000</value>
+<value letter_id="n3">0.000000</value>
+<value letter_id="n4">0.000000</value>
+<value letter_id="n5">0.000000</value>
+</alphabet_array>
+<alphabet_array>
+<value letter_id="A">0.000000</value>
+<value letter_id="C">0.000000</value>
+<value letter_id="G">0.200000</value>
+<value letter_id="T">0.000000</value>
+<value letter_id="a">0.000000</value>
+<value letter_id="c">0.000000</value>
+<value letter_id="f">0.000000</value>
+<value letter_id="g">0.000000</value>
+<value letter_id="h">0.000000</value>
+<value letter_id="m">0.000000</value>
+<value letter_id="t">0.800000</value>
+<value letter_id="n1">0.000000</value>
+<value letter_id="n2">0.000000</value>
+<value letter_id="n3">0.000000</value>
+<value letter_id="n4">0.000000</value>
+<value letter_id="n5">0.000000</value>
+</alphabet_array>
+<alphabet_array>
+<value letter_id="A">0.000000</value>
+<value letter_id="C">0.000000</value>
+<value letter_id="G">0.200000</value>
+<value letter_id="T">0.000000</value>
+<value letter_id="a">0.400000</value>
+<value letter_id="c">0.400000</value>
+<value letter_id="f">0.000000</value>
+<value letter_id="g">0.000000</value>
+<value letter_id="h">0.000000</value>
+<value letter_id="m">0.000000</value>
+<value letter_id="t">0.000000</value>
+<value letter_id="n1">0.000000</value>
+<value letter_id="n2">0.000000</value>
+<value letter_id="n3">0.000000</value>
+<value letter_id="n4">0.000000</value>
+<value letter_id="n5">0.000000</value>
+</alphabet_array>
+<alphabet_array>
+<value letter_id="A">0.000000</value>
+<value letter_id="C">0.000000</value>
+<value letter_id="G">0.000000</value>
+<value letter_id="T">0.000000</value>
+<value letter_id="a">1.000000</value>
+<value letter_id="c">0.000000</value>
+<value letter_id="f">0.000000</value>
+<value letter_id="g">0.000000</value>
+<value letter_id="h">0.000000</value>
+<value letter_id="m">0.000000</value>
+<value letter_id="t">0.000000</value>
+<value letter_id="n1">0.000000</value>
+<value letter_id="n2">0.000000</value>
+<value letter_id="n3">0.000000</value>
+<value letter_id="n4">0.000000</value>
+<value letter_id="n5">0.000000</value>
+</alphabet_array>
+<alphabet_array>
+<value letter_id="A">0.000000</value>
+<value letter_id="C">0.000000</value>
+<value letter_id="G">0.000000</value>
+<value letter_id="T">0.000000</value>
+<value letter_id="a">0.200000</value>
+<value letter_id="c">0.800000</value>
+<value letter_id="f">0.000000</value>
+<value letter_id="g">0.000000</value>
+<value letter_id="h">0.000000</value>
+<value letter_id="m">0.000000</value>
+<value letter_id="t">0.000000</value>
+<value letter_id="n1">0.000000</value>
+<value letter_id="n2">0.000000</value>
+<value letter_id="n3">0.000000</value>
+<value letter_id="n4">0.000000</value>
+<value letter_id="n5">0.000000</value>
+</alphabet_array>
+<alphabet_array>
+<value letter_id="A">0.000000</value>
+<value letter_id="C">0.000000</value>
+<value letter_id="G">0.000000</value>
+<value letter_id="T">0.000000</value>
+<value letter_id="a">0.200000</value>
+<value letter_id="c">0.400000</value>
+<value letter_id="f">0.000000</value>
+<value letter_id="g">0.000000</value>
+<value letter_id="h">0.000000</value>
+<value letter_id="m">0.000000</value>
+<value letter_id="t">0.400000</value>
+<value letter_id="n1">0.000000</value>
+<value letter_id="n2">0.000000</value>
+<value letter_id="n3">0.000000</value>
+<value letter_id="n4">0.000000</value>
+<value letter_id="n5">0.000000</value>
+</alphabet_array>
+<alphabet_array>
+<value letter_id="A">0.000000</value>
+<value letter_id="C">0.000000</value>
+<value letter_id="G">0.000000</value>
+<value letter_id="T">0.000000</value>
+<value letter_id="a">0.000000</value>
+<value letter_id="c">0.600000</value>
+<value letter_id="f">0.000000</value>
+<value letter_id="g">0.000000</value>
+<value letter_id="h">0.000000</value>
+<value letter_id="m">0.000000</value>
+<value letter_id="t">0.400000</value>
+<value letter_id="n1">0.000000</value>
+<value letter_id="n2">0.000000</value>
+<value letter_id="n3">0.000000</value>
+<value letter_id="n4">0.000000</value>
+<value letter_id="n5">0.000000</value>
+</alphabet_array>
+<alphabet_array>
+<value letter_id="A">0.000000</value>
+<value letter_id="C">0.000000</value>
+<value letter_id="G">0.000000</value>
+<value letter_id="T">0.000000</value>
+<value letter_id="a">0.400000</value>
+<value letter_id="c">0.000000</value>
+<value letter_id="f">0.000000</value>
+<value letter_id="g">0.000000</value>
+<value letter_id="h">0.000000</value>
+<value letter_id="m">0.000000</value>
+<value letter_id="t">0.600000</value>
+<value letter_id="n1">0.000000</value>
+<value letter_id="n2">0.000000</value>
+<value letter_id="n3">0.000000</value>
+<value letter_id="n4">0.000000</value>
+<value letter_id="n5">0.000000</value>
+</alphabet_array>
+<alphabet_array>
+<value letter_id="A">0.000000</value>
+<value letter_id="C">0.000000</value>
+<value letter_id="G">0.000000</value>
+<value letter_id="T">0.000000</value>
+<value letter_id="a">0.400000</value>
+<value letter_id="c">0.600000</value>
+<value letter_id="f">0.000000</value>
+<value letter_id="g">0.000000</value>
+<value letter_id="h">0.000000</value>
+<value letter_id="m">0.000000</value>
+<value letter_id="t">0.000000</value>
+<value letter_id="n1">0.000000</value>
+<value letter_id="n2">0.000000</value>
+<value letter_id="n3">0.000000</value>
+<value letter_id="n4">0.000000</value>
+<value letter_id="n5">0.000000</value>
+</alphabet_array>
+<alphabet_array>
+<value letter_id="A">0.000000</value>
+<value letter_id="C">0.000000</value>
+<value letter_id="G">0.000000</value>
+<value letter_id="T">0.000000</value>
+<value letter_id="a">0.400000</value>
+<value letter_id="c">0.000000</value>
+<value letter_id="f">0.000000</value>
+<value letter_id="g">0.200000</value>
+<value letter_id="h">0.000000</value>
+<value letter_id="m">0.000000</value>
+<value letter_id="t">0.400000</value>
+<value letter_id="n1">0.000000</value>
+<value letter_id="n2">0.000000</value>
+<value letter_id="n3">0.000000</value>
+<value letter_id="n4">0.000000</value>
+<value letter_id="n5">0.000000</value>
+</alphabet_array>
+<alphabet_array>
+<value letter_id="A">0.000000</value>
+<value letter_id="C">0.000000</value>
+<value letter_id="G">0.000000</value>
+<value letter_id="T">0.000000</value>
+<value letter_id="a">0.200000</value>
+<value letter_id="c">0.400000</value>
+<value letter_id="f">0.000000</value>
+<value letter_id="g">0.200000</value>
+<value letter_id="h">0.000000</value>
+<value letter_id="m">0.000000</value>
+<value letter_id="t">0.200000</value>
+<value letter_id="n1">0.000000</value>
+<value letter_id="n2">0.000000</value>
+<value letter_id="n3">0.000000</value>
+<value letter_id="n4">0.000000</value>
+<value letter_id="n5">0.000000</value>
+</alphabet_array>
+</alphabet_matrix>
+</probabilities>
+<regular_expression>
+[tA][aCGt][Cat][aCT][aA][Aag][Ccgt][Atg][CGacg][tAGc][acC][tG][acG]a[ca][cta][ct][ta][ca][atg][cagt]
+</regular_expression>
+<contributing_sites>
+<contributing_site sequence_id="sequence_17" position="8" strand="plus" pvalue="1.01e-33" >
+<left_flank>gatggttt</left_flank>
+<site>
+<letter_ref letter_id="t"/>
+<letter_ref letter_id="a"/>
+<letter_ref letter_id="t"/>
+<letter_ref letter_id="a"/>
+<letter_ref letter_id="a"/>
+<letter_ref letter_id="g"/>
+<letter_ref letter_id="g"/>
+<letter_ref letter_id="g"/>
+<letter_ref letter_id="g"/>
+<letter_ref letter_id="c"/>
+<letter_ref letter_id="c"/>
+<letter_ref letter_id="t"/>
+<letter_ref letter_id="c"/>
+<letter_ref letter_id="a"/>
+<letter_ref letter_id="c"/>
+<letter_ref letter_id="c"/>
+<letter_ref letter_id="c"/>
+<letter_ref letter_id="t"/>
+<letter_ref letter_id="c"/>
+<letter_ref letter_id="g"/>
+<letter_ref letter_id="g"/>
+</site>
+<right_flank>ctcagccctc</right_flank>
+</contributing_site>
+<contributing_site sequence_id="sequence_16" position="28" strand="plus" pvalue="7.62e-28" >
+<left_flank>AGTTGGCATC</left_flank>
+<site>
+<letter_ref letter_id="t"/>
+<letter_ref letter_id="a"/>
+<letter_ref letter_id="a"/>
+<letter_ref letter_id="a"/>
+<letter_ref letter_id="a"/>
+<letter_ref letter_id="a"/>
+<letter_ref letter_id="t"/>
+<letter_ref letter_id="t"/>
+<letter_ref letter_id="a"/>
+<letter_ref letter_id="t"/>
+<letter_ref letter_id="a"/>
+<letter_ref letter_id="t"/>
+<letter_ref letter_id="a"/>
+<letter_ref letter_id="a"/>
+<letter_ref letter_id="c"/>
+<letter_ref letter_id="t"/>
+<letter_ref letter_id="t"/>
+<letter_ref letter_id="t"/>
+<letter_ref letter_id="a"/>
+<letter_ref letter_id="t"/>
+<letter_ref letter_id="t"/>
+</site>
+<right_flank>t</right_flank>
+</contributing_site>
+<contributing_site sequence_id="sequence_10" position="4" strand="plus" pvalue="2.07e-26" >
+<left_flank>aaac</left_flank>
+<site>
+<letter_ref letter_id="t"/>
+<letter_ref letter_id="t"/>
+<letter_ref letter_id="a"/>
+<letter_ref letter_id="a"/>
+<letter_ref letter_id="a"/>
+<letter_ref letter_id="a"/>
+<letter_ref letter_id="c"/>
+<letter_ref letter_id="t"/>
+<letter_ref letter_id="c"/>
+<letter_ref letter_id="t"/>
+<letter_ref letter_id="a"/>
+<letter_ref letter_id="t"/>
+<letter_ref letter_id="a"/>
+<letter_ref letter_id="a"/>
+<letter_ref letter_id="a"/>
+<letter_ref letter_id="c"/>
+<letter_ref letter_id="t"/>
+<letter_ref letter_id="t"/>
+<letter_ref letter_id="a"/>
+<letter_ref letter_id="a"/>
+<letter_ref letter_id="a"/>
+</site>
+<right_flank>actCTAGAAT</right_flank>
+</contributing_site>
+<contributing_site sequence_id="sequence_19" position="28" strand="plus" pvalue="8.19e-18" >
+<left_flank>AAGCCCCAGC</left_flank>
+<site>
+<letter_ref letter_id="A"/>
+<letter_ref letter_id="G"/>
+<letter_ref letter_id="C"/>
+<letter_ref letter_id="C"/>
+<letter_ref letter_id="A"/>
+<letter_ref letter_id="A"/>
+<letter_ref letter_id="C"/>
+<letter_ref letter_id="A"/>
+<letter_ref letter_id="G"/>
+<letter_ref letter_id="G"/>
+<letter_ref letter_id="c"/>
+<letter_ref letter_id="t"/>
+<letter_ref letter_id="c"/>
+<letter_ref letter_id="a"/>
+<letter_ref letter_id="c"/>
+<letter_ref letter_id="a"/>
+<letter_ref letter_id="c"/>
+<letter_ref letter_id="a"/>
+<letter_ref letter_id="c"/>
+<letter_ref letter_id="a"/>
+<letter_ref letter_id="c"/>
+</site>
+<right_flank>a</right_flank>
+</contributing_site>
+<contributing_site sequence_id="sequence_22" position="29" strand="plus" pvalue="9.00e-16" >
+<left_flank>ATCCCTGAGC</left_flank>
+<site>
+<letter_ref letter_id="A"/>
+<letter_ref letter_id="C"/>
+<letter_ref letter_id="C"/>
+<letter_ref letter_id="T"/>
+<letter_ref letter_id="A"/>
+<letter_ref letter_id="A"/>
+<letter_ref letter_id="C"/>
+<letter_ref letter_id="A"/>
+<letter_ref letter_id="C"/>
+<letter_ref letter_id="A"/>
+<letter_ref letter_id="C"/>
+<letter_ref letter_id="G"/>
+<letter_ref letter_id="G"/>
+<letter_ref letter_id="a"/>
+<letter_ref letter_id="c"/>
+<letter_ref letter_id="t"/>
+<letter_ref letter_id="c"/>
+<letter_ref letter_id="a"/>
+<letter_ref letter_id="c"/>
+<letter_ref letter_id="t"/>
+<letter_ref letter_id="c"/>
+</site>
+<right_flank></right_flank>
+</contributing_site>
+</contributing_sites>
+</motif>
+</motifs>
+<scanned_sites_summary p_thresh="0.0001">
+<scanned_sites sequence_id="sequence_0" pvalue="9.99e-01" num_sites="0"></scanned_sites>
+<scanned_sites sequence_id="sequence_1" pvalue="9.78e-01" num_sites="0"></scanned_sites>
+<scanned_sites sequence_id="sequence_2" pvalue="1.00e+00" num_sites="0"></scanned_sites>
+<scanned_sites sequence_id="sequence_3" pvalue="9.99e-01" num_sites="0"></scanned_sites>
+<scanned_sites sequence_id="sequence_4" pvalue="9.99e-01" num_sites="0"></scanned_sites>
+<scanned_sites sequence_id="sequence_5" pvalue="1.00e+00" num_sites="0"></scanned_sites>
+<scanned_sites sequence_id="sequence_6" pvalue="9.61e-01" num_sites="0"></scanned_sites>
+<scanned_sites sequence_id="sequence_7" pvalue="1.00e+00" num_sites="0"></scanned_sites>
+<scanned_sites sequence_id="sequence_8" pvalue="9.65e-01" num_sites="0"></scanned_sites>
+<scanned_sites sequence_id="sequence_9" pvalue="9.67e-01" num_sites="0"></scanned_sites>
+<scanned_sites sequence_id="sequence_10" pvalue="6.20e-25" num_sites="1"><scanned_site motif_id="motif_1" strand="plus" position="4" pvalue="2.07e-26"/>
+</scanned_sites>
+<scanned_sites sequence_id="sequence_11" pvalue="1.00e+00" num_sites="0"></scanned_sites>
+<scanned_sites sequence_id="sequence_12" pvalue="7.25e-01" num_sites="0"></scanned_sites>
+<scanned_sites sequence_id="sequence_13" pvalue="9.59e-01" num_sites="0"></scanned_sites>
+<scanned_sites sequence_id="sequence_14" pvalue="7.20e-01" num_sites="0"></scanned_sites>
+<scanned_sites sequence_id="sequence_15" pvalue="9.99e-01" num_sites="0"></scanned_sites>
+<scanned_sites sequence_id="sequence_16" pvalue="2.29e-26" num_sites="1"><scanned_site motif_id="motif_1" strand="plus" position="28" pvalue="7.62e-28"/>
+</scanned_sites>
+<scanned_sites sequence_id="sequence_17" pvalue="3.02e-32" num_sites="2"><scanned_site motif_id="motif_1" strand="plus" position="8" pvalue="1.01e-33"/>
+<scanned_site motif_id="motif_1" strand="plus" position="29" pvalue="1.08e-05"/>
+</scanned_sites>
+<scanned_sites sequence_id="sequence_18" pvalue="1.00e+00" num_sites="0"></scanned_sites>
+<scanned_sites sequence_id="sequence_19" pvalue="2.46e-16" num_sites="1"><scanned_site motif_id="motif_1" strand="plus" position="28" pvalue="8.19e-18"/>
+</scanned_sites>
+<scanned_sites sequence_id="sequence_20" pvalue="1.27e-03" num_sites="1"><scanned_site motif_id="motif_1" strand="plus" position="28" pvalue="4.22e-05"/>
+</scanned_sites>
+<scanned_sites sequence_id="sequence_21" pvalue="9.58e-01" num_sites="0"></scanned_sites>
+<scanned_sites sequence_id="sequence_22" pvalue="2.70e-14" num_sites="1"><scanned_site motif_id="motif_1" strand="plus" position="29" pvalue="9.00e-16"/>
+</scanned_sites>
+<scanned_sites sequence_id="sequence_23" pvalue="9.69e-01" num_sites="0"></scanned_sites>
+<scanned_sites sequence_id="sequence_24" pvalue="2.53e-03" num_sites="1"><scanned_site motif_id="motif_1" strand="plus" position="28" pvalue="8.43e-05"/>
+</scanned_sites>
+<scanned_sites sequence_id="sequence_25" pvalue="9.67e-01" num_sites="0"></scanned_sites>
+<scanned_sites sequence_id="sequence_26" pvalue="1.00e+00" num_sites="0"></scanned_sites>
+<scanned_sites sequence_id="sequence_27" pvalue="1.00e+00" num_sites="0"></scanned_sites>
+<scanned_sites sequence_id="sequence_28" pvalue="1.00e+00" num_sites="0"></scanned_sites>
+<scanned_sites sequence_id="sequence_29" pvalue="1.00e+00" num_sites="0"></scanned_sites>
+</scanned_sites_summary>
+</MEME>
--- a/test-data/meme_output_test1.html	Thu Aug 29 10:19:40 2024 +0000
+++ b/test-data/meme_output_test1.html	Mon Jul 14 21:33:56 2025 +0000
@@ -1,73 +1,124 @@
-      <script>
-      {
-        $("opt_mod").className = data.options.mod;
-        $("opt_objfun").textContent = data.options.objfun;
-        $("opt_spfun").textContent = data.options.spfun;
-        $("opt_strand").className = (current_alphabet.has_complement() ? (data.options.revcomp ? "both" : "given") : "none");
-        $("opt_nmotifs").textContent = data.options.nmotifs;
-        $("opt_evt").textContent = (typeof data.options.evt === "number" ? data.options.evt : "no limit");
-        $("opt_minw").textContent = data.options.minw;
-        $("opt_maxw").textContent = data.options.maxw;
-        $("opt_minsites").textContent = data.options.minsites;
-        $("opt_maxsites").textContent = data.options.maxsites;
-        $("opt_wnsites").textContent = data.options.wnsites;
-        $("opt_spmap").className = data.options.spmap;
-        $("opt_spfuzz").textContent = data.options.spfuzz;
-        $("opt_prior").className = data.options.prior;
-        if (data.options.prior == "dirichlet") {
-          $("opt_prior_source").textContent = make_background_source("Source", data.background.source, true);
-        } else {
-          $("opt_prior_source").textContent = (data.options.prior == "addone") ? "motif observed frequencies" : data.options.priors_source;
-        }
-        $("opt_b").textContent = (data.options.b < 0) ? "not applicable" : (data.options.b == 0) ? "intrinsic strength" : data.options.b;
-        $("opt_maxiter").textContent = data.options.maxiter;
-        $("opt_distance").textContent = data.options.distance;
-        $("opt_searchsize").textContent = data.options.searchsize;
-        if (typeof data.options.csites != "undefined") {
-          $("opt_csites").textContent = data.options.csites;
-        } else {
-          $("opt_csites").parentElement.style.display = "none"
-        }
-        if (typeof data.options.wg != "undefined") {
-          $("opt_wg").textContent = data.options.wg;
-        } else {
-          $("opt_wg").parentElement.style.display = "none"
-        }
-        if (typeof data.options.ws != "undefined") {
-          $("opt_ws").textContent = data.options.ws;
-        }
-        else {
-          $("opt_ws").parentElement.style.display = "none"
-        }
-        if (typeof data.options.noendgaps != "undefined") {
-          $("opt_noendgaps").className = (data.options.noendgaps ? "on" : "off");
-        }
-        else {
-          $("opt_noendgaps").parentElement.style.display = "none"
-        }
-        $("opt_substring").className = (data.options.substring ? "on" : "off");
-      }
-      </script>
-    </div>
-    <!-- list information on this program -->
-    <div id="info_sec" class="bar">
-      <div class="subsection">
-        <h5 id="version">MEME version</h5>
-        <span id="ins_version"></span> 
-        (Release date: <span id="ins_release"></span>)<br>
-      </div>
-      <script>
-        $("ins_version").innerHTML = data["version"];
-        $("ins_release").innerHTML = data["release"];
-      </script>
-      <div class="subsection" id="reference"> <script>print_citation("reference", "MEME");</script></div>
-      <div class="subsection">
-        <h5 id="command">Command line</h5>
-        <textarea id="cmd" rows="5" style="width:100%;" readonly="readonly">
-        </textarea>
-        <script>$("cmd").value = data["cmd"].join(" ");</script>
-      </div>
-    </div>
-    
-  </body>
-</html>
+          "sequences": [
+            {
+              "name": "chr21_19617074_19617124_+",
+              "length": 50,
+              "weight": 1.000000
+            }, {
+              "name": "chr21_26934381_26934431_+",
+              "length": 50,
+              "weight": 1.000000
+            }, {
+              "name": "chr21_28217753_28217803_-",
+              "length": 50,
+              "weight": 1.000000
+            }, {
+              "name": "chr21_31710037_31710087_-",
+              "length": 50,
+              "weight": 1.000000
+            }, {
+              "name": "chr21_31744582_31744632_-",
+              "length": 50,
+              "weight": 1.000000
+            }, {
+              "name": "chr21_31768316_31768366_+",
+              "length": 50,
+              "weight": 1.000000
+            }, {
+              "name": "chr21_31914206_31914256_-",
+              "length": 50,
+              "weight": 1.000000
+            }, {
+              "name": "chr21_31933633_31933683_-",
+              "length": 50,
+              "weight": 1.000000
+            }, {
+              "name": "chr21_31962741_31962791_-",
+              "length": 50,
+              "weight": 1.000000
+            }, {
+              "name": "chr21_31964683_31964733_+",
+              "length": 50,
+              "weight": 1.000000
+            }, {
+              "name": "chr21_31973364_31973414_+",
+              "length": 50,
+              "weight": 1.000000
+            }, {
+              "name": "chr21_31992870_31992920_+",
+              "length": 50,
+              "weight": 1.000000
+            }, {
+              "name": "chr21_32185595_32185645_-",
+              "length": 50,
+              "weight": 1.000000
+            }, {
+              "name": "chr21_32202076_32202126_-",
+              "length": 50,
+              "weight": 1.000000
+            }, {
+              "name": "chr21_32253899_32253949_-",
+              "length": 50,
+              "weight": 1.000000
+            }, {
+              "name": "chr21_32410820_32410870_-",
+              "length": 50,
+              "weight": 1.000000
+            }, {
+              "name": "chr21_36411748_36411798_-",
+              "length": 50,
+              "weight": 1.000000
+            }, {
+              "name": "chr21_37838750_37838800_-",
+              "length": 50,
+              "weight": 1.000000
+            }, {
+              "name": "chr21_45705687_45705737_+",
+              "length": 50,
+              "weight": 1.000000
+            }, {
+              "name": "chr21_45971413_45971463_-",
+              "length": 50,
+              "weight": 1.000000
+            }, {
+              "name": "chr21_45978668_45978718_-",
+              "length": 50,
+              "weight": 1.000000
+            }, {
+              "name": "chr21_45993530_45993580_+",
+              "length": 50,
+              "weight": 1.000000
+            }, {
+              "name": "chr21_46020421_46020471_+",
+              "length": 50,
+              "weight": 1.000000
+            }, {
+              "name": "chr21_46031920_46031970_+",
+              "length": 50,
+              "weight": 1.000000
+            }, {
+              "name": "chr21_46046964_46047014_+",
+              "length": 50,
+              "weight": 1.000000
+            }, {
+              "name": "chr21_46057197_46057247_+",
+              "length": 50,
+              "weight": 1.000000
+            }, {
+              "name": "chr21_46086869_46086919_-",
+              "length": 50,
+              "weight": 1.000000
+            }, {
+              "name": "chr21_46102103_46102153_-",
+              "length": 50,
+              "weight": 1.000000
+            }, {
+              "name": "chr21_47517957_47518007_+",
+              "length": 50,
+              "weight": 1.000000
+            }, {
+              "name": "chr21_47575506_47575556_-",
+              "length": 50,
+              "weight": 1.000000
+            }
+          ]
+        },
\ No newline at end of file
--- a/test-data/meme_output_test1.txt	Thu Aug 29 10:19:40 2024 +0000
+++ b/test-data/meme_output_test1.txt	Mon Jul 14 21:33:56 2025 +0000
@@ -1,39 +1,207 @@
+model:  mod=         zoops    nmotifs=         1    evt=           inf
+objective function:           em=       E-value of product of p-values
+                              starts=   E-value of product of p-values
+width:  minw=            8    maxw=           50
+nsites: minsites=        2    maxsites=       30    wnsites=       0.8
+theta:  spmap=         pam    spfuzz=        120
+em:     prior=       megap    b=            7500    maxiter=        50
+        distance=    1e-05
+trim:   wg=             11    ws=              1    endgaps=       yes
+data:   n=            1500    N=              30
+sample: seed=            0    hsfrac=          0
+        searchsize=   1500    norand=         no    csites=       1000
+Dirichlet mixture priors file: prior30.plib
+Letter frequencies in dataset:
+A 0.294 C 0.231 D 0 E 0 F 0 G 0.257 H 0 I 0 K 0 
+L 0 M 0 N 0 P 0 Q 0 R 0 S 0 T 0.217 V 0 
+W 0 Y 0 
+Background letter frequencies (from file dataset with add-one prior applied):
+A 0.291 C 0.229 D 0.000658 E 0.000658 F 0.000658 G 0.255 H 0.000658 I 0.000658 K 0.000658 
+L 0.000658 M 0.000658 N 0.000658 P 0.000658 Q 0.000658 R 0.000658 S 0.000658 T 0.215 V 0.000658 
+W 0.000658 Y 0.000658 
+Background model order: 0
 ********************************************************************************
-SUMMARY OF MOTIFS
+
+
+********************************************************************************
+MOTIF GGGGTATAAAA MEME-1	width =  11  sites =  25  llr = 239  E-value = 2.4e-011
 ********************************************************************************
+--------------------------------------------------------------------------------
+	Motif GGGGTATAAAA MEME-1 Description
+--------------------------------------------------------------------------------
+Simplified        A  2323:a:a8a8
+pos.-specific     C  ::3::::::::
+probability       D  :::::::::::
+matrix            E  :::::::::::
+                  F  :::::::::::
+                  G  7746::::::1
+                  H  :::::::::::
+                  I  :::::::::::
+                  K  :::::::::::
+                  L  :::::::::::
+                  M  :::::::::::
+                  N  :::::::::::
+                  P  :::::::::::
+                  Q  :::::::::::
+                  R  :::::::::::
+                  S  :::::::::::
+                  T  1:2:a:a:2::
+                  V  :::::::::::
+                  W  :::::::::::
+                  Y  :::::::::::
+
+         bits   10.6            
+                 9.5            
+                 8.5            
+                 7.4            
+Relative         6.3            
+Entropy          5.3            
+(13.8 bits)      4.2            
+                 3.2            
+                 2.1     * **   
+                 1.1 ** ********
+                 0.0 -----------
+
+Multilevel           GGGGTATAAAA
+consensus            AACA    T  
+sequence                        
+                                
+                                
+--------------------------------------------------------------------------------
+
+--------------------------------------------------------------------------------
+	Motif GGGGTATAAAA MEME-1 sites sorted by position p-value
+--------------------------------------------------------------------------------
+Sequence name             Start   P-value               Site  
+-------------             ----- ---------            -----------
+chr21_46046964_46047014_     13  1.06e-06 AAGGCCAGGA GGGGTATAAAA GCCTGAGAGC
+chr21_46057197_46057247_     37  3.41e-06 ACAGGCCCTG GGCATATAAAA GCC       
+chr21_45971413_45971463_     10  3.41e-06  CAGGCCCTG GGCATATAAAA GCCCCAGCAG
+chr21_31964683_31964733_     14  3.41e-06 GATTCACTGA GGCATATAAAA GGCCCTCTGC
+chr21_45993530_45993580_      8  4.00e-06    CCAAGGA GGAGTATAAAA GCCCCACAAA
+chr21_32202076_32202126_     14  5.01e-06 CCACCAGCTT GAGGTATAAAA AGCCCTGTAC
+chr21_46031920_46031970_     16  6.06e-06 ATACCCAGGG AGGGTATAAAA CCTCAGCAGC
+chr21_32410820_32410870_     22  8.67e-06 AATCACTGAG GATGTATAAAA GTCCCAGGGA
+chr21_32185595_32185645_     19  8.67e-06 CACCAGAGCT GGGATATATAA AGAAGGTTCT
+chr21_31992870_31992920_     17  8.67e-06 CACTATTGAA GATGTATAAAA TTTCATTTGC
+chr21_46020421_46020471_      3  1.21e-05         GA GACATATAAAA GCCAACATCC
+chr21_47517957_47518007_     33  1.59e-05 CCGGCGGGGC GGGGTATAAAG GGGGCGG   
+chr21_45978668_45978718_      5  1.59e-05       CAGA GGGGTATAAAG GTTCCGACCA
+chr21_31914206_31914256_     16  1.68e-05 CCCACTACTT AGAGTATAAAA TCATTCTGAG
+chr21_32253899_32253949_     20  2.03e-05 CACCAGCAAG GATATATAAAA GCTCAGGAGT
+chr21_31744582_31744632_     13  3.06e-05 CAGGTCTAAG AGCATATATAA CTTGGAGTCC
+chr21_19617074_19617124_     40  3.06e-05 CCTCGGGACG TGGGTATATAA           
+chr21_45705687_45705737_     38  3.82e-05 CGTGGTCGCG GGGGTATAACA GC        
+chr21_31768316_31768366_      1  3.82e-05          . AACGTATATAA ATGGTCCTGT
+chr21_47575506_47575556_     31  4.02e-05 GCTGCCGGTG AGCGTATAAAG GCCCTGGCG 
+chr21_26934381_26934431_     28  5.52e-05 AGTCACAAGT GAGTTATAAAA GGGTCGCACG
+chr21_31710037_31710087_     15  5.94e-05 CCCAGGTTTC TGAGTATATAA TCGCCGCACC
+chr21_36411748_36411798_     23  6.78e-05 AGTTTCAGTT GGCATCtaaaa attatataac
+chr21_31933633_31933683_      3  2.08e-04         TC AGAGTATATAT AAATGTTCCT
+chr21_31962741_31962791_     14  4.05e-04 TATAACTCAG GTTGGATAAAA TAATTTGTAC
+--------------------------------------------------------------------------------
 
 --------------------------------------------------------------------------------
-	Combined block diagrams: non-overlapping sites with p-value < 0.0001
+	Motif GGGGTATAAAA MEME-1 block diagrams
 --------------------------------------------------------------------------------
-SEQUENCE NAME            COMBINED P-VALUE  MOTIF DIAGRAM
+SEQUENCE NAME            POSITION P-VALUE  MOTIF DIAGRAM
 -------------            ----------------  -------------
-chr21_19617074_19617124_         1.22e-03  39_[1(3.06e-05)]
-chr21_26934381_26934431_         2.21e-03  27_[1(5.52e-05)]_12
-chr21_28217753_28217803_         7.29e-01  50
-chr21_31710037_31710087_         2.37e-03  14_[1(5.94e-05)]_25
-chr21_31744582_31744632_         1.22e-03  12_[1(3.06e-05)]_27
-chr21_31768316_31768366_         1.53e-03  [1(3.82e-05)]_39
-chr21_31914206_31914256_         6.70e-04  15_[1(1.68e-05)]_24
-chr21_31933633_31933683_         1.81e-03  4_[1(4.54e-05)]_35
-chr21_31962741_31962791_         1.61e-02  50
-chr21_31964683_31964733_         1.36e-04  13_[1(3.41e-06)]_26
-chr21_31973364_31973414_         1.99e-01  50
-chr21_31992870_31992920_         3.47e-04  16_[1(8.67e-06)]_23
-chr21_32185595_32185645_         3.47e-04  18_[1(8.67e-06)]_21
-chr21_32202076_32202126_         2.01e-04  13_[1(5.01e-06)]_26
-chr21_32253899_32253949_         8.11e-04  19_[1(2.03e-05)]_20
-chr21_32410820_32410870_         3.47e-04  21_[1(8.67e-06)]_18
-chr21_36411748_36411798_         2.71e-03  22_[1(6.78e-05)]_17
-chr21_37838750_37838800_         8.23e-02  50
-chr21_45705687_45705737_         1.53e-03  37_[1(3.82e-05)]_2
-chr21_45971413_45971463_         1.36e-04  9_[1(3.41e-06)]_30
-chr21_45978668_45978718_         6.37e-04  4_[1(1.59e-05)]_35
-chr21_45993530_45993580_         1.60e-04  7_[1(4.00e-06)]_32
-chr21_46020421_46020471_         4.83e-04  2_[1(1.21e-05)]_37
-chr21_46031920_46031970_         2.43e-04  15_[1(6.06e-06)]_24
-chr21_46046964_46047014_         4.26e-05  12_[1(1.06e-06)]_27
-chr21_46057197_46057247_         1.36e-04  36_[1(3.41e-06)]_3
-chr21_46086869_46086919_         4.30e-02  50
-chr21_46102103_46102153_         4.30e-02  50
-chr21_47517957_47518007_         6.37e-04  32_[1(1.59e-05)]_7
-chr21_47575506_47575556_         1.61e-03  30_[1(4.02e-05)]_9
+chr21_46046964_46047014_          1.1e-06  12_[1]_27
+chr21_46057197_46057247_          3.4e-06  36_[1]_3
+chr21_45971413_45971463_          3.4e-06  9_[1]_30
+chr21_31964683_31964733_          3.4e-06  13_[1]_26
+chr21_45993530_45993580_            4e-06  7_[1]_32
+chr21_32202076_32202126_            5e-06  13_[1]_26
+chr21_46031920_46031970_          6.1e-06  15_[1]_24
+chr21_32410820_32410870_          8.7e-06  21_[1]_18
+chr21_32185595_32185645_          8.7e-06  18_[1]_21
+chr21_31992870_31992920_          8.7e-06  16_[1]_23
+chr21_46020421_46020471_          1.2e-05  2_[1]_37
+chr21_47517957_47518007_          1.6e-05  32_[1]_7
+chr21_45978668_45978718_          1.6e-05  4_[1]_35
+chr21_31914206_31914256_          1.7e-05  15_[1]_24
+chr21_32253899_32253949_            2e-05  19_[1]_20
+chr21_31744582_31744632_          3.1e-05  12_[1]_27
+chr21_19617074_19617124_          3.1e-05  39_[1]
+chr21_45705687_45705737_          3.8e-05  37_[1]_2
+chr21_31768316_31768366_          3.8e-05  [1]_39
+chr21_47575506_47575556_            4e-05  30_[1]_9
+chr21_26934381_26934431_          5.5e-05  27_[1]_12
+chr21_31710037_31710087_          5.9e-05  14_[1]_25
+chr21_36411748_36411798_          6.8e-05  22_[1]_17
+chr21_31933633_31933683_          0.00021  2_[1]_37
+chr21_31962741_31962791_           0.0004  13_[1]_26
+--------------------------------------------------------------------------------
+
+--------------------------------------------------------------------------------
+	Motif GGGGTATAAAA MEME-1 in BLOCKS format
+--------------------------------------------------------------------------------
+BL   MOTIF GGGGTATAAAA width=11 seqs=25
+chr21_46046964_46047014_ (   13) GGGGTATAAAA  1 
+chr21_46057197_46057247_ (   37) GGCATATAAAA  1 
+chr21_45971413_45971463_ (   10) GGCATATAAAA  1 
+chr21_31964683_31964733_ (   14) GGCATATAAAA  1 
+chr21_45993530_45993580_ (    8) GGAGTATAAAA  1 
+chr21_32202076_32202126_ (   14) GAGGTATAAAA  1 
+chr21_46031920_46031970_ (   16) AGGGTATAAAA  1 
+chr21_32410820_32410870_ (   22) GATGTATAAAA  1 
+chr21_32185595_32185645_ (   19) GGGATATATAA  1 
+chr21_31992870_31992920_ (   17) GATGTATAAAA  1 
+chr21_46020421_46020471_ (    3) GACATATAAAA  1 
+chr21_47517957_47518007_ (   33) GGGGTATAAAG  1 
+chr21_45978668_45978718_ (    5) GGGGTATAAAG  1 
+chr21_31914206_31914256_ (   16) AGAGTATAAAA  1 
+chr21_32253899_32253949_ (   20) GATATATAAAA  1 
+chr21_31744582_31744632_ (   13) AGCATATATAA  1 
+chr21_19617074_19617124_ (   40) TGGGTATATAA  1 
+chr21_45705687_45705737_ (   38) GGGGTATAACA  1 
+chr21_31768316_31768366_ (    1) AACGTATATAA  1 
+chr21_47575506_47575556_ (   31) AGCGTATAAAG  1 
+chr21_26934381_26934431_ (   28) GAGTTATAAAA  1 
+chr21_31710037_31710087_ (   15) TGAGTATATAA  1 
+chr21_36411748_36411798_ (   23) GGCATCTAAAA  1 
+chr21_31933633_31933683_ (    3) AGAGTATATAT  1 
+chr21_31962741_31962791_ (   14) GTTGGATAAAA  1 
+//
+
+--------------------------------------------------------------------------------
+
+--------------------------------------------------------------------------------
+	Motif GGGGTATAAAA MEME-1 position-specific scoring matrix
+--------------------------------------------------------------------------------
+log-odds matrix: alength= 20 w= 11 n= 1200 bayes= 5.33554 E= 2.4e-011 
+   -32   -680     91     77      7    138    -20     55     64    107     11    150    142     72     87    396   -148    221   -140    -36 
+   -11   -680     89     76      7    137    -21     55     63    107     10    149    141     71     87    396   -239    220   -140    -36 
+   -79     41      4     21     -7     44    -62     42     -5     99      0     99    138     52     42    399    -46    223   -173    -68 
+    11   -677     48     47     -2    127    -43     46     27    101      3    124    138     60     62    397   -235    220   -160    -55 
+  -596   -820     12    -21    -53   -267    -74     37     16     44    -37     98     31      9     19    319    212    127   -193    -95 
+   165   -261     70    110     77   -521     -4    147     95    201     90    121    124     91    107    425   -527    314    -95      8 
+  -838   -990    -89   -149   -151   -841   -161   -117   -113    -66   -209    -68    -69   -129    -91    111    221    -55   -255   -173 
+   176   -858    -79   -103   -115   -717   -148    -95   -108    -17   -162    -61    -12    -95    -69    193   -737     52   -240   -153 
+   134   -686      0     16    -12   -553    -68     44     -8     96     -9     88    124     41     36    384     11    216   -177    -71 
+   165   -261     70    110     77   -521     -4    147     95    201     90    121    124     91    107    425   -527    314    -95      8 
+   147   -614     89    129     93   -121     12    160    113    217    108    144    144    111    125    447   -241    332    -81     22 
+--------------------------------------------------------------------------------
+
+--------------------------------------------------------------------------------
+	Motif GGGGTATAAAA MEME-1 position-specific probability matrix
+--------------------------------------------------------------------------------
+letter-probability matrix: alength= 20 w= 11 nsites= 25 E= 2.4e-011 
+ 0.240000  0.000000  0.000000  0.000000  0.000000  0.680000  0.000000  0.000000  0.000000  0.000000  0.000000  0.000000  0.000000  0.000000  0.000000  0.000000  0.080000  0.000000  0.000000  0.000000 
+ 0.280000  0.000000  0.000000  0.000000  0.000000  0.680000  0.000000  0.000000  0.000000  0.000000  0.000000  0.000000  0.000000  0.000000  0.000000  0.000000  0.040000  0.000000  0.000000  0.000000 
+ 0.160000  0.320000  0.000000  0.000000  0.000000  0.360000  0.000000  0.000000  0.000000  0.000000  0.000000  0.000000  0.000000  0.000000  0.000000  0.000000  0.160000  0.000000  0.000000  0.000000 
+ 0.320000  0.000000  0.000000  0.000000  0.000000  0.640000  0.000000  0.000000  0.000000  0.000000  0.000000  0.000000  0.000000  0.000000  0.000000  0.000000  0.040000  0.000000  0.000000  0.000000 
+ 0.000000  0.000000  0.000000  0.000000  0.000000  0.040000  0.000000  0.000000  0.000000  0.000000  0.000000  0.000000  0.000000  0.000000  0.000000  0.000000  0.960000  0.000000  0.000000  0.000000 
+ 0.960000  0.040000  0.000000  0.000000  0.000000  0.000000  0.000000  0.000000  0.000000  0.000000  0.000000  0.000000  0.000000  0.000000  0.000000  0.000000  0.000000  0.000000  0.000000  0.000000 
+ 0.000000  0.000000  0.000000  0.000000  0.000000  0.000000  0.000000  0.000000  0.000000  0.000000  0.000000  0.000000  0.000000  0.000000  0.000000  0.000000  1.000000  0.000000  0.000000  0.000000 
+ 1.000000  0.000000  0.000000  0.000000  0.000000  0.000000  0.000000  0.000000  0.000000  0.000000  0.000000  0.000000  0.000000  0.000000  0.000000  0.000000  0.000000  0.000000  0.000000  0.000000 
+ 0.760000  0.000000  0.000000  0.000000  0.000000  0.000000  0.000000  0.000000  0.000000  0.000000  0.000000  0.000000  0.000000  0.000000  0.000000  0.000000  0.240000  0.000000  0.000000  0.000000 
+ 0.960000  0.040000  0.000000  0.000000  0.000000  0.000000  0.000000  0.000000  0.000000  0.000000  0.000000  0.000000  0.000000  0.000000  0.000000  0.000000  0.000000  0.000000  0.000000  0.000000 
+ 0.840000  0.000000  0.000000  0.000000  0.000000  0.120000  0.000000  0.000000  0.000000  0.000000  0.000000  0.000000  0.000000  0.000000  0.000000  0.000000  0.040000  0.000000  0.000000  0.000000 
+--------------------------------------------------------------------------------
+
+--------------------------------------------------------------------------------
+	Motif GGGGTATAAAA MEME-1 regular expression
+--------------------------------------------------------------------------------
+[GA][GA][GC][GA]TATA[AT]AA
+--------------------------------------------------------------------------------
\ No newline at end of file
--- a/test-data/meme_output_test1.xml	Thu Aug 29 10:19:40 2024 +0000
+++ b/test-data/meme_output_test1.xml	Mon Jul 14 21:33:56 2025 +0000
@@ -1,3 +1,924 @@
+<alphabet_array>
+<value letter_id="A">-32</value>
+<value letter_id="C">-680</value>
+<value letter_id="D">91</value>
+<value letter_id="E">77</value>
+<value letter_id="F">7</value>
+<value letter_id="G">138</value>
+<value letter_id="H">-20</value>
+<value letter_id="I">55</value>
+<value letter_id="K">64</value>
+<value letter_id="L">107</value>
+<value letter_id="M">11</value>
+<value letter_id="N">150</value>
+<value letter_id="P">142</value>
+<value letter_id="Q">72</value>
+<value letter_id="R">87</value>
+<value letter_id="S">396</value>
+<value letter_id="T">-148</value>
+<value letter_id="V">221</value>
+<value letter_id="W">-140</value>
+<value letter_id="Y">-36</value>
+</alphabet_array>
+<alphabet_array>
+<value letter_id="A">-11</value>
+<value letter_id="C">-680</value>
+<value letter_id="D">89</value>
+<value letter_id="E">76</value>
+<value letter_id="F">7</value>
+<value letter_id="G">137</value>
+<value letter_id="H">-21</value>
+<value letter_id="I">55</value>
+<value letter_id="K">63</value>
+<value letter_id="L">107</value>
+<value letter_id="M">10</value>
+<value letter_id="N">149</value>
+<value letter_id="P">141</value>
+<value letter_id="Q">71</value>
+<value letter_id="R">87</value>
+<value letter_id="S">396</value>
+<value letter_id="T">-239</value>
+<value letter_id="V">220</value>
+<value letter_id="W">-140</value>
+<value letter_id="Y">-36</value>
+</alphabet_array>
+<alphabet_array>
+<value letter_id="A">-79</value>
+<value letter_id="C">41</value>
+<value letter_id="D">4</value>
+<value letter_id="E">21</value>
+<value letter_id="F">-7</value>
+<value letter_id="G">44</value>
+<value letter_id="H">-62</value>
+<value letter_id="I">42</value>
+<value letter_id="K">-5</value>
+<value letter_id="L">99</value>
+<value letter_id="M">0</value>
+<value letter_id="N">99</value>
+<value letter_id="P">138</value>
+<value letter_id="Q">52</value>
+<value letter_id="R">42</value>
+<value letter_id="S">399</value>
+<value letter_id="T">-46</value>
+<value letter_id="V">223</value>
+<value letter_id="W">-173</value>
+<value letter_id="Y">-68</value>
+</alphabet_array>
+<alphabet_array>
+<value letter_id="A">11</value>
+<value letter_id="C">-677</value>
+<value letter_id="D">48</value>
+<value letter_id="E">47</value>
+<value letter_id="F">-2</value>
+<value letter_id="G">127</value>
+<value letter_id="H">-43</value>
+<value letter_id="I">46</value>
+<value letter_id="K">27</value>
+<value letter_id="L">101</value>
+<value letter_id="M">3</value>
+<value letter_id="N">124</value>
+<value letter_id="P">138</value>
+<value letter_id="Q">60</value>
+<value letter_id="R">62</value>
+<value letter_id="S">397</value>
+<value letter_id="T">-235</value>
+<value letter_id="V">220</value>
+<value letter_id="W">-160</value>
+<value letter_id="Y">-55</value>
+</alphabet_array>
+<alphabet_array>
+<value letter_id="A">-596</value>
+<value letter_id="C">-820</value>
+<value letter_id="D">12</value>
+<value letter_id="E">-21</value>
+<value letter_id="F">-53</value>
+<value letter_id="G">-267</value>
+<value letter_id="H">-74</value>
+<value letter_id="I">37</value>
+<value letter_id="K">16</value>
+<value letter_id="L">44</value>
+<value letter_id="M">-37</value>
+<value letter_id="N">98</value>
+<value letter_id="P">31</value>
+<value letter_id="Q">9</value>
+<value letter_id="R">19</value>
+<value letter_id="S">319</value>
+<value letter_id="T">212</value>
+<value letter_id="V">127</value>
+<value letter_id="W">-193</value>
+<value letter_id="Y">-95</value>
+</alphabet_array>
+<alphabet_array>
+<value letter_id="A">165</value>
+<value letter_id="C">-261</value>
+<value letter_id="D">70</value>
+<value letter_id="E">110</value>
+<value letter_id="F">77</value>
+<value letter_id="G">-521</value>
+<value letter_id="H">-4</value>
+<value letter_id="I">147</value>
+<value letter_id="K">95</value>
+<value letter_id="L">201</value>
+<value letter_id="M">90</value>
+<value letter_id="N">121</value>
+<value letter_id="P">124</value>
+<value letter_id="Q">91</value>
+<value letter_id="R">107</value>
+<value letter_id="S">425</value>
+<value letter_id="T">-527</value>
+<value letter_id="V">314</value>
+<value letter_id="W">-95</value>
+<value letter_id="Y">8</value>
+</alphabet_array>
+<alphabet_array>
+<value letter_id="A">-838</value>
+<value letter_id="C">-990</value>
+<value letter_id="D">-89</value>
+<value letter_id="E">-149</value>
+<value letter_id="F">-151</value>
+<value letter_id="G">-841</value>
+<value letter_id="H">-161</value>
+<value letter_id="I">-117</value>
+<value letter_id="K">-113</value>
+<value letter_id="L">-66</value>
+<value letter_id="M">-209</value>
+<value letter_id="N">-68</value>
+<value letter_id="P">-69</value>
+<value letter_id="Q">-129</value>
+<value letter_id="R">-91</value>
+<value letter_id="S">111</value>
+<value letter_id="T">221</value>
+<value letter_id="V">-55</value>
+<value letter_id="W">-255</value>
+<value letter_id="Y">-173</value>
+</alphabet_array>
+<alphabet_array>
+<value letter_id="A">176</value>
+<value letter_id="C">-858</value>
+<value letter_id="D">-79</value>
+<value letter_id="E">-103</value>
+<value letter_id="F">-115</value>
+<value letter_id="G">-717</value>
+<value letter_id="H">-148</value>
+<value letter_id="I">-95</value>
+<value letter_id="K">-108</value>
+<value letter_id="L">-17</value>
+<value letter_id="M">-162</value>
+<value letter_id="N">-61</value>
+<value letter_id="P">-12</value>
+<value letter_id="Q">-95</value>
+<value letter_id="R">-69</value>
+<value letter_id="S">193</value>
+<value letter_id="T">-737</value>
+<value letter_id="V">52</value>
+<value letter_id="W">-240</value>
+<value letter_id="Y">-153</value>
+</alphabet_array>
+<alphabet_array>
+<value letter_id="A">134</value>
+<value letter_id="C">-686</value>
+<value letter_id="D">0</value>
+<value letter_id="E">16</value>
+<value letter_id="F">-12</value>
+<value letter_id="G">-553</value>
+<value letter_id="H">-68</value>
+<value letter_id="I">44</value>
+<value letter_id="K">-8</value>
+<value letter_id="L">96</value>
+<value letter_id="M">-9</value>
+<value letter_id="N">88</value>
+<value letter_id="P">124</value>
+<value letter_id="Q">41</value>
+<value letter_id="R">36</value>
+<value letter_id="S">384</value>
+<value letter_id="T">11</value>
+<value letter_id="V">216</value>
+<value letter_id="W">-177</value>
+<value letter_id="Y">-71</value>
+</alphabet_array>
+<alphabet_array>
+<value letter_id="A">165</value>
+<value letter_id="C">-261</value>
+<value letter_id="D">70</value>
+<value letter_id="E">110</value>
+<value letter_id="F">77</value>
+<value letter_id="G">-521</value>
+<value letter_id="H">-4</value>
+<value letter_id="I">147</value>
+<value letter_id="K">95</value>
+<value letter_id="L">201</value>
+<value letter_id="M">90</value>
+<value letter_id="N">121</value>
+<value letter_id="P">124</value>
+<value letter_id="Q">91</value>
+<value letter_id="R">107</value>
+<value letter_id="S">425</value>
+<value letter_id="T">-527</value>
+<value letter_id="V">314</value>
+<value letter_id="W">-95</value>
+<value letter_id="Y">8</value>
+</alphabet_array>
+<alphabet_array>
+<value letter_id="A">147</value>
+<value letter_id="C">-614</value>
+<value letter_id="D">89</value>
+<value letter_id="E">129</value>
+<value letter_id="F">93</value>
+<value letter_id="G">-121</value>
+<value letter_id="H">12</value>
+<value letter_id="I">160</value>
+<value letter_id="K">113</value>
+<value letter_id="L">217</value>
+<value letter_id="M">108</value>
+<value letter_id="N">144</value>
+<value letter_id="P">144</value>
+<value letter_id="Q">111</value>
+<value letter_id="R">125</value>
+<value letter_id="S">447</value>
+<value letter_id="T">-241</value>
+<value letter_id="V">332</value>
+<value letter_id="W">-81</value>
+<value letter_id="Y">22</value>
+</alphabet_array>
+</alphabet_matrix>
+</scores>
+<probabilities>
+<alphabet_matrix>
+<alphabet_array>
+<value letter_id="A">0.240000</value>
+<value letter_id="C">0.000000</value>
+<value letter_id="D">0.000000</value>
+<value letter_id="E">0.000000</value>
+<value letter_id="F">0.000000</value>
+<value letter_id="G">0.680000</value>
+<value letter_id="H">0.000000</value>
+<value letter_id="I">0.000000</value>
+<value letter_id="K">0.000000</value>
+<value letter_id="L">0.000000</value>
+<value letter_id="M">0.000000</value>
+<value letter_id="N">0.000000</value>
+<value letter_id="P">0.000000</value>
+<value letter_id="Q">0.000000</value>
+<value letter_id="R">0.000000</value>
+<value letter_id="S">0.000000</value>
+<value letter_id="T">0.080000</value>
+<value letter_id="V">0.000000</value>
+<value letter_id="W">0.000000</value>
+<value letter_id="Y">0.000000</value>
+</alphabet_array>
+<alphabet_array>
+<value letter_id="A">0.280000</value>
+<value letter_id="C">0.000000</value>
+<value letter_id="D">0.000000</value>
+<value letter_id="E">0.000000</value>
+<value letter_id="F">0.000000</value>
+<value letter_id="G">0.680000</value>
+<value letter_id="H">0.000000</value>
+<value letter_id="I">0.000000</value>
+<value letter_id="K">0.000000</value>
+<value letter_id="L">0.000000</value>
+<value letter_id="M">0.000000</value>
+<value letter_id="N">0.000000</value>
+<value letter_id="P">0.000000</value>
+<value letter_id="Q">0.000000</value>
+<value letter_id="R">0.000000</value>
+<value letter_id="S">0.000000</value>
+<value letter_id="T">0.040000</value>
+<value letter_id="V">0.000000</value>
+<value letter_id="W">0.000000</value>
+<value letter_id="Y">0.000000</value>
+</alphabet_array>
+<alphabet_array>
+<value letter_id="A">0.160000</value>
+<value letter_id="C">0.320000</value>
+<value letter_id="D">0.000000</value>
+<value letter_id="E">0.000000</value>
+<value letter_id="F">0.000000</value>
+<value letter_id="G">0.360000</value>
+<value letter_id="H">0.000000</value>
+<value letter_id="I">0.000000</value>
+<value letter_id="K">0.000000</value>
+<value letter_id="L">0.000000</value>
+<value letter_id="M">0.000000</value>
+<value letter_id="N">0.000000</value>
+<value letter_id="P">0.000000</value>
+<value letter_id="Q">0.000000</value>
+<value letter_id="R">0.000000</value>
+<value letter_id="S">0.000000</value>
+<value letter_id="T">0.160000</value>
+<value letter_id="V">0.000000</value>
+<value letter_id="W">0.000000</value>
+<value letter_id="Y">0.000000</value>
+</alphabet_array>
+<alphabet_array>
+<value letter_id="A">0.320000</value>
+<value letter_id="C">0.000000</value>
+<value letter_id="D">0.000000</value>
+<value letter_id="E">0.000000</value>
+<value letter_id="F">0.000000</value>
+<value letter_id="G">0.640000</value>
+<value letter_id="H">0.000000</value>
+<value letter_id="I">0.000000</value>
+<value letter_id="K">0.000000</value>
+<value letter_id="L">0.000000</value>
+<value letter_id="M">0.000000</value>
+<value letter_id="N">0.000000</value>
+<value letter_id="P">0.000000</value>
+<value letter_id="Q">0.000000</value>
+<value letter_id="R">0.000000</value>
+<value letter_id="S">0.000000</value>
+<value letter_id="T">0.040000</value>
+<value letter_id="V">0.000000</value>
+<value letter_id="W">0.000000</value>
+<value letter_id="Y">0.000000</value>
+</alphabet_array>
+<alphabet_array>
+<value letter_id="A">0.000000</value>
+<value letter_id="C">0.000000</value>
+<value letter_id="D">0.000000</value>
+<value letter_id="E">0.000000</value>
+<value letter_id="F">0.000000</value>
+<value letter_id="G">0.040000</value>
+<value letter_id="H">0.000000</value>
+<value letter_id="I">0.000000</value>
+<value letter_id="K">0.000000</value>
+<value letter_id="L">0.000000</value>
+<value letter_id="M">0.000000</value>
+<value letter_id="N">0.000000</value>
+<value letter_id="P">0.000000</value>
+<value letter_id="Q">0.000000</value>
+<value letter_id="R">0.000000</value>
+<value letter_id="S">0.000000</value>
+<value letter_id="T">0.960000</value>
+<value letter_id="V">0.000000</value>
+<value letter_id="W">0.000000</value>
+<value letter_id="Y">0.000000</value>
+</alphabet_array>
+<alphabet_array>
+<value letter_id="A">0.960000</value>
+<value letter_id="C">0.040000</value>
+<value letter_id="D">0.000000</value>
+<value letter_id="E">0.000000</value>
+<value letter_id="F">0.000000</value>
+<value letter_id="G">0.000000</value>
+<value letter_id="H">0.000000</value>
+<value letter_id="I">0.000000</value>
+<value letter_id="K">0.000000</value>
+<value letter_id="L">0.000000</value>
+<value letter_id="M">0.000000</value>
+<value letter_id="N">0.000000</value>
+<value letter_id="P">0.000000</value>
+<value letter_id="Q">0.000000</value>
+<value letter_id="R">0.000000</value>
+<value letter_id="S">0.000000</value>
+<value letter_id="T">0.000000</value>
+<value letter_id="V">0.000000</value>
+<value letter_id="W">0.000000</value>
+<value letter_id="Y">0.000000</value>
+</alphabet_array>
+<alphabet_array>
+<value letter_id="A">0.000000</value>
+<value letter_id="C">0.000000</value>
+<value letter_id="D">0.000000</value>
+<value letter_id="E">0.000000</value>
+<value letter_id="F">0.000000</value>
+<value letter_id="G">0.000000</value>
+<value letter_id="H">0.000000</value>
+<value letter_id="I">0.000000</value>
+<value letter_id="K">0.000000</value>
+<value letter_id="L">0.000000</value>
+<value letter_id="M">0.000000</value>
+<value letter_id="N">0.000000</value>
+<value letter_id="P">0.000000</value>
+<value letter_id="Q">0.000000</value>
+<value letter_id="R">0.000000</value>
+<value letter_id="S">0.000000</value>
+<value letter_id="T">1.000000</value>
+<value letter_id="V">0.000000</value>
+<value letter_id="W">0.000000</value>
+<value letter_id="Y">0.000000</value>
+</alphabet_array>
+<alphabet_array>
+<value letter_id="A">1.000000</value>
+<value letter_id="C">0.000000</value>
+<value letter_id="D">0.000000</value>
+<value letter_id="E">0.000000</value>
+<value letter_id="F">0.000000</value>
+<value letter_id="G">0.000000</value>
+<value letter_id="H">0.000000</value>
+<value letter_id="I">0.000000</value>
+<value letter_id="K">0.000000</value>
+<value letter_id="L">0.000000</value>
+<value letter_id="M">0.000000</value>
+<value letter_id="N">0.000000</value>
+<value letter_id="P">0.000000</value>
+<value letter_id="Q">0.000000</value>
+<value letter_id="R">0.000000</value>
+<value letter_id="S">0.000000</value>
+<value letter_id="T">0.000000</value>
+<value letter_id="V">0.000000</value>
+<value letter_id="W">0.000000</value>
+<value letter_id="Y">0.000000</value>
+</alphabet_array>
+<alphabet_array>
+<value letter_id="A">0.760000</value>
+<value letter_id="C">0.000000</value>
+<value letter_id="D">0.000000</value>
+<value letter_id="E">0.000000</value>
+<value letter_id="F">0.000000</value>
+<value letter_id="G">0.000000</value>
+<value letter_id="H">0.000000</value>
+<value letter_id="I">0.000000</value>
+<value letter_id="K">0.000000</value>
+<value letter_id="L">0.000000</value>
+<value letter_id="M">0.000000</value>
+<value letter_id="N">0.000000</value>
+<value letter_id="P">0.000000</value>
+<value letter_id="Q">0.000000</value>
+<value letter_id="R">0.000000</value>
+<value letter_id="S">0.000000</value>
+<value letter_id="T">0.240000</value>
+<value letter_id="V">0.000000</value>
+<value letter_id="W">0.000000</value>
+<value letter_id="Y">0.000000</value>
+</alphabet_array>
+<alphabet_array>
+<value letter_id="A">0.960000</value>
+<value letter_id="C">0.040000</value>
+<value letter_id="D">0.000000</value>
+<value letter_id="E">0.000000</value>
+<value letter_id="F">0.000000</value>
+<value letter_id="G">0.000000</value>
+<value letter_id="H">0.000000</value>
+<value letter_id="I">0.000000</value>
+<value letter_id="K">0.000000</value>
+<value letter_id="L">0.000000</value>
+<value letter_id="M">0.000000</value>
+<value letter_id="N">0.000000</value>
+<value letter_id="P">0.000000</value>
+<value letter_id="Q">0.000000</value>
+<value letter_id="R">0.000000</value>
+<value letter_id="S">0.000000</value>
+<value letter_id="T">0.000000</value>
+<value letter_id="V">0.000000</value>
+<value letter_id="W">0.000000</value>
+<value letter_id="Y">0.000000</value>
+</alphabet_array>
+<alphabet_array>
+<value letter_id="A">0.840000</value>
+<value letter_id="C">0.000000</value>
+<value letter_id="D">0.000000</value>
+<value letter_id="E">0.000000</value>
+<value letter_id="F">0.000000</value>
+<value letter_id="G">0.120000</value>
+<value letter_id="H">0.000000</value>
+<value letter_id="I">0.000000</value>
+<value letter_id="K">0.000000</value>
+<value letter_id="L">0.000000</value>
+<value letter_id="M">0.000000</value>
+<value letter_id="N">0.000000</value>
+<value letter_id="P">0.000000</value>
+<value letter_id="Q">0.000000</value>
+<value letter_id="R">0.000000</value>
+<value letter_id="S">0.000000</value>
+<value letter_id="T">0.040000</value>
+<value letter_id="V">0.000000</value>
+<value letter_id="W">0.000000</value>
+<value letter_id="Y">0.000000</value>
+</alphabet_array>
+</alphabet_matrix>
+</probabilities>
+<regular_expression>
+[GA][GA][GC][GA]TATA[AT]AA
+</regular_expression>
+<contributing_sites>
+<contributing_site sequence_id="sequence_24" position="12" strand="none" pvalue="1.06e-06" >
+<left_flank>AAGGCCAGGA</left_flank>
+<site>
+<letter_ref letter_id="G"/>
+<letter_ref letter_id="G"/>
+<letter_ref letter_id="G"/>
+<letter_ref letter_id="G"/>
+<letter_ref letter_id="T"/>
+<letter_ref letter_id="A"/>
+<letter_ref letter_id="T"/>
+<letter_ref letter_id="A"/>
+<letter_ref letter_id="A"/>
+<letter_ref letter_id="A"/>
+<letter_ref letter_id="A"/>
+</site>
+<right_flank>GCCTGAGAGC</right_flank>
+</contributing_site>
+<contributing_site sequence_id="sequence_25" position="36" strand="none" pvalue="3.41e-06" >
+<left_flank>ACAGGCCCTG</left_flank>
+<site>
+<letter_ref letter_id="G"/>
+<letter_ref letter_id="G"/>
+<letter_ref letter_id="C"/>
+<letter_ref letter_id="A"/>
+<letter_ref letter_id="T"/>
+<letter_ref letter_id="A"/>
+<letter_ref letter_id="T"/>
+<letter_ref letter_id="A"/>
+<letter_ref letter_id="A"/>
+<letter_ref letter_id="A"/>
+<letter_ref letter_id="A"/>
+</site>
+<right_flank>GCC</right_flank>
+</contributing_site>
+<contributing_site sequence_id="sequence_19" position="9" strand="none" pvalue="3.41e-06" >
+<left_flank>CAGGCCCTG</left_flank>
+<site>
+<letter_ref letter_id="G"/>
+<letter_ref letter_id="G"/>
+<letter_ref letter_id="C"/>
+<letter_ref letter_id="A"/>
+<letter_ref letter_id="T"/>
+<letter_ref letter_id="A"/>
+<letter_ref letter_id="T"/>
+<letter_ref letter_id="A"/>
+<letter_ref letter_id="A"/>
+<letter_ref letter_id="A"/>
+<letter_ref letter_id="A"/>
+</site>
+<right_flank>GCCCCAGCAG</right_flank>
+</contributing_site>
+<contributing_site sequence_id="sequence_9" position="13" strand="none" pvalue="3.41e-06" >
+<left_flank>GATTCACTGA</left_flank>
+<site>
+<letter_ref letter_id="G"/>
+<letter_ref letter_id="G"/>
+<letter_ref letter_id="C"/>
+<letter_ref letter_id="A"/>
+<letter_ref letter_id="T"/>
+<letter_ref letter_id="A"/>
+<letter_ref letter_id="T"/>
+<letter_ref letter_id="A"/>
+<letter_ref letter_id="A"/>
+<letter_ref letter_id="A"/>
+<letter_ref letter_id="A"/>
+</site>
+<right_flank>GGCCCTCTGC</right_flank>
+</contributing_site>
+<contributing_site sequence_id="sequence_21" position="7" strand="none" pvalue="4.00e-06" >
+<left_flank>CCAAGGA</left_flank>
+<site>
+<letter_ref letter_id="G"/>
+<letter_ref letter_id="G"/>
+<letter_ref letter_id="A"/>
+<letter_ref letter_id="G"/>
+<letter_ref letter_id="T"/>
+<letter_ref letter_id="A"/>
+<letter_ref letter_id="T"/>
+<letter_ref letter_id="A"/>
+<letter_ref letter_id="A"/>
+<letter_ref letter_id="A"/>
+<letter_ref letter_id="A"/>
+</site>
+<right_flank>GCCCCACAAA</right_flank>
+</contributing_site>
+<contributing_site sequence_id="sequence_13" position="13" strand="none" pvalue="5.01e-06" >
+<left_flank>CCACCAGCTT</left_flank>
+<site>
+<letter_ref letter_id="G"/>
+<letter_ref letter_id="A"/>
+<letter_ref letter_id="G"/>
+<letter_ref letter_id="G"/>
+<letter_ref letter_id="T"/>
+<letter_ref letter_id="A"/>
+<letter_ref letter_id="T"/>
+<letter_ref letter_id="A"/>
+<letter_ref letter_id="A"/>
+<letter_ref letter_id="A"/>
+<letter_ref letter_id="A"/>
+</site>
+<right_flank>AGCCCTGTAC</right_flank>
+</contributing_site>
+<contributing_site sequence_id="sequence_23" position="15" strand="none" pvalue="6.06e-06" >
+<left_flank>ATACCCAGGG</left_flank>
+<site>
+<letter_ref letter_id="A"/>
+<letter_ref letter_id="G"/>
+<letter_ref letter_id="G"/>
+<letter_ref letter_id="G"/>
+<letter_ref letter_id="T"/>
+<letter_ref letter_id="A"/>
+<letter_ref letter_id="T"/>
+<letter_ref letter_id="A"/>
+<letter_ref letter_id="A"/>
+<letter_ref letter_id="A"/>
+<letter_ref letter_id="A"/>
+</site>
+<right_flank>CCTCAGCAGC</right_flank>
+</contributing_site>
+<contributing_site sequence_id="sequence_15" position="21" strand="none" pvalue="8.67e-06" >
+<left_flank>AATCACTGAG</left_flank>
+<site>
+<letter_ref letter_id="G"/>
+<letter_ref letter_id="A"/>
+<letter_ref letter_id="T"/>
+<letter_ref letter_id="G"/>
+<letter_ref letter_id="T"/>
+<letter_ref letter_id="A"/>
+<letter_ref letter_id="T"/>
+<letter_ref letter_id="A"/>
+<letter_ref letter_id="A"/>
+<letter_ref letter_id="A"/>
+<letter_ref letter_id="A"/>
+</site>
+<right_flank>GTCCCAGGGA</right_flank>
+</contributing_site>
+<contributing_site sequence_id="sequence_12" position="18" strand="none" pvalue="8.67e-06" >
+<left_flank>CACCAGAGCT</left_flank>
+<site>
+<letter_ref letter_id="G"/>
+<letter_ref letter_id="G"/>
+<letter_ref letter_id="G"/>
+<letter_ref letter_id="A"/>
+<letter_ref letter_id="T"/>
+<letter_ref letter_id="A"/>
+<letter_ref letter_id="T"/>
+<letter_ref letter_id="A"/>
+<letter_ref letter_id="T"/>
+<letter_ref letter_id="A"/>
+<letter_ref letter_id="A"/>
+</site>
+<right_flank>AGAAGGTTCT</right_flank>
+</contributing_site>
+<contributing_site sequence_id="sequence_11" position="16" strand="none" pvalue="8.67e-06" >
+<left_flank>CACTATTGAA</left_flank>
+<site>
+<letter_ref letter_id="G"/>
+<letter_ref letter_id="A"/>
+<letter_ref letter_id="T"/>
+<letter_ref letter_id="G"/>
+<letter_ref letter_id="T"/>
+<letter_ref letter_id="A"/>
+<letter_ref letter_id="T"/>
+<letter_ref letter_id="A"/>
+<letter_ref letter_id="A"/>
+<letter_ref letter_id="A"/>
+<letter_ref letter_id="A"/>
+</site>
+<right_flank>TTTCATTTGC</right_flank>
+</contributing_site>
+<contributing_site sequence_id="sequence_22" position="2" strand="none" pvalue="1.21e-05" >
+<left_flank>GA</left_flank>
+<site>
+<letter_ref letter_id="G"/>
+<letter_ref letter_id="A"/>
+<letter_ref letter_id="C"/>
+<letter_ref letter_id="A"/>
+<letter_ref letter_id="T"/>
+<letter_ref letter_id="A"/>
+<letter_ref letter_id="T"/>
+<letter_ref letter_id="A"/>
+<letter_ref letter_id="A"/>
+<letter_ref letter_id="A"/>
+<letter_ref letter_id="A"/>
+</site>
+<right_flank>GCCAACATCC</right_flank>
+</contributing_site>
+<contributing_site sequence_id="sequence_28" position="32" strand="none" pvalue="1.59e-05" >
+<left_flank>CCGGCGGGGC</left_flank>
+<site>
+<letter_ref letter_id="G"/>
+<letter_ref letter_id="G"/>
+<letter_ref letter_id="G"/>
+<letter_ref letter_id="G"/>
+<letter_ref letter_id="T"/>
+<letter_ref letter_id="A"/>
+<letter_ref letter_id="T"/>
+<letter_ref letter_id="A"/>
+<letter_ref letter_id="A"/>
+<letter_ref letter_id="A"/>
+<letter_ref letter_id="G"/>
+</site>
+<right_flank>GGGGCGG</right_flank>
+</contributing_site>
+<contributing_site sequence_id="sequence_20" position="4" strand="none" pvalue="1.59e-05" >
+<left_flank>CAGA</left_flank>
+<site>
+<letter_ref letter_id="G"/>
+<letter_ref letter_id="G"/>
+<letter_ref letter_id="G"/>
+<letter_ref letter_id="G"/>
+<letter_ref letter_id="T"/>
+<letter_ref letter_id="A"/>
+<letter_ref letter_id="T"/>
+<letter_ref letter_id="A"/>
+<letter_ref letter_id="A"/>
+<letter_ref letter_id="A"/>
+<letter_ref letter_id="G"/>
+</site>
+<right_flank>GTTCCGACCA</right_flank>
+</contributing_site>
+<contributing_site sequence_id="sequence_6" position="15" strand="none" pvalue="1.68e-05" >
+<left_flank>CCCACTACTT</left_flank>
+<site>
+<letter_ref letter_id="A"/>
+<letter_ref letter_id="G"/>
+<letter_ref letter_id="A"/>
+<letter_ref letter_id="G"/>
+<letter_ref letter_id="T"/>
+<letter_ref letter_id="A"/>
+<letter_ref letter_id="T"/>
+<letter_ref letter_id="A"/>
+<letter_ref letter_id="A"/>
+<letter_ref letter_id="A"/>
+<letter_ref letter_id="A"/>
+</site>
+<right_flank>TCATTCTGAG</right_flank>
+</contributing_site>
+<contributing_site sequence_id="sequence_14" position="19" strand="none" pvalue="2.03e-05" >
+<left_flank>CACCAGCAAG</left_flank>
+<site>
+<letter_ref letter_id="G"/>
+<letter_ref letter_id="A"/>
+<letter_ref letter_id="T"/>
+<letter_ref letter_id="A"/>
+<letter_ref letter_id="T"/>
+<letter_ref letter_id="A"/>
+<letter_ref letter_id="T"/>
+<letter_ref letter_id="A"/>
+<letter_ref letter_id="A"/>
+<letter_ref letter_id="A"/>
+<letter_ref letter_id="A"/>
+</site>
+<right_flank>GCTCAGGAGT</right_flank>
+</contributing_site>
+<contributing_site sequence_id="sequence_4" position="12" strand="none" pvalue="3.06e-05" >
+<left_flank>CAGGTCTAAG</left_flank>
+<site>
+<letter_ref letter_id="A"/>
+<letter_ref letter_id="G"/>
+<letter_ref letter_id="C"/>
+<letter_ref letter_id="A"/>
+<letter_ref letter_id="T"/>
+<letter_ref letter_id="A"/>
+<letter_ref letter_id="T"/>
+<letter_ref letter_id="A"/>
+<letter_ref letter_id="T"/>
+<letter_ref letter_id="A"/>
+<letter_ref letter_id="A"/>
+</site>
+<right_flank>CTTGGAGTCC</right_flank>
+</contributing_site>
+<contributing_site sequence_id="sequence_0" position="39" strand="none" pvalue="3.06e-05" >
+<left_flank>CCTCGGGACG</left_flank>
+<site>
+<letter_ref letter_id="T"/>
+<letter_ref letter_id="G"/>
+<letter_ref letter_id="G"/>
+<letter_ref letter_id="G"/>
+<letter_ref letter_id="T"/>
+<letter_ref letter_id="A"/>
+<letter_ref letter_id="T"/>
+<letter_ref letter_id="A"/>
+<letter_ref letter_id="T"/>
+<letter_ref letter_id="A"/>
+<letter_ref letter_id="A"/>
+</site>
+<right_flank></right_flank>
+</contributing_site>
+<contributing_site sequence_id="sequence_18" position="37" strand="none" pvalue="3.82e-05" >
+<left_flank>CGTGGTCGCG</left_flank>
+<site>
+<letter_ref letter_id="G"/>
+<letter_ref letter_id="G"/>
+<letter_ref letter_id="G"/>
+<letter_ref letter_id="G"/>
+<letter_ref letter_id="T"/>
+<letter_ref letter_id="A"/>
+<letter_ref letter_id="T"/>
+<letter_ref letter_id="A"/>
+<letter_ref letter_id="A"/>
+<letter_ref letter_id="C"/>
+<letter_ref letter_id="A"/>
+</site>
+<right_flank>GC</right_flank>
+</contributing_site>
+<contributing_site sequence_id="sequence_5" position="0" strand="none" pvalue="3.82e-05" >
+<left_flank></left_flank>
+<site>
+<letter_ref letter_id="A"/>
+<letter_ref letter_id="A"/>
+<letter_ref letter_id="C"/>
+<letter_ref letter_id="G"/>
+<letter_ref letter_id="T"/>
+<letter_ref letter_id="A"/>
+<letter_ref letter_id="T"/>
+<letter_ref letter_id="A"/>
+<letter_ref letter_id="T"/>
+<letter_ref letter_id="A"/>
+<letter_ref letter_id="A"/>
+</site>
+<right_flank>ATGGTCCTGT</right_flank>
+</contributing_site>
+<contributing_site sequence_id="sequence_29" position="30" strand="none" pvalue="4.02e-05" >
+<left_flank>GCTGCCGGTG</left_flank>
+<site>
+<letter_ref letter_id="A"/>
+<letter_ref letter_id="G"/>
+<letter_ref letter_id="C"/>
+<letter_ref letter_id="G"/>
+<letter_ref letter_id="T"/>
+<letter_ref letter_id="A"/>
+<letter_ref letter_id="T"/>
+<letter_ref letter_id="A"/>
+<letter_ref letter_id="A"/>
+<letter_ref letter_id="A"/>
+<letter_ref letter_id="G"/>
+</site>
+<right_flank>GCCCTGGCG</right_flank>
+</contributing_site>
+<contributing_site sequence_id="sequence_1" position="27" strand="none" pvalue="5.52e-05" >
+<left_flank>AGTCACAAGT</left_flank>
+<site>
+<letter_ref letter_id="G"/>
+<letter_ref letter_id="A"/>
+<letter_ref letter_id="G"/>
+<letter_ref letter_id="T"/>
+<letter_ref letter_id="T"/>
+<letter_ref letter_id="A"/>
+<letter_ref letter_id="T"/>
+<letter_ref letter_id="A"/>
+<letter_ref letter_id="A"/>
+<letter_ref letter_id="A"/>
+<letter_ref letter_id="A"/>
+</site>
+<right_flank>GGGTCGCACG</right_flank>
+</contributing_site>
+<contributing_site sequence_id="sequence_3" position="14" strand="none" pvalue="5.94e-05" >
+<left_flank>CCCAGGTTTC</left_flank>
+<site>
+<letter_ref letter_id="T"/>
+<letter_ref letter_id="G"/>
+<letter_ref letter_id="A"/>
+<letter_ref letter_id="G"/>
+<letter_ref letter_id="T"/>
+<letter_ref letter_id="A"/>
+<letter_ref letter_id="T"/>
+<letter_ref letter_id="A"/>
+<letter_ref letter_id="T"/>
+<letter_ref letter_id="A"/>
+<letter_ref letter_id="A"/>
+</site>
+<right_flank>TCGCCGCACC</right_flank>
+</contributing_site>
+<contributing_site sequence_id="sequence_16" position="22" strand="none" pvalue="6.78e-05" >
+<left_flank>AGTTTCAGTT</left_flank>
+<site>
+<letter_ref letter_id="G"/>
+<letter_ref letter_id="G"/>
+<letter_ref letter_id="C"/>
+<letter_ref letter_id="A"/>
+<letter_ref letter_id="T"/>
+<letter_ref letter_id="C"/>
+<letter_ref letter_id="T"/>
+<letter_ref letter_id="A"/>
+<letter_ref letter_id="A"/>
+<letter_ref letter_id="A"/>
+<letter_ref letter_id="A"/>
+</site>
+<right_flank>attatataac</right_flank>
+</contributing_site>
+<contributing_site sequence_id="sequence_7" position="2" strand="none" pvalue="2.08e-04" >
+<left_flank>TC</left_flank>
+<site>
+<letter_ref letter_id="A"/>
+<letter_ref letter_id="G"/>
+<letter_ref letter_id="A"/>
+<letter_ref letter_id="G"/>
+<letter_ref letter_id="T"/>
+<letter_ref letter_id="A"/>
+<letter_ref letter_id="T"/>
+<letter_ref letter_id="A"/>
+<letter_ref letter_id="T"/>
+<letter_ref letter_id="A"/>
+<letter_ref letter_id="T"/>
+</site>
+<right_flank>AAATGTTCCT</right_flank>
+</contributing_site>
+<contributing_site sequence_id="sequence_8" position="13" strand="none" pvalue="4.05e-04" >
+<left_flank>TATAACTCAG</left_flank>
+<site>
+<letter_ref letter_id="G"/>
+<letter_ref letter_id="T"/>
+<letter_ref letter_id="T"/>
+<letter_ref letter_id="G"/>
+<letter_ref letter_id="G"/>
+<letter_ref letter_id="A"/>
+<letter_ref letter_id="T"/>
+<letter_ref letter_id="A"/>
+<letter_ref letter_id="A"/>
+<letter_ref letter_id="A"/>
+<letter_ref letter_id="A"/>
+</site>
+<right_flank>TAATTTGTAC</right_flank>
+</contributing_site>
+</contributing_sites>
+</motif>
 </motifs>
 <scanned_sites_summary p_thresh="0.0001">
 <scanned_sites sequence_id="sequence_0" pvalue="1.22e-03" num_sites="1"><scanned_site motif_id="motif_1" strand="none" position="39" pvalue="3.06e-05"/>
--- a/test-data/meme_output_test2.html	Thu Aug 29 10:19:40 2024 +0000
+++ b/test-data/meme_output_test2.html	Mon Jul 14 21:33:56 2025 +0000
@@ -1,3 +1,9508 @@
+ * See http://stackoverflow.com/a/5450113/66387
+ * Does string multiplication like the perl x operator.
+ */
+function string_mult(pattern, count) {
+    if (count < 1) return '';
+    var result = '';
+    while (count > 1) {
+        if (count & 1) result += pattern;
+        count >>= 1, pattern += pattern;
+    }
+    return result + pattern;
+}
+
+/*
+ * See http://stackoverflow.com/questions/814613/how-to-read-get-data-from-a-url-using-javascript
+ * Slightly modified with information from
+ * https://developer.mozilla.org/en/DOM/window.location
+ */
+function parse_params() {
+  "use strict";
+  var search, queryStart, queryEnd, query, params, nvPairs, i, nv, n, v;
+  search = window.location.search;
+  queryStart = search.indexOf("?") + 1;
+  queryEnd   = search.indexOf("#") + 1 || search.length + 1;
+  query      = search.slice(queryStart, queryEnd - 1);
+
+  if (query === search || query === "") return {};
+
+  params  = {};
+  nvPairs = query.replace(/\+/g, " ").split("&");
+
+  for (i = 0; i < nvPairs.length; i++) {
+    nv = nvPairs[i].split("=");
+    n  = decodeURIComponent(nv[0]);
+    v  = decodeURIComponent(nv[1]);
+    // allow a name to be used multiple times
+    // storing each value in the array
+    if (!(n in params)) {
+      params[n] = [];
+    }
+    params[n].push(nv.length === 2 ? v : null);
+  }
+  return params;
+}
+
+/*
+ * coords
+ *
+ * Calculates the x and y offset of an element.
+ * From http://www.quirksmode.org/js/findpos.html
+ * with alterations to take into account scrolling regions
+ */
+function coords(elem) {
+  var myX = myY = 0;
+  if (elem.getBoundingClientRect) {
+    var rect;
+    rect = elem.getBoundingClientRect();
+    myX = rect.left + ((typeof window.pageXOffset !== "undefined") ?
+        window.pageXOffset : document.body.scrollLeft);
+    myY = rect.top + ((typeof window.pageYOffset !== "undefined") ?
+        window.pageYOffset : document.body.scrollTop);
+  } else {
+    // this fall back doesn't properly handle absolutely positioned elements
+    // inside a scrollable box
+    var node;
+    if (elem.offsetParent) {
+      // subtract all scrolling
+      node = elem;
+      do {
+        myX -= node.scrollLeft ? node.scrollLeft : 0;
+        myY -= node.scrollTop ? node.scrollTop : 0;
+      } while (node = node.parentNode);
+      // this will include the page scrolling (which is unwanted) so add it back on
+      myX += (typeof window.pageXOffset !== "undefined") ? window.pageXOffset : document.body.scrollLeft;
+      myY += (typeof window.pageYOffset !== "undefined") ? window.pageYOffset : document.body.scrollTop;
+      // sum up offsets
+      node = elem;
+      do {
+        myX += node.offsetLeft;
+        myY += node.offsetTop;
+      } while (node = node.offsetParent);
+    }
+  }
+  return [myX, myY];
+}
+
+/*
+ * position_popup
+ *
+ * Positions a popup relative to an anchor element.
+ *
+ * The available positions are:
+ * 0 - Centered below the anchor.
+ */
+function position_popup(anchor, popup, position) {
+  "use strict";
+  var a_x, a_y, a_w, a_h, p_x, p_y, p_w, p_h;
+  var a_xy, spacer, margin, scrollbar, page_w;
+  // define constants
+  spacer = 5;
+  margin = 15;
+  scrollbar = 15;
+  // define the positions and widths
+  a_xy = coords(anchor);
+  a_x = a_xy[0];
+  a_y = a_xy[1];
+  a_w = anchor.offsetWidth;
+  a_h = anchor.offsetHeight;
+  p_w = popup.offsetWidth;
+  p_h = popup.offsetHeight;
+  page_w = null;
+  if (window.innerWidth) {
+    page_w = window.innerWidth;
+  } else if (document.body) {
+    page_w = document.body.clientWidth;
+  }
+  // check the position type is defined
+  if (typeof position !== "number") {
+    position = 0;
+  }
+  // calculate the popup position
+  switch (position) {
+    case 1:
+      p_x = a_x + a_w + spacer;
+      p_y = a_y + (a_h / 2) - (p_h / 2);
+      break;
+    case 0:
+    default:
+      p_x = a_x + (a_w / 2) - (p_w / 2);
+      p_y = a_y + a_h + spacer;
+      break;
+  }
+  // constrain the popup position
+  if (p_x < margin) {
+    p_x = margin;
+  } else if (page_w != null && (p_x + p_w) > (page_w - margin - scrollbar)) {
+    p_x = page_w - margin - scrollbar - p_w;
+  }
+  if (p_y < margin) {
+    p_y = margin;
+  }
+  // position the popup
+  popup.style.left = p_x + "px";
+  popup.style.top = p_y + "px";
+}
+
+function lookup_help_popup(popup_id) {
+  var _body, pop, info;
+  pop = document.getElementById(popup_id);
+  if (pop == null) {
+    _body = document.getElementsByTagName("body")[0];
+    pop = document.createElement("div");
+    pop.className = "pop_content";
+    pop.id = popup_id;
+    pop.style.backgroundColor = "#FFC";
+    pop.style.borderColor = "black";
+    info = document.createElement("p");
+    info.style.fontWeight = "bold";
+    info.appendChild(document.createTextNode("Error: No popup for topic \"" + popup_id + "\"."));
+    pop.appendChild(info);
+    // this might cause problems with the menu, but as this only happens
+    // when something is already wrong I don't think that's too much of a problem
+    _body.insertBefore(pop, _body.firstChild);
+  }
+  if (document.getElementsByTagName('body')[0].hasAttribute("data-autobtns")) {
+    if (!/\bauto_buttons\b/.test(pop.className)) {
+      pop.className += " auto_buttons";
+      var back_btn_sec = document.createElement("div");
+      back_btn_sec.className = "nested_only pop_back_sec";
+      var back_btn = document.createElement("span");
+      back_btn.className = "pop_back";
+      back_btn.appendChild(document.createTextNode("<< back"));
+      back_btn.addEventListener("click", function(e) {
+        help_return();
+      }, false);
+      back_btn_sec.appendChild(back_btn);
+      pop.insertBefore(back_btn_sec, pop.firstChild);
+      var close_btn_sec = document.createElement("div");
+      close_btn_sec.className = "pop_close_sec";
+      var close_btn = document.createElement("span");
+      close_btn.className = "pop_close";
+      close_btn.appendChild(document.createTextNode("close"));
+      close_btn.addEventListener("click", function(e) {
+        help_popup();
+      }, false);
+      close_btn_sec.appendChild(close_btn);
+      pop.appendChild(close_btn_sec);
+    }
+  }
+  return pop;
+}
+
+/*
+ * help_popup
+ *
+ * Moves around help pop-ups so they appear
+ * below an activator.
+ */
+function help_popup(activator, popup_id) {
+  "use strict";
+  var pop;
+  // set default values
+  if (typeof help_popup.popup === "undefined") {
+    help_popup.popup = [];
+  }
+  if (typeof help_popup.activator === "undefined") {
+    help_popup.activator = null;
+  }
+  var last_pop = (help_popup.popup.length > 0 ? help_popup.popup[help_popup.popup.length - 1] : null);
+  if (typeof(activator) == "undefined") { // no activator so hide
+    if (last_pop != null) {
+      last_pop.style.display = 'none';
+      help_popup.popup = [];
+    }
+    return;
+  }
+  pop = lookup_help_popup(popup_id);
+  if (pop == last_pop) {
+    if (activator == help_popup.activator) {
+      //hide popup (as we've already shown it for the current help button)
+      last_pop.style.display = 'none';
+      help_popup.popup = [];
+      return; // toggling complete!
+    }
+  } else if (last_pop != null) {
+    //activating different popup so hide current one
+    last_pop.style.display = 'none';
+  }
+  help_popup.popup = [pop];
+  help_popup.activator = activator;
+  toggle_class(pop, "nested", false);
+  //must make the popup visible to measure it or it has zero width
+  pop.style.display = 'block';
+  position_popup(activator, pop);
+}
+
+/*
+ * help_refine
+ * 
+ * Intended for links within a help popup. Stores a stack of state so
+ * you can go back.
+ */
+function help_refine(popup_id) {
+  if (help_popup.popup == null || help_popup.popup.length == 0 || help_popup.activator == null) {
+    //throw new Error("Cannot refine a help popup when one is not shown!");
+    var pop = lookup_help_popup(popup_id);
+    var act_id = popup_id + '_act';
+    var activator = document.getElementById(act_id);
+    help_popup(activator, popup_id);
+  }
+  var pop = lookup_help_popup(popup_id);
+  var last_pop = help_popup.popup[help_popup.popup.length - 1];
+  if (pop == last_pop) return; // slightly odd, but no real cause for alarm
+  help_popup.popup.push(pop);
+  toggle_class(pop, "nested", true);
+  last_pop.style.display = "none";
+  //must make the popup visible to measure it or it has zero width
+  pop.style.display = "block";
+  position_popup(help_popup.activator, pop);
+}
+
+/*
+ * help_return
+ * 
+ * Intended for links within a help popup. Stores a stack of state so
+ * you can go back.
+ */
+function help_return() {
+  if (help_popup.popup == null || help_popup.popup.length == 0 || help_popup.activator == null) {
+    throw new Error("Can not return to a earlier help popup when one is not shown!");
+  }
+  var last_pop = help_popup.popup.pop();
+  last_pop.style.display = "none";
+  var pop = (help_popup.popup.length > 0 ? help_popup.popup[help_popup.popup.length - 1] : null);
+  if (pop != null) {
+    toggle_class(pop, "nested", help_popup.popup.length > 1);
+    pop.style.display = "block";
+    position_popup(help_popup.activator, pop);
+  } else {
+    help_popup.activator = null;
+  }
+}
+
+/*
+ * update_scroll_pad
+ *
+ * Creates padding at the bottom of the page to allow
+ * scrolling of anything into view.
+ */
+function update_scroll_pad() {
+  var page, pad;
+  page = (document.compatMode === "CSS1Compat") ? document.documentElement : document.body;
+  pad = $("scrollpad");
+  if (pad === null) {
+    pad = document.createElement("div");
+    pad.id = 'scrollpad';
+    document.getElementsByTagName('body')[0].appendChild(pad);
+  }
+  pad.style.height = Math.abs(page.clientHeight - 100) + "px";
+}
+
+function substitute_classes(node, remove, add) {
+  "use strict";
+  var list, all, i, cls, classes;
+  list = node.className.split(/\s+/);
+  all = {};
+  for (i = 0; i < list.length; i++) {
+    if (list[i].length > 0) all[list[i]] = true;
+  }
+  for (i = 0; i < remove.length; i++) {
+    if (all.hasOwnProperty(remove[i])) {
+      delete all[remove[i]];
+    }
+  }
+  for (i = 0; i < add.length; i++) {
+    all[add[i]] = true;
+  }
+  classes = "";
+  for (cls in all) {
+    classes += cls + " ";
+  }
+  node.className = classes;
+}
+
+/*
+ * toggle_class
+ *
+ * Adds or removes a class from the node. If the parameter 'enabled' is not 
+ * passed then the existence of the class will be toggled, otherwise it will be
+ * included if enabled is true.
+ */
+function toggle_class(node, cls, enabled) {
+  var classes = node.className;
+  var list = classes.replace(/^\s+/, '').replace(/\s+$/, '').split(/\s+/);
+  var found = false;
+  for (var i = 0; i < list.length; i++) {
+    if (list[i] == cls) {
+      list.splice(i, 1);
+      i--;
+      found = true;
+    }
+  }
+  if (typeof enabled == "undefined") {
+    if (!found) list.push(cls);
+  } else {
+    if (enabled) list.push(cls);
+  }
+  node.className = list.join(" ");
+}
+
+/*
+ * find_child
+ *
+ * Searches child nodes in depth first order and returns the first it finds
+ * with the className specified.
+ * TODO replace with querySelector
+ */
+function find_child(node, className) {
+  var pattern;
+  if (node == null || typeof node !== "object") {
+    return null;
+  }
+  if (typeof className === "string") {
+    pattern = new RegExp("\\b" + className + "\\b");
+  } else {
+    pattern = className;
+  }
+  if (node.nodeType == Node.ELEMENT_NODE && 
+      pattern.test(node.className)) {
+    return node;
+  } else {
+    var result = null;
+    for (var i = 0; i < node.childNodes.length; i++) {
+      result = find_child(node.childNodes[i], pattern);
+      if (result != null) break;
+    }
+    return result;
+  }
+}
+
+/*
+ * find_parent
+ *
+ * Searches parent nodes outwards from the node and returns the first it finds
+ * with the className specified.
+ */
+function find_parent(node, className) {
+  var pattern;
+  pattern = new RegExp("\\b" + className + "\\b");
+  do {
+    if (node.nodeType == Node.ELEMENT_NODE && 
+        pattern.test(node.className)) {
+      return node;
+    }
+  } while (node = node.parentNode);
+  return null;
+}
+
+/*
+ * find_parent_tag
+ *
+ * Searches parent nodes outwards from the node and returns the first it finds
+ * with the tag name specified. HTML tags should be specified in upper case.
+ */
+function find_parent_tag(node, tag_name) {
+  do {
+    if (node.nodeType == Node.ELEMENT_NODE && node.tagName == tag_name) {
+      return node;
+    }
+  } while (node = node.parentNode);
+  return null;
+}
+
+/*
+ * __toggle_help
+ *
+ * Uses the 'topic' property of the this object to
+ * toggle display of a help topic.
+ *
+ * This function is not intended to be called directly.
+ */
+function __toggle_help(e) {
+  if (!e) e = window.event;
+  if (e.type === "keydown") {
+    if (e.keyCode !== 13 && e.keyCode !== 32) {
+      return;
+    }
+    // stop a submit or something like that
+    e.preventDefault();
+  }
+
+  help_popup(this, this.getAttribute("data-topic"));
+}
+
+function setup_help_button(button) {
+  "use strict";
+  var topic;
+  if (button.hasAttribute("data-topic")) {
+    topic = button.getAttribute("data-topic");
+    if (document.getElementById(topic) != null) {
+      button.tabIndex = "0"; // make keyboard selectable
+      button.addEventListener("click", function() {
+        help_popup(button, topic);
+      }, false);
+      button.addEventListener("keydown", function(e) {
+        // toggle only on Enter or Spacebar, let other keys do their thing
+        if (e.keyCode !== 13 && e.keyCode !== 32) return;
+        // stop a submit or something like that
+        e.preventDefault();
+        help_popup(button, topic);
+      }, false);
+    } else {
+      button.style.visibility = "hidden";
+    }
+  }
+  button.className += " active";
+}
+
+/*
+ * help_button
+ *
+ * Makes a help button for the passed topic.
+ */
+function help_button(topic) {
+  var btn = document.createElement("div");
+  btn.className = "help";
+  btn.setAttribute("data-topic", topic);
+  setup_help_button(btn);
+  return btn;
+}
+
+/*
+ * prepare_download
+ *
+ * Sets the attributes of a link to setup a file download using the given content.
+ * If no link is provided then create one and click it.
+ */
+function prepare_download(content, mimetype, filename, link) {
+  "use strict";
+  // if no link is provided then create one and click it
+  var click_link = false;
+  if (!link) {
+    link = document.createElement("a");
+    click_link = true;
+  }
+  try {
+    // Use a BLOB to convert the text into a data URL.
+    // We could do this manually with a base 64 conversion.
+    // This will only be supported on modern browsers,
+    // hence the try block.
+    var blob = new Blob([content], {type: mimetype});
+    var reader = new FileReader();
+    reader.onloadend = function() {
+      // If we're lucky the browser will also support the download
+      // attribute which will let us suggest a file name to save the link.
+      // Otherwise it is likely that the filename will be unintelligible. 
+      link.setAttribute("download", filename);
+      link.href = reader.result;
+      if (click_link) {
+        // must add the link to click it
+        document.body.appendChild(link);
+        link.click();
+        document.body.removeChild(link);
+      }
+    }
+    reader.readAsDataURL(blob);
+  } catch (error) {
+    if (console && console.log) console.log(error);
+    // probably an old browser
+    link.href = "";
+    link.visible = false;
+  }
+}
+
+/*
+ * add_cell
+ *
+ * Add a cell to the table row.
+ */
+function add_cell(row, node, cls, click_action) {
+  var cell = row.insertCell(row.cells.length);
+  if (node) cell.appendChild(node);
+  if (cls && cls !== "") cell.className = cls;
+  if (click_action) cell.addEventListener("click", click_action, false);
+}
+
+/*
+ * add_header_cell
+ *
+ * Add a header cell to the table row.
+ */
+function add_header_cell(row, node, help_topic, cls, colspan, is_new) {
+  var th = document.createElement("th");
+  if (node) th.appendChild(node);
+  if (help_topic && help_topic !== "") th.appendChild(help_button(help_topic));
+  if (is_new && is_new !== "") {
+    var br = document.createElement("span");
+    br.innerHTML = "<br>";
+    th.appendChild(br);
+    var new_icon = document.createElement("img");
+    new_icon.src = new_icon_src;
+    new_icon.alt = "NEW";
+    th.appendChild(new_icon);
+  }
+  if (cls && cls !== "") th.className = cls;
+  if (typeof colspan == "number" && colspan > 1) th.colSpan = colspan;
+  row.appendChild(th);
+}
+
+/*
+ * add_text_cell
+ *
+ * Add a text cell to the table row.
+ */
+function add_text_cell(row, text, cls, action) {
+  var node = null;
+  if (typeof(text) != 'undefined') node = document.createTextNode(text);
+  add_cell(row, node, cls, action);
+}
+
+/*
+ * add_text_header_cell
+ *
+ * Add a text header cell to the table row.
+ */
+function add_text_header_cell(row, text, help_topic, cls, action, colspan, is_new) {
+  var node = null;
+  if (typeof(text) != 'undefined') {
+    var nbsp = (help_topic ? "\u00A0" : "");
+    var str = "" + text;
+    var parts = str.split(/\n/);
+    if (parts.length === 1) {
+      if (action) {
+        node = document.createElement("span");
+        node.appendChild(document.createTextNode(str + nbsp));
+      } else {
+        node = document.createTextNode(str + nbsp);
+      }
+    } else {
+      node = document.createElement("span");
+      for (var i = 0; i < parts.length; i++) {
+        if (i !== 0) {
+          node.appendChild(document.createElement("br"));
+        }
+        node.appendChild(document.createTextNode(parts[i]));
+      }
+    }
+    if (action) {
+      node.addEventListener("click", action, false);
+      node.style.cursor = "pointer";
+    }
+  }
+  add_header_cell(row, node, help_topic, cls, colspan, is_new);
+}
+
+function setup_help() {
+  "use strict";
+  var help_buttons, i;
+  help_buttons = document.querySelectorAll(".help:not(.active)");
+  for (i = 0; i < help_buttons.length; i++) {
+    setup_help_button(help_buttons[i]);
+  }
+}
+
+function setup_scrollpad() {
+  "use strict";
+  if (document.getElementsByTagName('body')[0].hasAttribute("data-scrollpad") && document.getElementById("scrollpad") == null) {
+    window.addEventListener("resize", update_scroll_pad, false);
+    update_scroll_pad();
+  }
+}
+
+// anon function to avoid polluting global scope
+(function() {
+  "use strict";
+  window.addEventListener("load", function load(evt) {
+    window.removeEventListener("load", load, false);
+    setup_help();
+    setup_scrollpad();
+  }, false);
+})();
+
+/*
+ *  make_link
+ *
+ *  Creates a text node and if a URL is specified it surrounds it with a link.
+ *  If the URL doesn't begin with "http://" it automatically adds it, as
+ *  relative links don't make much sense in this context.
+ */
+function make_link(text, url) {
+  var textNode = null;
+  var link = null;
+  if (typeof text !== "undefined" && text !== null) textNode = document.createTextNode(text);
+  if (typeof url === "string") {
+    if (url.indexOf("//") == -1) {
+      url = "http://" + url;
+    }
+    link = document.createElement('a');
+    link.href = url;
+    if (textNode) link.appendChild(textNode);
+    return link;
+  }
+  return textNode;
+}
+
+//
+// Function to create an HTML paragraph describing the 
+// MEME Suite background model source.
+//
+function make_background_source(title, source, text) {
+  var paraNode = document.createElement("P");
+  var titleNode = document.createElement("B");
+  var textNode1 = document.createTextNode("\u00A0\u00A0\u00A0\u00A0" + title + ": ");
+  titleNode.appendChild(textNode1);
+  var source_text = ((source == "--motif--") ? "the (first) motif file" : (source == "--nrdb--") ? "an old version of the NCBI non-redundant database" : (source == "--uniform--") ? "the uniform model" : (source == "--query--") ? "the query file" : (source == "--sequences--") ? "built from the (primary) sequences" : (source == "--control--") ? "built from the control (negative) sequences" : ((source == "--negatives--") ? "built from the negative (control) sequences" : "the file '" + source + "'"));
+  if (text) { return source_text; }
+  var textNode2 = document.createTextNode(source_text);
+  paraNode.appendChild(titleNode);
+  paraNode.appendChild(textNode2);
+  return paraNode;
+}
+
+// Function to create a help button
+function make_help_button(container, help_topic) {
+  container.appendChild(help_button(help_topic));
+}
+
+// Function to toggle display.
+function change_display(id) {
+  var element=document.getElementById(id);
+  element.style.display=(element.style.display=='none') ? element.style.display='inline' : element.style.display='none';
+}
+</script>
+    <script>
+      // 
+      // return true if any part of the passed element is visible in the viewport
+      //
+      function element_in_viewport(elem) {
+        var rect;
+        try {
+          rect = elem.getBoundingClientRect();
+        } catch (e) {
+          return false;
+        }
+        return (
+            rect.top < (window.innerHeight || document.body.clientHeight) &&
+            rect.bottom > 0 &&
+            rect.left < (window.innerWidth || document.body.clientWidth) &&
+            rect.right > 0
+            );
+      }
+
+      //
+      // 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 = 300;
+      // 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
+      //
+      var Drawable = function(elem, task) {
+        this.elem = elem;
+        this.task = task;
+      }
+
+      //
+      // Drawable.is_visible
+      //
+      // Determines if the element is visible in the viewport
+      //
+      Drawable.prototype.is_visible = function() {
+        return element_in_viewport(this.elem);
+      }
+
+      //
+      // Drawable.run
+      //
+      // Run the task held by the drawable
+      Drawable.prototype.run = function() {
+        if (this.task) this.task.run();
+        this.task = null;
+      }
+
+      //
+      // Drawable.run
+      //
+      // Run the task iff visible
+      // returns true if the task ran or has already run
+      Drawable.prototype.run_visible = function() {
+        if (this.task) {
+          if (element_in_viewport(this.elem)) {
+            this.task.run();
+            this.task = null;
+            return true;
+          }
+          return false;
+        } else {
+          return true;
+        }
+      }
+
+      //
+      // draw_on_screen
+      //
+      // Checks each drawable object and draws those on screen.
+      //
+      function draw_on_screen() {
+        var found = false;
+        for (var i = 0; i < drawable_list.length; i++) {
+          if (drawable_list[i].run_visible()) {
+            drawable_list.splice(i--, 1);
+            found = true;
+          }
+        }
+        return found;
+      }
+
+      //
+      // process_draw_tasks
+      //
+      // Called on a delay to process the next available
+      // 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()", 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) {
+        drawable = new Drawable(elem, task);
+        if (drawable.is_visible()) {
+          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);
+        }
+      }
+
+</script>
+    <script>
+function motif_logo_template(inputs) {
+  function _input(name) {
+    if (typeof inputs[name] === "undefined") {
+      throw new Error("Missing template variable: " + name);
+    }
+    return inputs[name];
+  }
+  return (
+"%!PS-Adobe-3.0 EPSF-3.0\n" +
+"%%Title: Sequence Logo : " + _input("TITLE") + "\n" +
+"%%Creator: " + _input("CREATOR") + "\n" +
+"%%CreationDate: " + _input("CREATIONDATE") + "\n" +
+"%%BoundingBox:   0  0  " + _input("BOUNDINGWIDTH") + " " + _input("BOUNDINGHEIGHT") + " \n" +
+"%%Pages: 0\n" +
+"%%DocumentFonts: \n" +
+"%%EndComments\n" +
+"\n" +
+"% ---- CONSTANTS ----\n" +
+"\/cmfactor 72 2.54 div def % defines points -> cm conversion\n" +
+"\/cm {cmfactor mul} bind def % defines centimeters\n" +
+"\n" +
+"% ---- VARIABLES ----\n" +
+"\n" +
+"% NA = Nucleic Acid, AA = Amino Acid\n" +
+"\/logoType (" + _input("LOGOTYPE") + ") def \n" +
+"\n" +
+"\/logoTitle (" + _input("TITLE") + ") def\n" +
+"\n" +
+"% Dimensions in cm\n" +
+"\/logoWidth " + _input("LOGOWIDTH") + " cm def\n" +
+"\/logoHeight " + _input("LOGOLINEHEIGHT") + " cm def\n" +
+"\/totalHeight " + _input("LOGOHEIGHT") + " cm def\n" +
+"\n" +
+"\/yaxis " + _input("YAXIS") + " def\n" +
+"\/yaxisLabel (" + _input("YAXISLABEL") + ") def\n" +
+"\/yaxisBits  " + _input("BARBITS") + " def % bits\n" +
+"\/yaxisTicBits " + _input("TICBITS") + " def\n" +
+"\n" +
+"\/xaxis " + _input("NUMBERING") + " def\n" +
+"\/xaxisLabel (" + _input("XAXISLABEL") + ") def\n" +
+"\/showEnds (" + _input("SHOWENDS") + ") def \n" +
+"\n" +
+"\/showFineprint true def\n" +
+"\/fineprint (" + _input("FINEPRINT") + ") def\n" +
+"\n" +
+"\/charsPerLine " + _input("CHARSPERLINE") + " def\n" +
+"\n" +
+"\/showingBox " + _input("SHOWINGBOX") + " def    \n" +
+"\/shrinking false def   % true falses\n" +
+"\/shrink  1.0 def\n" +
+"\/outline " + _input("OUTLINE") + " def\n" +
+"\n" +
+"\/IbeamFraction  " + _input("ERRORBARFRACTION") + " def\n" +
+"\/IbeamGray      0.50 def\n" +
+"\/IbeamLineWidth 0.5 def\n" +
+"\n" +
+"\/fontsize       " + _input("FONTSIZE") + " def\n" +
+"\/titleFontsize  " + _input("TITLEFONTSIZE") + " def\n" +
+"\/smallFontsize  " + _input("SMALLFONTSIZE") + " def\n" +
+"\n" +
+"\/topMargin      " + _input("TOPMARGIN") + " cm def\n" +
+"\/bottomMargin   " + _input("BOTTOMMARGIN") + " cm def\n" +
+"\n" +
+"\/defaultColor [0 0 0] def \n" +
+"\n" +
+_input("COLORDICT") + "\n" +
+"\n" +
+"\/colorDict fullColourDict def\n" +
+"\n" +
+"% ---- DERIVED PARAMETERS ----\n" +
+"\n" +
+"\/leftMargin\n" +
+"  fontsize 3.5 mul\n" +
+"\n" +
+"def \n" +
+"\n" +
+"\/rightMargin \n" +
+"  %Add extra room if showing ends\n" +
+"  showEnds (false) eq { fontsize}{fontsize 1.5 mul} ifelse\n" +
+"def\n" +
+"\n" +
+"\/yaxisHeight \n" +
+"  logoHeight \n" +
+"  bottomMargin sub  \n" +
+"  topMargin sub\n" +
+"def\n" +
+"\n" +
+"\/ticWidth fontsize 2 div def\n" +
+"\n" +
+"\/pointsPerBit yaxisHeight yaxisBits div  def\n" +
+"\n" +
+"\/stackMargin 1 def\n" +
+"\n" +
+"% Do not add space aroung characters if characters are boxed\n" +
+"\/charRightMargin \n" +
+"  showingBox { 0.0 } {stackMargin} ifelse\n" +
+"def\n" +
+"\n" +
+"\/charTopMargin \n" +
+"  showingBox { 0.0 } {stackMargin} ifelse\n" +
+"def\n" +
+"\n" +
+"\/charWidth\n" +
+"  logoWidth\n" +
+"  leftMargin sub\n" +
+"  rightMargin sub\n" +
+"  charsPerLine div\n" +
+"  charRightMargin sub\n" +
+"def\n" +
+"\n" +
+"\/charWidth4 charWidth 4 div def\n" +
+"\/charWidth2 charWidth 2 div def\n" +
+"\n" +
+"\/stackWidth \n" +
+"  charWidth charRightMargin add\n" +
+"def\n" +
+" \n" +
+"\/numberFontsize \n" +
+"  fontsize charWidth lt {fontsize}{charWidth} ifelse\n" +
+"def\n" +
+"\n" +
+"% movements to place 5'\/N and 3'\/C symbols\n" +
+"\/leftEndDeltaX  fontsize neg         def\n" +
+"\/leftEndDeltaY  fontsize 1.5 mul neg def\n" +
+"\/rightEndDeltaX fontsize 0.25 mul     def\n" +
+"\/rightEndDeltaY leftEndDeltaY        def\n" +
+"\n" +
+"% Outline width is proporional to charWidth, \n" +
+"% but no less that 1 point\n" +
+"\/outlinewidth \n" +
+"  charWidth 32 div dup 1 gt  {}{pop 1} ifelse\n" +
+"def\n" +
+"\n" +
+"\n" +
+"% ---- PROCEDURES ----\n" +
+"\n" +
+"\/StartLogo { \n" +
+"  % Save state\n" +
+"  save \n" +
+"  gsave \n" +
+"\n" +
+"  % Print Logo Title, top center \n" +
+"  gsave \n" +
+"    SetStringFont\n" +
+"\n" +
+"    logoWidth 2 div\n" +
+"    logoTitle\n" +
+"    stringwidth pop 2 div sub\n" +
+"    totalHeight\n" +
+"    titleFontsize sub\n" +
+"    moveto\n" +
+"\n" +
+"    logoTitle\n" +
+"    show\n" +
+"  grestore\n" +
+"\n" +
+"  % Print X-axis label, bottom center\n" +
+"  gsave\n" +
+"    SetStringFont\n" +
+"\n" +
+"    logoWidth 2 div\n" +
+"    xaxisLabel\n" +
+"    stringwidth pop 2 div sub\n" +
+"    0\n" +
+"    titleFontsize 3 div\n" +
+"    add\n" +
+"    moveto\n" +
+"\n" +
+"    xaxisLabel\n" +
+"    show\n" +
+"  grestore\n" +
+"\n" +
+"  % Show Fine Print\n" +
+"  showFineprint {\n" +
+"    gsave\n" +
+"      SetSmallFont\n" +
+"      logoWidth\n" +
+"        fineprint stringwidth pop sub\n" +
+"        smallFontsize sub\n" +
+"          smallFontsize 3 div\n" +
+"      moveto\n" +
+"    \n" +
+"      fineprint show\n" +
+"    grestore\n" +
+"  } if\n" +
+"\n" +
+"  % Move to lower left corner of last line, first stack\n" +
+"  leftMargin bottomMargin translate\n" +
+"\n" +
+"  % Move above first line ready for StartLine \n" +
+"  0 totalHeight translate\n" +
+"\n" +
+"  SetLogoFont\n" +
+"} bind def\n" +
+"\n" +
+"\/EndLogo { \n" +
+"  grestore \n" +
+"  showpage \n" +
+"  restore \n" +
+"} bind def\n" +
+"\n" +
+"\n" +
+"\/StartLine { \n" +
+"  % move down to the bottom of the line:\n" +
+"  0 logoHeight neg translate\n" +
+"  \n" +
+"  gsave \n" +
+"    yaxis { MakeYaxis } if\n" +
+"    xaxis { showEnds (true) eq {ShowLeftEnd} if } if\n" +
+"} bind def\n" +
+"\n" +
+"\/EndLine{ \n" +
+"    xaxis { showEnds (true) eq {ShowRightEnd} if } if\n" +
+"  grestore \n" +
+"} bind def\n" +
+"\n" +
+"\n" +
+"\/MakeYaxis {\n" +
+"  gsave    \n" +
+"    stackMargin neg 0 translate\n" +
+"    ShowYaxisBar\n" +
+"    ShowYaxisLabel\n" +
+"  grestore\n" +
+"} bind def\n" +
+"\n" +
+"\n" +
+"\/ShowYaxisBar { \n" +
+"  gsave  \n" +
+"    SetStringFont\n" +
+"\n" +
+"    \/str 10 string def % string to hold number  \n" +
+"    \/smallgap stackMargin 2 div def\n" +
+"\n" +
+"    % Draw first tic and bar\n" +
+"    gsave    \n" +
+"      ticWidth neg 0 moveto \n" +
+"      ticWidth 0 rlineto \n" +
+"      0 yaxisHeight rlineto\n" +
+"      stroke\n" +
+"    grestore\n" +
+"\n" +
+"   \n" +
+"    % Draw the tics\n" +
+"    % initial increment limit proc for\n" +
+"    0 yaxisTicBits yaxisBits abs %cvi\n" +
+"    {\/loopnumber exch def\n" +
+"\n" +
+"      % convert the number coming from the loop to a string\n" +
+"      % and find its width\n" +
+"      loopnumber 10 str cvrs\n" +
+"      \/stringnumber exch def % string representing the number\n" +
+"\n" +
+"      stringnumber stringwidth pop\n" +
+"      \/numberwidth exch def % width of number to show\n" +
+"\n" +
+"      \/halfnumberheight\n" +
+"         stringnumber CharBoxHeight 2 div\n" +
+"      def\n" +
+"\n" +
+"      numberwidth % move back width of number\n" +
+"      neg loopnumber pointsPerBit mul % shift on y axis\n" +
+"      halfnumberheight sub % down half the digit\n" +
+"\n" +
+"      moveto % move back the width of the string\n" +
+"\n" +
+"      ticWidth neg smallgap sub % Move back a bit more  \n" +
+"      0 rmoveto % move back the width of the tic  \n" +
+"\n" +
+"      stringnumber show\n" +
+"      smallgap 0 rmoveto % Make a small gap  \n" +
+"\n" +
+"      % now show the tic mark\n" +
+"      0 halfnumberheight rmoveto % shift up again\n" +
+"      ticWidth 0 rlineto\n" +
+"      stroke\n" +
+"    } for\n" +
+"  grestore\n" +
+"} bind def\n" +
+"\n" +
+"\/ShowYaxisLabel {\n" +
+"  gsave\n" +
+"    SetStringFont\n" +
+"\n" +
+"    % How far we move left depends on the size of\n" +
+"    % the tic labels.\n" +
+"    \/str 10 string def % string to hold number  \n" +
+"    yaxisBits yaxisTicBits div cvi yaxisTicBits mul \n" +
+"    str cvs stringwidth pop\n" +
+"    ticWidth 1.5 mul  add neg  \n" +
+"\n" +
+"\n" +
+"    yaxisHeight\n" +
+"    yaxisLabel stringwidth pop\n" +
+"    sub 2 div\n" +
+"\n" +
+"    translate\n" +
+"    90 rotate\n" +
+"    0 0 moveto\n" +
+"    yaxisLabel show\n" +
+"  grestore\n" +
+"} bind def\n" +
+"\n" +
+"\n" +
+"\/StartStack {  % <stackNumber> startstack\n" +
+"  xaxis {MakeNumber}{pop} ifelse\n" +
+"  gsave\n" +
+"} bind def\n" +
+"\n" +
+"\/EndStack {\n" +
+"  grestore\n" +
+"  stackWidth 0 translate\n" +
+"} bind def\n" +
+"\n" +
+"\n" +
+"% Draw a character whose height is proportional to symbol bits\n" +
+"\/MakeSymbol{ % charbits character MakeSymbol\n" +
+"  gsave\n" +
+"    \/char exch def\n" +
+"    \/bits exch def\n" +
+"\n" +
+"    \/bitsHeight \n" +
+"       bits pointsPerBit mul \n" +
+"    def\n" +
+"\n" +
+"    \/charHeight \n" +
+"       bitsHeight charTopMargin sub\n" +
+"       dup \n" +
+"       0.0 gt {}{pop 0.0} ifelse % if neg replace with zero \n" +
+"    def \n" +
+" \n" +
+"    charHeight 0.0 gt {\n" +
+"      char SetColor\n" +
+"      charWidth charHeight char ShowChar\n" +
+"\n" +
+"      showingBox { % Unfilled box\n" +
+"        0 0 charWidth charHeight false ShowBox\n" +
+"      } if\n" +
+"\n" +
+"\n" +
+"    } if\n" +
+"\n" +
+"  grestore\n" +
+"\n" +
+"  0 bitsHeight translate \n" +
+"} bind def\n" +
+"\n" +
+"\n" +
+"\/ShowChar { % <width> <height> <char> ShowChar\n" +
+"  gsave\n" +
+"    \/tc exch def    % The character\n" +
+"    \/ysize exch def % the y size of the character\n" +
+"    \/xsize exch def % the x size of the character\n" +
+"\n" +
+"    \/xmulfactor 1 def \n" +
+"    \/ymulfactor 1 def\n" +
+"    \/limmulfactor 0.01 def\n" +
+"    \/drawable true def\n" +
+"\n" +
+"  \n" +
+"    % if ysize is negative, make everything upside down!\n" +
+"    ysize 0 lt {\n" +
+"      % put ysize normal in this orientation\n" +
+"      \/ysize ysize abs def\n" +
+"      xsize ysize translate\n" +
+"      180 rotate\n" +
+"    } if\n" +
+"\n" +
+"    shrinking {\n" +
+"      xsize 1 shrink sub 2 div mul\n" +
+"        ysize 1 shrink sub 2 div mul translate \n" +
+"\n" +
+"      shrink shrink scale\n" +
+"    } if\n" +
+"\n" +
+"    % Calculate the font scaling factors\n" +
+"    % Loop twice to catch small correction due to first scaling\n" +
+"    2 {\n" +
+"      gsave\n" +
+"        xmulfactor ymulfactor scale\n" +
+"      \n" +
+"        ysize % desired size of character in points\n" +
+"        tc CharBoxHeight \n" +
+"        dup 0.0 ne {\n" +
+"          div % factor by which to scale up the character\n" +
+"          \/ymulfactor exch def\n" +
+"        } % end if\n" +
+"        {pop pop}\n" +
+"        ifelse\n" +
+"\n" +
+"        xsize % desired size of character in points\n" +
+"        tc CharBoxWidth  \n" +
+"        dup 0.0 ne {\n" +
+"          div % factor by which to scale up the character\n" +
+"          \/xmulfactor exch def\n" +
+"        } % end if\n" +
+"        {pop pop}\n" +
+"        ifelse\n" +
+"      grestore\n" +
+"      % if the multiplication factors get too small we need to avoid a crash\n" +
+"      xmulfactor limmulfactor lt {\n" +
+"        \/xmulfactor 1 def\n" +
+"        \/drawable false def\n" +
+"      } if\n" +
+"      ymulfactor limmulfactor lt {\n" +
+"        \/ymulfactor 1 def\n" +
+"        \/drawable false def\n" +
+"      } if\n" +
+"    } repeat\n" +
+"\n" +
+"    % Adjust horizontal position if the symbol is an I\n" +
+"    tc (I) eq {\n" +
+"      charWidth 2 div % half of requested character width\n" +
+"      tc CharBoxWidth 2 div % half of the actual character\n" +
+"      sub 0 translate\n" +
+"      % Avoid x scaling for I \n" +
+"      \/xmulfactor 1 def \n" +
+"    } if\n" +
+"\n" +
+"\n" +
+"    % ---- Finally, draw the character\n" +
+"    drawable { \n" +
+"      newpath\n" +
+"      xmulfactor ymulfactor scale\n" +
+"\n" +
+"      % Move lower left corner of character to start point\n" +
+"      tc CharBox pop pop % llx lly : Lower left corner\n" +
+"      exch neg exch neg\n" +
+"      moveto\n" +
+"\n" +
+"      outline {  % outline characters:\n" +
+"        outlinewidth setlinewidth\n" +
+"        tc true charpath\n" +
+"        gsave 1 setgray fill grestore\n" +
+"        clip stroke\n" +
+"      } { % regular characters\n" +
+"        tc show\n" +
+"      } ifelse\n" +
+"    } if\n" +
+"\n" +
+"  grestore\n" +
+"} bind def\n" +
+"\n" +
+"\n" +
+"\/ShowBox { % x1 y1 x2 y2 filled ShowBox\n" +
+"  gsave\n" +
+"    \/filled exch def \n" +
+"    \/y2 exch def\n" +
+"    \/x2 exch def\n" +
+"    \/y1 exch def\n" +
+"    \/x1 exch def\n" +
+"    newpath\n" +
+"    x1 y1 moveto\n" +
+"    x2 y1 lineto\n" +
+"    x2 y2 lineto\n" +
+"    x1 y2 lineto\n" +
+"    closepath\n" +
+"\n" +
+"    clip\n" +
+"    \n" +
+"    filled {\n" +
+"      fill\n" +
+"    }{ \n" +
+"      0 setgray stroke   \n" +
+"    } ifelse\n" +
+"\n" +
+"  grestore\n" +
+"} bind def\n" +
+"\n" +
+"\n" +
+"\/MakeNumber { % number MakeNumber\n" +
+"  gsave\n" +
+"    SetNumberFont\n" +
+"    stackWidth 0 translate\n" +
+"    90 rotate % rotate so the number fits\n" +
+"    dup stringwidth pop % find the length of the number\n" +
+"    neg % prepare for move\n" +
+"    stackMargin sub % Move back a bit\n" +
+"    charWidth (0) CharBoxHeight % height of numbers\n" +
+"    sub 2 div %\n" +
+"    moveto % move back to provide space\n" +
+"    show\n" +
+"  grestore\n" +
+"} bind def\n" +
+"\n" +
+"\n" +
+"\/Ibeam{ % heightInBits Ibeam\n" +
+"  gsave\n" +
+"    % Make an Ibeam of twice the given height in bits\n" +
+"    \/height exch  pointsPerBit mul def \n" +
+"    \/heightDRAW height IbeamFraction mul def\n" +
+"\n" +
+"    IbeamLineWidth setlinewidth\n" +
+"    IbeamGray setgray \n" +
+"\n" +
+"    charWidth2 height neg translate\n" +
+"    ShowIbar\n" +
+"    newpath\n" +
+"      0 0 moveto\n" +
+"      0 heightDRAW rlineto\n" +
+"    stroke\n" +
+"    newpath\n" +
+"      0 height moveto\n" +
+"      0 height rmoveto\n" +
+"      currentpoint translate\n" +
+"    ShowIbar\n" +
+"    newpath\n" +
+"    0 0 moveto\n" +
+"    0 heightDRAW neg rlineto\n" +
+"    currentpoint translate\n" +
+"    stroke\n" +
+"  grestore\n" +
+"} bind def\n" +
+"\n" +
+"\n" +
+"\/ShowIbar { % make a horizontal bar\n" +
+"  gsave\n" +
+"    newpath\n" +
+"      charWidth4 neg 0 moveto\n" +
+"      charWidth4 0 lineto\n" +
+"    stroke\n" +
+"  grestore\n" +
+"} bind def\n" +
+"\n" +
+"\n" +
+"\/ShowLeftEnd {\n" +
+"  gsave\n" +
+"    SetStringFont\n" +
+"    leftEndDeltaX leftEndDeltaY moveto\n" +
+"    logoType (NA) eq {(5) show ShowPrime} if\n" +
+"    logoType (AA) eq {(N) show} if\n" +
+"  grestore\n" +
+"} bind def\n" +
+"\n" +
+"\n" +
+"\/ShowRightEnd { \n" +
+"  gsave\n" +
+"    SetStringFont\n" +
+"    rightEndDeltaX rightEndDeltaY moveto\n" +
+"    logoType (NA) eq {(3) show ShowPrime} if\n" +
+"    logoType (AA) eq {(C) show} if\n" +
+"  grestore\n" +
+"} bind def\n" +
+"\n" +
+"\n" +
+"\/ShowPrime {\n" +
+"  gsave\n" +
+"    SetPrimeFont\n" +
+"    (\\242) show \n" +
+"  grestore\n" +
+"} bind def\n" +
+"\n" +
+" \n" +
+"\/SetColor{ % <char> SetColor\n" +
+"  dup colorDict exch known {\n" +
+"    colorDict exch get aload pop setrgbcolor\n" +
+"  } {\n" +
+"    pop\n" +
+"    defaultColor aload pop setrgbcolor\n" +
+"  } ifelse \n" +
+"} bind def\n" +
+"\n" +
+"% define fonts\n" +
+"\/SetTitleFont {\/Times-Bold findfont titleFontsize scalefont setfont} bind def\n" +
+"\/SetLogoFont  {\/Helvetica-Bold findfont charWidth  scalefont setfont} bind def\n" +
+"\/SetStringFont{\/Helvetica-Bold findfont fontsize scalefont setfont} bind def\n" +
+"\/SetPrimeFont {\/Symbol findfont fontsize scalefont setfont} bind def\n" +
+"\/SetSmallFont {\/Helvetica findfont smallFontsize scalefont setfont} bind def\n" +
+"\n" +
+"\/SetNumberFont {\n" +
+"    \/Helvetica-Bold findfont \n" +
+"    numberFontsize\n" +
+"    scalefont\n" +
+"    setfont\n" +
+"} bind def\n" +
+"\n" +
+"%Take a single character and return the bounding box\n" +
+"\/CharBox { % <char> CharBox <lx> <ly> <ux> <uy>\n" +
+"  gsave\n" +
+"    newpath\n" +
+"    0 0 moveto\n" +
+"    % take the character off the stack and use it here:\n" +
+"    true charpath \n" +
+"    flattenpath \n" +
+"    pathbbox % compute bounding box of 1 pt. char => lx ly ux uy\n" +
+"    % the path is here, but toss it away ...\n" +
+"  grestore\n" +
+"} bind def\n" +
+"\n" +
+"\n" +
+"% The height of a characters bounding box\n" +
+"\/CharBoxHeight { % <char> CharBoxHeight <num>\n" +
+"  CharBox\n" +
+"  exch pop sub neg exch pop\n" +
+"} bind def\n" +
+"\n" +
+"\n" +
+"% The width of a characters bounding box\n" +
+"\/CharBoxWidth { % <char> CharBoxHeight <num>\n" +
+"  CharBox\n" +
+"  pop exch pop sub neg \n" +
+"} bind def\n" +
+"\n" +
+"% Set the colour scheme to be faded to indicate trimming\n" +
+"\/MuteColour {\n" +
+"  \/colorDict mutedColourDict def\n" +
+"} def\n" +
+"\n" +
+"% Restore the colour scheme to the normal colours\n" +
+"\/RestoreColour {\n" +
+"  \/colorDict fullColourDict def\n" +
+"} def\n" +
+"\n" +
+"% Draw the background for a trimmed section\n" +
+"% takes the number of columns as a parameter\n" +
+"\/DrawTrimBg { % <num> DrawTrimBox\n" +
+"  \/col exch def\n" +
+"  \n" +
+"  \/boxwidth \n" +
+"    col stackWidth mul \n" +
+"  def\n" +
+" \n" +
+"  gsave\n" +
+"    0.97 setgray\n" +
+"\n" +
+"    newpath\n" +
+"    0 0 moveto\n" +
+"    boxwidth 0 rlineto\n" +
+"    0 yaxisHeight rlineto\n" +
+"    0 yaxisHeight lineto\n" +
+"    closepath\n" +
+"    \n" +
+"    fill\n" +
+"  grestore\n" +
+"} def\n" +
+"\n" +
+"\/DrawTrimEdge {\n" +
+"  gsave\n" +
+"    0.2 setgray\n" +
+"    [2] 0 setdash\n" +
+"\n" +
+"    newpath\n" +
+"    0 0 moveto\n" +
+"    0 yaxisHeight lineto\n" +
+"    \n" +
+"    stroke\n" +
+"\n" +
+"} def\n" +
+"\n" +
+"\n" +
+"% Deprecated names\n" +
+"\/startstack {StartStack} bind  def\n" +
+"\/endstack {EndStack}     bind def\n" +
+"\/makenumber {MakeNumber} bind def\n" +
+"\/numchar { MakeSymbol }  bind def\n" +
+"\n" +
+"%%EndProlog\n" +
+"\n" +
+"%%Page: 1 1\n" +
+"StartLogo\n" +
+"\n" +
+_input("DATA") + "\n" +
+"\n" +
+"EndLogo\n" +
+"\n" +
+"%%EOF\n"
+  );
+}</script>
+    <script>
+//======================================================================
+// start Alphabet object
+//======================================================================
+var Alphabet = function(alphabet, background) {
+  "use strict";
+  var i, j, sym, aliases, complement, comp_e_sym, ambigs, generate_background;
+  generate_background = (background == null);
+  if (generate_background) {
+    background = [];
+    for (i = 0; i < alphabet.ncore; i++) background[i] = 1.0 / alphabet.ncore;
+  } else if (alphabet.ncore != background.length) {
+    throw new Error("The background length does not match the alphabet length.");
+  }
+  this.name = alphabet.name;
+  this.like = (alphabet.like != null ? alphabet.like.toUpperCase() : null);
+  this.ncore = alphabet.ncore;
+  this.symbols = alphabet.symbols;
+  this.background = background;
+  this.genbg = generate_background;
+  this.encode = {};
+  this.encode2core = {};
+  this.complement = {};
+  // check if all symbols are same case
+  var seen_uc = false;
+  var seen_lc = false;
+  var check_case = function (syms) {
+    var s, sym;
+    if (typeof syms === "string") {
+      for (s = 0; s < syms.length; s++) {
+        sym = syms.charAt(s);
+        if (sym >= 'a' && sym <= 'z') seen_lc = true;
+        else if (sym >= 'A' && sym <= 'Z') seen_uc = true;
+      }
+    }
+  };
+  for (i = 0; i < this.symbols.length; i++) {
+    check_case(this.symbols[i].symbol);
+    check_case(this.symbols[i].aliases);
+  }
+  // now map symbols to indexes
+  var update_array = function(array, syms, index) {
+    var s, sym;
+    if (typeof syms === "string") {
+      for (s = 0; s < syms.length; s++) {
+        sym = syms.charAt(s);
+        array[sym] = index;
+        // when only a single case is used, then encode as case insensitive
+        if (seen_uc != seen_lc) {
+          if (sym >= 'a' && sym <= 'z') {
+            array[sym.toUpperCase()] = index;
+          } else if (sym >= 'A' && sym <= 'Z') {
+            array[sym.toLowerCase()] = index;
+          }
+        }
+      }
+    }
+  }
+  // map core symbols to index
+  for (i = 0; i < this.ncore; i++) {
+    update_array(this.encode2core, this.symbols[i].symbol, i);
+    update_array(this.encode, this.symbols[i].symbol, i);
+    update_array(this.encode2core, this.symbols[i].aliases, i);
+    update_array(this.encode, this.symbols[i].aliases, i);
+  }
+  // map ambiguous symbols to index
+  ambigs = {};
+  for (i = this.ncore; i < this.symbols.length; i++) {
+    update_array(this.encode, this.symbols[i].symbol, i);
+    update_array(this.encode, this.symbols[i].aliases, i);
+    ambigs[this.symbols[i].equals] = i;
+  }
+  // determine complements
+  for (i = 0; i < this.ncore; i++) {
+    complement = this.symbols[i].complement;
+    if (typeof complement === "string") {
+      this.complement[i] = this.encode2core[complement];
+    }
+  }
+  next_symbol:
+  for (i = this.ncore; i < this.symbols.length; i++) {
+    complement = "";
+    for (j = 0; j < this.symbols[i].equals.length; j++) {
+      comp_e_sym = this.complement[this.encode2core[this.symbols[i].equals.charAt(j)]];
+      if (typeof comp_e_sym !== "number") continue next_symbol;
+      complement += this.symbols[comp_e_sym].symbol;
+    }
+    complement = complement.split("").sort().join("");
+    if (typeof ambigs[complement] === "number") {
+      this.complement[i] = ambigs[complement];
+    }
+  }
+  // determine case insensitivity
+  this.case_insensitive = true;
+  if (seen_uc == seen_lc) {
+    // when there is a mixture of cases it probably won't
+    // be case insensitive but we still need to check
+    loop:
+    for (i = 0; i < this.symbols.length; i++) {
+      sym = this.symbols[i].symbol;
+      if (sym >= 'A' && sym <= 'Z') {
+        if (this.encode[sym.toLowerCase()] != i) {
+          this.case_insensitive = false;
+          break loop;
+        }
+      } else if (sym >= 'a' && sym <= 'z') {
+        if (this.encode[sym.toUpperCase()] != i) {
+          this.case_insensitive = false;
+          break loop;
+        }
+      }
+      aliases = this.symbols[i].aliases;
+      if (aliases != null) {
+        for (j = 0; j < aliases.length; j++) {
+          sym = aliases.charAt(j);
+          if (sym >= 'A' && sym <= 'Z') {
+            if (this.encode[sym.toLowerCase()] != i) {
+              this.case_insensitive = false;
+              break loop;
+            }
+          } else if (sym >= 'a' && sym <= 'z') {
+            if (this.encode[sym.toUpperCase()] != i) {
+              this.case_insensitive = false;
+              break loop;
+            }
+          }
+        }
+      }
+    }
+  }
+  // normalise aliases to remove the prime symbol and eliminate
+  // the alternate cases when the alphabet is case insensitive
+  var seen, out;
+  for (i = 0; i < this.symbols.length; i++) {
+    sym = this.symbols[i].symbol;
+    aliases = this.symbols[i].aliases;
+    if (typeof aliases != "string") aliases = "";
+    seen = {};
+    out = [];
+    if (this.case_insensitive) {
+      sym = sym.toUpperCase();
+      aliases = aliases.toUpperCase();
+    }
+    seen[sym] = true;
+    for (j = 0; j < aliases.length; j++) {
+      if (!seen[aliases.charAt(j)]) {
+        seen[aliases.charAt(j)] = true;
+        out.push(aliases.charAt(j));
+      }
+    }
+    this.symbols[i].aliases = out.sort().join("");
+  }
+};
+// return the name of the alphabet
+Alphabet.prototype.get_alphabet_name = function() {
+  return this.name;
+};
+// return if the alphabet can be complemented
+Alphabet.prototype.has_complement = function() {
+  return (typeof this.symbols[0].complement === "string");
+};
+// return true if an uppercase letter has the same meaning as the lowercase form
+Alphabet.prototype.is_case_insensitive = function() {
+  return this.case_insensitive;
+};
+// return the information content of an alphabet letter
+Alphabet.prototype.get_ic = function() {
+  return Math.log(this.ncore) / Math.LN2;
+};
+// return the count of the core alphabet symbols
+Alphabet.prototype.get_size_core = function() {
+  return this.ncore;
+};
+// return the count of all alphabet symbols
+Alphabet.prototype.get_size_full = function() {
+  return this.symbols.length;
+};
+// return the symbol for the given alphabet index
+Alphabet.prototype.get_symbol = function(alph_index) {
+  "use strict";
+  if (alph_index < 0 || alph_index >= this.symbols.length) {
+    throw new Error("Alphabet index out of bounds");
+  }
+  return this.symbols[alph_index].symbol;
+};
+// return the aliases for the given alphabet index
+Alphabet.prototype.get_aliases = function(alph_index) {
+  "use strict";
+  if (alph_index < 0 || alph_index >= this.symbols.length) {
+    throw new Error("Alphabet index out of bounds");
+  }
+  var sym_obj = this.symbols[alph_index];
+  return (sym_obj.aliases != null ? sym_obj.aliases : "");
+};
+// return the name for the given alphabet index
+Alphabet.prototype.get_name = function(alph_index) {
+  "use strict";
+  var sym;
+  if (alph_index < 0 || alph_index >= this.symbols.length) {
+    throw new Error("Alphabet index out of bounds");
+  }
+  sym = this.symbols[alph_index];
+  return (typeof sym.name === "string" ? sym.name : sym.symbol);
+};
+// return the alphabet it is like or null
+Alphabet.prototype.get_like = function() {
+  "use strict";
+  return this.like;
+};
+// return the index of the complement for the given alphabet index
+Alphabet.prototype.get_complement = function(alph_index) {
+  var comp_e_sym = this.complement[alph_index];
+  if (typeof comp_e_sym === "number") {
+    return comp_e_sym;
+  } else {
+    return -1;
+  }
+};
+// return a string containing the core symbols
+Alphabet.prototype.get_symbols = function() {
+  "use strict";
+  var i, core_symbols;
+  core_symbols = "";
+  for (i = 0; i < this.ncore; i++) {
+    core_symbols += this.symbols[i].symbol;
+  }
+  return core_symbols;
+};
+// return if the background was not a uniform generated background
+Alphabet.prototype.has_bg = function() {
+  "use strict";
+  return !this.genbg;
+};
+// get the background frequency for the index
+Alphabet.prototype.get_bg_freq = function(alph_index) {
+  "use strict";
+  var freq, i, symbols;
+  if (alph_index >= 0) {
+    if (alph_index < this.ncore) {
+      return this.background[alph_index];
+    } else if (alph_index < this.symbols.length) {
+      freq = 0;
+      symbols = this.symbols[alph_index].equals;
+      for (i = 0; i < symbols.length; i++) {
+        freq += this.background[this.encode2core[symbols.charAt(i)]];
+      }
+      return freq;
+    } 
+  }
+  throw new Error("The alphabet index is out of range.");
+};
+// get the colour of the index
+Alphabet.prototype.get_colour = function(alph_index) {
+  "use strict";
+  if (alph_index < 0 || alph_index >= this.symbols.length) {
+    throw new Error("BAD_ALPHABET_INDEX");
+  }
+  if (typeof this.symbols[alph_index].colour != "string") {
+    return "black";
+  }
+  return "#" + this.symbols[alph_index].colour;
+};
+// get the rgb components of the colour at the index
+Alphabet.prototype.get_rgb = function(alph_index) {
+  "use strict";
+  if (alph_index < 0 || alph_index >= this.symbols.length) {
+    throw new Error("BAD_ALPHABET_INDEX");
+  }
+  if (typeof this.symbols[alph_index].colour != "string") {
+    return {"red": 0, "green": 0, "blue": 0};
+  }
+  var colour = this.symbols[alph_index].colour;
+  var red = parseInt(colour.substr(0, 2), 16) / 255;
+  var green = parseInt(colour.substr(2, 2), 16) / 255;
+  var blue = parseInt(colour.substr(4, 2), 16) / 255;
+  return {"red": red, "green": green, "blue": blue};
+};
+// convert a symbol into the index
+Alphabet.prototype.get_index = function(letter) {
+  "use strict";
+  var alph_index;
+  alph_index = this.encode[letter];
+  if (typeof alph_index === "undefined") {
+    return -1;
+  }
+  return alph_index;
+};
+// convert a symbol into the list of core indexes that it equals
+Alphabet.prototype.get_indexes = function(letter) {
+  "use strict";
+  var alph_index, comprise_str, i, comprise_list;
+  alph_index = this.encode[letter];
+  if (typeof alph_index === "undefined") {
+    throw new Error("Unknown letter");
+  }
+  comprise_str = this.symbols[alph_index].equals;
+  comprise_list = [];
+  if (typeof comprise_str == "string") {
+    for (i = 0; i < comprise_str.length; i++) {
+      comprise_list.push(this.encode2core[comprise_str.charAt(i)]);
+    }
+  } else {
+    comprise_list.push(alph_index);
+  }
+  return comprise_list;
+};
+// check if a symbol is the primary way of representing the symbol in the alphabet
+Alphabet.prototype.is_prime_symbol = function(letter) {
+  var alph_index;
+  alph_index = this.encode[letter];
+  if (alph_index == null) return false;
+  if (this.is_case_insensitive()) {
+    return (this.symbols[alph_index].symbol.toUpperCase() == letter.toUpperCase());
+  } else {
+    return (this.symbols[alph_index].symbol == letter);
+  }
+};
+// compare 2 alphabets
+Alphabet.prototype.equals = function(other) {
+  "use strict";
+  var i, sym1, sym2;
+  // first check that it's actually an alphabet object
+  if (!(typeof other === "object" && other != null && other instanceof Alphabet)) {
+    return false;
+  }
+  // second shortcircuit if it's the same object
+  if (this === other) return true;
+  // compare
+  if (this.name !== other.name) return false;
+  if (this.ncore !== other.ncore) return false;
+  if (this.symbols.length !== other.symbols.length) return false;
+  for (i = 0; i < this.symbols.length; i++) {
+    sym1 = this.symbols[i];
+    sym2 = other.symbols[i];
+    if (sym1.symbol !== sym2.symbol) return false;
+    if (sym1.aliases !== sym2.aliases) return false;
+    if (sym1.name !== sym2.name) return false;
+    if (typeof sym1.colour !== typeof sym2.colour || 
+        (typeof sym1.colour === "string" && typeof sym2.colour === "string" &&
+         parseInt(sym1.colour, 16) != parseInt(sym2.colour, 16))) {
+      return false;
+    }
+    if (sym1.complement !== sym2.complement) return false;
+    if (sym1.equals !== sym2.equals) return false;
+  }
+  return true;
+};
+Alphabet.prototype.check_core_subset = function(super_alph) {
+  var complement_same = true;
+  var seen_set = {};
+  var sub_i, sub_symbol, super_i, super_symbol;
+  for (sub_i = 0; sub_i < this.ncore; sub_i++) {
+    sub_symbol = this.symbols[sub_i];
+    super_i = super_alph.encode[sub_symbol.symbol]; 
+    if (super_i == null) return 0;
+    super_symbol = super_alph.symbols[super_i];
+    if (seen_set[super_i]) return 0;
+    seen_set[super_i] = true;
+    // check complement
+    if (sub_symbol.complement != null && super_symbol.complement != null) {
+      if (super_alph.encode[sub_symbol.complement] != super_alph.encode[super_symbol.complement]) {
+        complement_same = false;
+      }
+    } else if (sub_symbol.complement != null || super_symbol.complement != null) {
+      complement_same = false;
+    }
+  }
+  return (complement_same ? 1 : -1);
+};
+// convert a sequence to its reverse complement
+Alphabet.prototype.invcomp_seq = function(seq) {
+  "use strict";
+  var syms, i, e_sym, comp_e_sym;
+  if (!this.has_complement()) throw new Error("Alphabet must be complementable");
+  syms = seq.split("");
+  for (i = 0; i < syms.length; i++) {
+    e_sym = this.encode[syms[i]];
+    if (typeof e_sym === "undefined") {
+      e_sym = this.ncore; // wildcard
+    }
+    comp_e_sym = this.complement[e_sym];
+    if (typeof comp_e_sym === "undefined") {
+      comp_e_sym = e_sym; // not complementable
+    }
+    syms[i] = this.symbols[comp_e_sym].symbol;
+  }
+  return syms.reverse().join("");
+};
+// convert the alphabet to the text version
+Alphabet.prototype.as_text = function() {
+  "use strict";
+  function name_as_text(name) {
+    var i, c, out;
+    out = "\"";
+    for (i = 0; i < name.length; i++) {
+      c = name.charAt(i);
+      if (c == "\"") {
+        out += "\\\"";
+      } else if (c == "/") {
+        out += "\\/";
+      } else if (c == "\\") {
+        out += "\\\\";
+      } else {
+        out += c;
+      }
+    }
+    out += "\"";
+    return out;
+  }
+  function symbol_as_text(sym) {
+    var out;
+    out = sym.symbol;
+    if (typeof sym.name === "string" && sym.name != sym.symbol) {
+      out += " " + name_as_text(sym.name);
+    }
+    if (typeof sym.colour === "string") {
+      out += " " + sym.colour;
+    }
+    return out;
+  }
+  var out, i, j, c, sym;
+  out = "";
+  // output core symbols with 2 way complements
+  for (i = 0; i < this.ncore; i++) {
+    c = this.complement[i];
+    if (typeof c === "number" && i < c && this.complement[c] === i) {
+      out += symbol_as_text(this.symbols[i]) + " ~ " + symbol_as_text(this.symbols[c]) + "\n";  
+    }
+  }
+  // output core symbols with no complement
+  for (i = 0; i < this.ncore; i++) {
+    if (typeof this.complement[i] === "undefined") {
+      out += symbol_as_text(this.symbols[i]) + "\n";
+    }
+  }
+  // output ambiguous symbols that have comprising characters
+  for (i = this.ncore; i < this.symbols.length; i++) {
+    if (this.symbols[i].equals.length == 0) break;
+    out += symbol_as_text(this.symbols[i]) + " = " + this.symbols[i].equals + "\n";
+    if (typeof this.symbols[i].aliases === "string") {
+      for (j = 0; j < this.symbols[i].aliases.length; j++) {
+        if (this.symbols[i].aliases.charAt(j) == this.symbols[i].symbol) continue;
+        out += this.symbols[i].aliases.charAt(j) + " = " + this.symbols[i].equals + "\n";
+      }
+    }
+  }
+  // output aliases of core symbols
+  for (i = 0; i < this.ncore; i++) {
+    if (typeof this.symbols[i].aliases === "string") {
+      for (j = 0; j < this.symbols[i].aliases.length; j++) {
+        if (this.symbols[i].aliases.charAt(j) == this.symbols[i].symbol) continue;
+        out += this.symbols[i].aliases.charAt(j) + " = " + this.symbols[i].symbol + "\n";
+      }
+    }
+  }
+  // output gap symbols
+  i = this.symbols.length - 1;
+  if (this.symbols[i].equals.length == 0) {
+    out += symbol_as_text(this.symbols[i]) + " =\n";
+    if (typeof this.symbols[i].aliases === "string") {
+      for (j = 0; j < this.symbols[i].aliases.length; j++) {
+        if (this.symbols[i].aliases.charAt(j) == this.symbols[i].symbol) continue;
+        out += this.symbols[i].aliases.charAt(j) + " =\n";
+      }
+    }
+  }
+  return out;
+};
+// output the alphabet as it appears in minimal MEME format
+Alphabet.prototype.as_meme = function() {
+  "use strict";
+  function name_as_text(name) {
+    var i, c, out;
+    out = "\"";
+    for (i = 0; i < name.length; i++) {
+      c = name.charAt(i);
+      if (c == "\"") {
+        out += "\\\"";
+      } else if (c == "/") {
+        out += "\\/";
+      } else if (c == "\\") {
+        out += "\\\\";
+      } else {
+        out += c;
+      }
+    }
+    out += "\"";
+    return out;
+  }
+  if (this.equals(AlphStd.DNA)) {
+    return "ALPHABET= ACGT\n";
+  } else if (this.equals(AlphStd.PROTEIN)) {
+    return "ALPHABET= ACDEFGHIKLMNPQRSTVWY\n";
+  } else {
+    return "ALPHABET" + 
+      (this.name != null ? " " + name_as_text(this.name) : "") + 
+      (this.like != null ? " " + this.like + "-LIKE" : "") + "\n" +
+      this.as_text() + "END ALPHABET\n";
+  }
+};
+
+// Returns a table showing all the letters in the alphabet
+Alphabet.prototype.as_table = function() {
+  "use strict";
+  var i, j, row, th, td, aliases, equals, sym;
+  var table = document.createElement("table");
+  // create the core symbol header
+  row = table.insertRow(table.rows.length);
+  th = document.createElement("th");
+  th.appendChild(document.createTextNode("Symbol(s)"));
+  row.appendChild(th);
+  th = document.createElement("th");
+  th.appendChild(document.createTextNode("Name"));
+  row.appendChild(th);
+  th = document.createElement("th");
+  if (this.has_complement()) {
+    th.appendChild(document.createTextNode("Complement"));
+  }
+  row.appendChild(th);
+  // list the core symbols
+  for (i = 0; i < this.ncore; i++) {
+    row = table.insertRow(table.rows.length);
+    td = document.createElement("td");
+    if (this.symbols[i].colour != null) {
+      td.style.color = '#' + this.symbols[i].colour;
+    }
+    td.appendChild(document.createTextNode(this.symbols[i].symbol));
+    aliases = this.get_aliases(i);
+    if (aliases.length > 0) {
+      td.appendChild(document.createTextNode(' ' + aliases.split('').join(' ')));
+    }
+    row.appendChild(td);
+    td = document.createElement("td");
+    if (this.symbols[i].name != null) {
+      td.appendChild(document.createTextNode(this.symbols[i].name));
+    }
+    row.appendChild(td);
+    td = document.createElement("td");
+    if (this.symbols[i].complement != null) {
+      td.style.color = this.get_colour(this.get_index(this.symbols[i].complement));
+      td.appendChild(document.createTextNode(this.symbols[i].complement));
+    }
+    row.appendChild(td);
+  }
+  // create the ambiguous symbol header
+  row = table.insertRow(table.rows.length);
+  th = document.createElement("th");
+  th.appendChild(document.createTextNode("Symbol(s)"));
+  row.appendChild(th);
+  th = document.createElement("th");
+  th.appendChild(document.createTextNode("Name"));
+  row.appendChild(th);
+  th = document.createElement("th");
+  th.appendChild(document.createTextNode("Matches"));
+  row.appendChild(th);
+  // list the ambiguous symbols
+  for (i = this.ncore; i < this.symbols.length; i++) {
+    row = table.insertRow(table.rows.length);
+    td = document.createElement("td");
+    if (this.symbols[i].colour != null) {
+      td.style.color = '#' + this.symbols[i].colour;
+    }
+    td.appendChild(document.createTextNode(this.symbols[i].symbol));
+    aliases = this.get_aliases(i);
+    if (aliases.length > 0) {
+      td.appendChild(document.createTextNode(' ' + aliases.split('').join(' ')));
+    }
+    row.appendChild(td);
+    td = document.createElement("td");
+    if (this.symbols[i].name != null) {
+      td.appendChild(document.createTextNode(this.symbols[i].name));
+    }
+    row.appendChild(td);
+    td = document.createElement("td");
+    equals = this.symbols[i].equals.split('');
+    for (j = 0; j < equals.length; j++) {
+      if (j != 0) td.appendChild(document.createTextNode(' '));
+      sym = document.createElement("span");
+      sym.style.color = this.get_colour(this.get_index(equals[j]));
+      sym.appendChild(document.createTextNode(equals[j]));
+      td.appendChild(sym);
+    }
+    row.appendChild(td);
+  }
+  return table;
+};
+
+// returns a dictionary of the colours for EPS
+Alphabet.prototype._as_eps_dict = function() {
+  "use strict";
+  var i, sym, rgb;
+  var out = "/fullColourDict <<\n";
+  for (i = 0; i < this.ncore; i++) {
+    sym = this.get_symbol(i);
+    sym = sym.replace(/\\/g, "\\\\");
+    sym = sym.replace(/\(/g, "\\(");
+    sym = sym.replace(/\)/g, "\\)");
+    rgb = this.get_rgb(i);
+    out += " (" + sym + ") [" + rgb.red.toFixed(4) + " " + rgb.green.toFixed(4) + " " + rgb.blue.toFixed(4) + "]\n";
+  }
+  out += ">> def\n";
+  out += "/mutedColourDict <<\n";
+  for (i = 0; i < this.ncore; i++) {
+    sym = this.get_symbol(i);
+    sym = sym.replace(/\\/g, "\\\\");
+    sym = sym.replace(/\(/g, "\\(");
+    sym = sym.replace(/\)/g, "\\)");
+    rgb = Alphabet.lighten_colour(this.get_rgb(i));
+    out += " (" + sym + ") [" + rgb.red.toFixed(4) + " " + rgb.green.toFixed(4) + " " + rgb.blue.toFixed(4) + "]\n";
+  }
+  out += ">> def\n";
+  return out;
+};
+
+// return the alphabet name or a list of primary symbols
+Alphabet.prototype.toString = function() {
+  "use strict";
+  if (this.name != null) {
+    return this.name;
+  } else {
+    return this.get_symbols();
+  }
+};
+
+//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+// Helper functions
+//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+// Convert a colour specified in RGB colourspace values into LAB colourspace
+Alphabet.rgb2lab = function(rgb) {
+  "use strict";
+  var xyzHelper, labHelper;
+  // XYZ helper
+  xyzHelper = function(value) {
+    if (value > 0.0445) {
+      value = (value + 0.055) / 1.055;
+      value = Math.pow(value, 2.4);
+    } else {
+      value /= 12.92;
+    }
+    value *= 100;
+    return value;
+  };
+  // lab helper
+  labHelper = function(value) {
+    if (value > 0.008856) {
+      value = Math.pow(value, 1.0 / 3.0);
+    } else {
+      value = (7.787 * value) + (16.0 / 116.0);
+    }
+    return value;
+  };
+  // convert into XYZ colourspace
+  var c1, c2, c3;
+  if (typeof rgb == "number") {
+    c1 = xyzHelper(((rgb >> 16) & 0xFF) / 255.0);
+    c2 = xyzHelper(((rgb >> 8) & 0xFF) / 255.0);
+    c3 = xyzHelper((rgb & 0xFF) / 255.0);
+  } else {
+    c1 = xyzHelper(rgb.red);
+    c2 = xyzHelper(rgb.green);
+    c3 = xyzHelper(rgb.blue);
+  }
+  var x = (c1 * 0.4124) + (c2 * 0.3576) + (c3 * 0.1805);
+  var y = (c1 * 0.2126) + (c2 * 0.7152) + (c3 * 0.0722);
+  var z = (c1 * 0.0193) + (c2 * 0.1192) + (c3 * 0.9505);
+  // convert into Lab colourspace
+  c1 = labHelper(x / 95.047);
+  c2 = labHelper(y / 100.0);
+  c3 = labHelper(z / 108.883);
+  var l = (116.0 * c2) - 16;
+  var a = 500.0 * (c1 - c2);
+  var b = 200.0 * (c2 - c3);
+  return {"l": l, "a": a, "b": b};
+};
+
+// Convert a colour specified in HSV colourspace into RGB colourspace
+Alphabet.hsv2rgb = function(hue, sat, value, output_object) {
+  // achromatic (grey)
+  var r = value;
+  var g = value;
+  var b = value;
+  if (sat != 0) {
+    var h = hue / 60.0;
+    var i = Math.floor(h);
+    var f = h - i;
+    var p = value * (1.0 - sat);
+    var q = value * (1.0 - (sat * f));
+    var t = value * (1.0 - (sat * (1.0 - f)));
+    if (i == 0) {
+      r = value;
+      g = t;
+      b = p;
+    } else if (i == 1) {
+      r = q;
+      g = value;
+      b = p;
+    } else if (i == 2) {
+      r = p;
+      g = value;
+      b = t;
+    } else if (i == 3) {
+      r = p;
+      g = q;
+      b = value;
+    } else if (i == 4) {
+      r = t;
+      g = p;
+      b = value;
+    } else {
+      r = value;
+      g = p;
+      b = q;
+    }
+  }
+  if (output_object) {
+    return {"red": r, "green": g, "blue": b};
+  } else {
+    return (Math.floor(r * 255) << 15) | (Math.floor(g * 255) << 8) | (Math.floor(b * 255));
+  }
+};
+
+// Calculate a distance score between two colours in LAB colourspace
+Alphabet.lab_dist = function(lab1, lab2) {
+  var c1 = Math.sqrt((lab1.l * lab1.l) + (lab1.a * lab1.a));
+  var c2 = Math.sqrt((lab2.l * lab2.l) + (lab2.a * lab2.a));
+  var dc = c1 - c2;
+  var dl = lab1.l - lab2.l;
+  var da = lab1.a - lab2.a;
+  var db = lab1.b - lab2.b;
+  // we don't want NaN due to rounding errors so fudge things a bit...
+  var dh = 0;
+  var dh_squared = (da * da) + (db * db) - (dc * dc);
+  if (dh_squared > 0) {
+    dh = Math.sqrt(dh_squared);
+  }
+  var first = dl;
+  var second = dc / (1.0 + (0.045 * c1));
+  var third = dh / (1.0 + (0.015 * c1));
+  return Math.sqrt((first * first) + (second * second) + (third * third));
+};
+
+// convert an RGB value into a HSL value
+Alphabet.rgb2hsl = function(rgb) {
+  "use strict";
+  var min, max, delta, h, s, l, r, g, b;
+  if (typeof rgb == "number") {
+    r = ((rgb >> 16) & 0xFF) / 255.0;
+    g = ((rgb >> 8) & 0xFF) / 255.0;
+    b = (rgb & 0xFF) / 255.0;
+  } else {
+    r = rgb.red;
+    g = rgb.green;
+    b = rgb.blue;
+  }
+  min = Math.min(r, g, b);
+  max = Math.max(r, g, b);
+  delta = max - min;
+  l = min + (delta / 2);
+  if (max == min) {
+    h = 0; // achromatic (grayscale)
+    s = 0;
+  } else {
+    if (l > 0.5) {
+      s = delta / (2 - max - min);
+    } else {
+      s = delta / (max + min);
+    }
+    if (max == r) {
+      h = (g - b) / delta;
+      if (g < b) h += 6;
+    } else if (max == g) {
+      h = ((b - r) / delta) + 2;
+    } else {
+      h = ((r - g) / delta) + 4;
+    }
+    h /= 6;
+  }
+  return {"h": h, "s": s, "l": l};
+};
+
+// convert a HSL value into an RGB value
+Alphabet.hsl2rgb = function(hsl, output_object) {
+  "use strict";
+  function _hue(p, q, t) {
+    "use strict";
+    if (t < 0) t += 1;
+    else if (t > 1) t -= 1;
+    if (t < (1.0 / 6.0)) {
+      return p + ((q - p) * 6.0 * t);
+    } else if (t < 0.5) {
+      return q;
+    } else if (t < (2.0 / 3.0)) {
+      return p + ((q - p) * ((2.0 / 3.0) - t) * 6.0);
+    } else {
+      return p;
+    }
+  }
+  var r, g, b, p, q;
+  if (hsl.s == 0) {
+    // achromatic (grayscale)
+    r = hsl.l;
+    g = hsl.l;
+    b = hsl.l;
+  } else {
+    if (hsl.l < 0.5) {
+      q = hsl.l * (1 + hsl.s);
+    } else {
+      q = hsl.l + hsl.s - (hsl.l * hsl.s);
+    }
+    p = (2 * hsl.l) - q;
+    r = _hue(p, q, hsl.h + (1.0 / 3.0));
+    g = _hue(p, q, hsl.h);
+    b = _hue(p, q, hsl.h - (1.0 / 3.0));
+  }
+  if (output_object) {
+    return {"red": r, "green": g, "blue": b};
+  } else {
+    return (Math.floor(r * 255) << 15) | (Math.floor(g * 255) << 8) | (Math.floor(b * 255));
+  }
+};
+
+Alphabet.lighten_colour = function(rgb) {
+  "use strict";
+  var hsl = Alphabet.rgb2hsl(rgb);
+  hsl.l += (1.0 - hsl.l) * 2 / 3;
+  return Alphabet.hsl2rgb(hsl, typeof rgb != "number");
+};
+
+//======================================================================
+// end Alphabet object
+//======================================================================
+
+//======================================================================
+// start StandardAlphabet object
+//======================================================================
+
+// an extension of the alphabet object to support some additional fields 
+// only present in standard alphabets.
+var StandardAlphabet = function(enum_code, enum_name, alphabet_data) {
+  Alphabet.apply(this, [alphabet_data]);
+  this.enum_code = enum_code;
+  this.enum_name = enum_name;
+};
+StandardAlphabet.prototype = Alphabet.prototype;
+StandardAlphabet.prototype.constructor = StandardAlphabet;
+
+// A unique code for this standard alphabet.
+// This code will be a power of 2 to enable creation of bitsets for
+// a selection of standard alphabets.
+StandardAlphabet.prototype.get_code = function() {
+  return this.enum_code;
+};
+
+// A unique name for this standard alphabet.
+// this name will be all upper case and the same as the property that
+// refers to this alphabet in the AlphStd collection.
+StandardAlphabet.prototype.get_enum = function() {
+  return this.enum_name;
+};
+
+//======================================================================
+// end StandardAlphabet object
+//======================================================================
+
+// A collection of standard alphabets.
+var AlphStd = {
+  RNA: new StandardAlphabet(1, "RNA", {
+    "name": "RNA",
+    "like": "RNA",
+    "ncore": 4,
+    "symbols": [
+      {"symbol": "A", "name": "Adenine", "colour": "CC0000"},
+      {"symbol": "C", "name": "Cytosine", "colour": "0000CC"},
+      {"symbol": "G", "name": "Guanine", "colour": "FFB300"},
+      {"symbol": "U", "name": "Uracil", "colour": "008000",
+        "aliases": "T"},
+      {"symbol": "N", "name": "Any base", "equals": "ACGU", "aliases": "X."},
+      {"symbol": "V", "name": "Not U", "equals": "ACG"},
+      {"symbol": "H", "name": "Not G", "equals": "ACU"},
+      {"symbol": "D", "name": "Not C", "equals": "AGU"},
+      {"symbol": "B", "name": "Not A", "equals": "CGU"},
+      {"symbol": "M", "name": "Amino", "equals": "AC"},
+      {"symbol": "R", "name": "Purine", "equals": "AG"},
+      {"symbol": "W", "name": "Weak", "equals": "AU"}, 
+      {"symbol": "S", "name": "Strong", "equals": "CG"},
+      {"symbol": "Y", "name": "Pyrimidine", "equals": "CU"},
+      {"symbol": "K", "name": "Keto", "equals": "GU"}
+    ]
+  }), 
+  DNA: new StandardAlphabet(2, "DNA", {
+    "name": "DNA",
+    "like": "DNA",
+    "ncore": 4,
+    "symbols": [
+      {"symbol": "A", "name": "Adenine", "colour": "CC0000", "complement": "T"},
+      {"symbol": "C", "name": "Cytosine", "colour": "0000CC", "complement": "G"},
+      {"symbol": "G", "name": "Guanine", "colour": "FFB300", "complement": "C"},
+      {"symbol": "T", "name": "Thymine", "colour": "008000", "complement": "A",
+        "aliases": "U"},
+      {"symbol": "N", "name": "Any base", "equals": "ACGT", "aliases": "X."},
+      {"symbol": "V", "name": "Not T", "equals": "ACG"},
+      {"symbol": "H", "name": "Not G", "equals": "ACT"},
+      {"symbol": "D", "name": "Not C", "equals": "AGT"},
+      {"symbol": "B", "name": "Not A", "equals": "CGT"},
+      {"symbol": "M", "name": "Amino", "equals": "AC"},
+      {"symbol": "R", "name": "Purine", "equals": "AG"},
+      {"symbol": "W", "name": "Weak", "equals": "AT"}, 
+      {"symbol": "S", "name": "Strong", "equals": "CG"},
+      {"symbol": "Y", "name": "Pyrimidine", "equals": "CT"},
+      {"symbol": "K", "name": "Keto", "equals": "GT"}
+    ]
+  }), 
+  PROTEIN: new StandardAlphabet(4, "PROTEIN", {
+    "name": "Protein",
+    "like": "PROTEIN",
+    "ncore": 20,
+    "symbols": [
+      {"symbol": "A", "name": "Alanine", "colour": "0000CC"},
+      {"symbol": "C", "name": "Cysteine", "colour": "0000CC"},
+      {"symbol": "D", "name": "Aspartic acid", "colour": "FF00FF"},
+      {"symbol": "E", "name": "Glutamic acid", "colour": "FF00FF"},
+      {"symbol": "F", "name": "Phenylalanine", "colour": "0000CC"},
+      {"symbol": "G", "name": "Glycine", "colour": "FFB300"},
+      {"symbol": "H", "name": "Histidine", "colour": "FFCCCC"},
+      {"symbol": "I", "name": "Isoleucine", "colour": "0000CC"},
+      {"symbol": "K", "name": "Lysine", "colour": "CC0000"},
+      {"symbol": "L", "name": "Leucine", "colour": "0000CC"},
+      {"symbol": "M", "name": "Methionine", "colour": "0000CC"},
+      {"symbol": "N", "name": "Asparagine", "colour": "008000"},
+      {"symbol": "P", "name": "Proline", "colour": "FFFF00"},
+      {"symbol": "Q", "name": "Glutamine", "colour": "008000"},
+      {"symbol": "R", "name": "Arginine", "colour": "CC0000"},
+      {"symbol": "S", "name": "Serine", "colour": "008000"},
+      {"symbol": "T", "name": "Threonine", "colour": "008000"},
+      {"symbol": "V", "name": "Valine", "colour": "0000CC"},
+      {"symbol": "W", "name": "Tryptophan", "colour": "0000CC"},
+      {"symbol": "Y", "name": "Tyrosine", "colour": "33E6CC"},
+      {"symbol": "X", "name": "Any amino acid", "equals": "ACDEFGHIKLMNPQRSTVWY", "aliases": "*."},
+      {"symbol": "B", "name": "Asparagine or Aspartic acid", "equals": "DN"}, 
+      {"symbol": "Z", "name": "Glutamine or Glutamic acid", "equals": "EQ"}, 
+      {"symbol": "J", "name": "Leucine or Isoleucine", "equals": "IL"}
+    ]
+  })
+};
+
+//======================================================================
+// start Symbol object
+//======================================================================
+var Symbol = function(alph_index, scale, alphabet) {
+  "use strict";
+  //variable prototype
+  this.symbol = alphabet.get_symbol(alph_index);
+  this.scale = scale;
+  this.colour = alphabet.get_colour(alph_index);
+};
+
+Symbol.prototype.get_symbol = function() {
+  "use strict";
+  return this.symbol;
+};
+
+Symbol.prototype.get_scale = function() {
+  "use strict";
+  return this.scale;
+};
+
+Symbol.prototype.get_colour = function() {
+  "use strict";
+  return this.colour;
+};
+
+Symbol.prototype.toString = function() {
+  "use strict";
+  return this.symbol + " " + (Math.round(this.scale*1000)/10) + "%";
+};
+
+function compare_symbol(sym1, sym2) {
+  "use strict";
+  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
+//======================================================================
+var Pspm = function(matrix, name, ltrim, rtrim, nsites, evalue, pssm, alt, pgm) {
+  "use strict";
+  var row, col, data, row_sum, delta, evalue_re;
+  if (typeof name !== "string") {
+    name = "";
+  }
+  this.name = name;
+  //construct
+  if (matrix instanceof Pspm) {
+    // copy constructor
+    this.alph_length = matrix.alph_length;
+    this.motif_length = matrix.motif_length;
+    this.name = matrix.name;
+    this.alt = matrix.alt;
+    this.nsites = matrix.nsites;
+    this.evalue = matrix.evalue;
+    this.ltrim = matrix.ltrim;
+    this.rtrim = matrix.rtrim;
+    this.pspm = [];
+    this.pgm = matrix.pgm;
+    for (row = 0; row < matrix.motif_length; row++) {
+      this.pspm[row] = [];
+      for (col = 0; col < matrix.alph_length; col++) {
+        this.pspm[row][col] = matrix.pspm[row][col];
+      }
+    }
+    if (matrix.pssm != null) {
+      this.pssm = [];
+      for (row = 0; row < matrix.motif_length; row++) {
+        this.pspm[row] = [];
+        for (col = 0; col < matrix.alph_length; col++) {
+          this.pssm[row][col] = matrix.pssm[row][col];
+        }
+      }
+    }
+  } else {
+    // check parameters
+    if (ltrim == null) {
+      ltrim = 0;
+    } else if (typeof ltrim !== "number" || ltrim % 1 !== 0 || ltrim < 0) {
+      throw new Error("ltrim must be a non-negative integer, got: " + ltrim);
+    }
+    if (rtrim == null) {
+      rtrim = 0;
+    } else if (typeof rtrim !== "number" || rtrim % 1 !== 0 || rtrim < 0) {
+      throw new Error("rtrim must be a non-negative integer, got: " + rtrim);
+    }
+    if (nsites != null) {
+      if (typeof nsites !== "number" || nsites < 0) {
+        throw new Error("nsites must be a positive number, got: " + nsites);
+      } else if (nsites == 0) {
+        nsites = null;
+      }
+    }
+    if (evalue != null) {
+      if (typeof evalue === "number") {
+        if (evalue < 0) {
+          throw new Error("evalue must be a non-negative number, got: " + evalue);
+        }
+      } else if (typeof evalue === "string") {
+        evalue_re = /^((?:[+]?[0-9]*\.?[0-9]+(?:[eE][-+]?[0-9]+)?)|inf)$/;
+        if (!evalue_re.test(evalue)) {
+          throw new Error("evalue must be a non-negative number, got: " + evalue);
+        }
+      } else {
+        throw new Error("evalue must be a non-negative number, got: " + evalue);
+      }
+    }
+    // set properties
+    this.name = name;
+    this.alt = alt;
+    this.nsites = nsites;
+    this.evalue = evalue;
+    this.ltrim = ltrim;
+    this.rtrim = rtrim;
+    this.pgm = pgm;
+    if (typeof matrix === "string") {
+      // string constructor
+      data = parse_pspm_string(matrix);
+      this.alph_length = data["alph_length"];
+      this.motif_length = data["motif_length"];
+      this.pspm = data["pspm"];
+      if (this.evalue == null) {
+        if (data["evalue"] != null) {
+          this.evalue = data["evalue"];
+        } else {
+          this.evalue = 0;
+        }
+      }
+      if (this.nsites == null) {
+        if (typeof data["nsites"] === "number") {
+          this.nsites = data["nsites"];
+        } else {
+          this.nsites = 20;
+        }
+      }
+    } else {
+      // assume pspm is a nested array
+      this.motif_length = matrix.length;
+      this.alph_length = (matrix.length > 0 ? matrix[0].length : 0);
+      if (this.nsites == null) {
+        this.nsites = 20;
+      }
+      if (this.evalue == null) {
+        this.evalue = 0;
+      }
+      this.pspm = [];
+      // copy pspm and check
+      for (row = 0; row < this.motif_length; row++) {
+        if (this.alph_length != matrix[row].length) {
+          throw new Error("COLUMN_MISMATCH");
+        }
+        this.pspm[row] = [];
+        row_sum = 0;
+        for (col = 0; col < this.alph_length; col++) {
+          this.pspm[row][col] = matrix[row][col];
+          row_sum += this.pspm[row][col];
+        }
+        delta = 0.1;
+        if (isNaN(row_sum) || (row_sum > 1 && (row_sum - 1) > delta) || 
+            (row_sum < 1 && (1 - row_sum) > delta)) {
+          throw new Error("INVALID_SUM");
+        }
+      }
+      // copy pssm
+      if (pssm != null) {
+        this.pssm = [];
+        for (row = 0; row < this.motif_length; row++) {
+          this.pssm[row] = [];
+          for (col = 0; col < this.alph_length; col++) {
+            this.pssm[row][col] = pssm[row][col];
+          }
+        }
+      }
+    }
+  }
+};
+
+Pspm.prototype.copy = function() {
+  "use strict";
+  return new Pspm(this);
+};
+
+Pspm.prototype.reverse = function() {
+  "use strict";
+  var x, y, temp, temp_trim;
+  //reverse
+  x = 0;
+  y = this.motif_length-1;
+  while (x < y) {
+    temp = this.pspm[x];
+    this.pspm[x] = this.pspm[y];
+    this.pspm[y] = temp;
+    x++;
+    y--;
+  }
+  // reverse pssm (if defined)
+  if (typeof this.pssm !== "undefined") {
+    //reverse
+    x = 0;
+    y = this.motif_length-1;
+    while (x < y) {
+      temp = this.pssm[x];
+      this.pspm[x] = this.pssm[y];
+      this.pssm[y] = temp;
+      x++;
+      y--;
+    }
+  }
+  //swap triming
+  temp_trim = this.ltrim;
+  this.ltrim = this.rtrim;
+  this.rtrim = temp_trim;
+  return this; //allow function chaining...
+};
+
+Pspm.prototype.reverse_complement = function(alphabet) {
+  "use strict";
+  var x, y, temp, i, row, c, temp_trim;
+  if (this.alph_length != alphabet.get_size_core()) {
+    throw new Error("The alphabet size does not match the size of the pspm.");
+  }
+  if (!alphabet.has_complement()) {
+    throw new Error("The specified alphabet can not be complemented.");
+  }
+  // reverse motif
+  this.reverse();
+  //complement
+  for (x = 0; x < this.motif_length; x++) {
+    row = this.pspm[x];
+    for (i = 0; i < row.length; i++) {
+      c = alphabet.get_complement(i);
+      if (c < i) continue;
+      temp = row[i];
+      row[i] = row[c];
+      row[c] = temp;
+    }
+  }
+  // complement pssm (if defined)
+  if (typeof this.pssm !== "undefined") {
+    //complement
+    for (x = 0; x < this.motif_length; x++) {
+      row = this.pssm[x];
+      for (i = 0; i < row.length; i++) {
+        c = alphabet.get_complement(i);
+        if (c < i) continue;
+        temp = row[i];
+        row[i] = row[c];
+        row[c] = temp;
+      }
+    }
+  }
+  return this; //allow function chaining...
+};
+
+Pspm.prototype.get_stack = function(position, alphabet, ssc) {
+  "use strict";
+  var row, stack_ic, alphabet_ic, stack, i, sym;
+  if (this.alph_length != alphabet.get_size_core()) {
+    throw new Error("The alphabet size does not match the size of the pspm.");
+  }
+  row = this.pspm[position];
+  stack_ic = this.get_stack_ic(position, alphabet);
+  if (ssc) stack_ic -= this.get_error(alphabet);
+  alphabet_ic = alphabet.get_ic();
+  stack = [];
+  for (i = 0; i < this.alph_length; i++) {
+    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;
+};
+
+Pspm.prototype.get_stack_ic = function(position, alphabet) {
+  "use strict";
+  var row, H, i;
+  if (this.alph_length != alphabet.get_size_core()) {
+    throw new Error("The alphabet size does not match the size fo the pspm.");
+  }
+  row = this.pspm[position];
+  H = 0;
+  for (i = 0; i < this.alph_length; i++) {
+    if (row[i] === 0) {
+      continue;
+    }
+    H -= (row[i] * (Math.log(row[i]) / Math.LN2));
+  }
+  return alphabet.get_ic() - H;
+};
+
+Pspm.prototype.get_error = function(alphabet) {
+  "use strict";
+  if (this.nsites === 0) {
+    return 0;
+  }
+  return (alphabet.get_size_core()-1) / (2 * Math.LN2 * this.nsites);
+};
+
+Pspm.prototype.get_motif_length = function() {
+  "use strict";
+  return this.motif_length;
+};
+
+Pspm.prototype.get_alph_length = function() {
+  "use strict";
+  return this.alph_length;
+};
+
+Pspm.prototype.get_left_trim = function() {
+  "use strict";
+  return this.ltrim;
+};
+
+Pspm.prototype.get_right_trim = function() {
+  "use strict";
+  return this.rtrim;
+};
+
+Pspm.prototype.as_best_match = function(alphabet) {
+  "use strict";
+  var match, odds, best_odds, best_index;
+  var i, j;
+  match = "";
+  for (i = 0; i < this.motif_length; i++) {
+    best_index = 0;
+    best_odds = this.pspm[i][0] / alphabet.get_bg_freq(0);
+    for (j = 1; j < this.alph_length; j++) {
+      odds = this.pspm[i][j] / alphabet.get_bg_freq(j);
+      if (odds > best_odds) {
+        best_odds = odds;
+        best_index = j;
+      }
+    }
+    match += alphabet.get_symbol(best_index);
+  }
+  return match;
+};
+
+Pspm.prototype.as_count_matrix = function() {
+  "use strict";
+  var count, count_text, text;
+  var i, j;
+  text = "";
+  for (i = 0; i < this.motif_length; i++) {
+    if (i !== 0) {
+      text += "\n";
+    }
+    for (j = 0; j < this.alph_length; j++) {
+      if (j !== 0) {
+        text += " ";
+      }
+      count = Math.round(this.nsites * this.pspm[i][j]);
+      count_text = "" + count;
+      // pad up to length of 4
+      if (count_text.length < 4) {
+        text += (new Array(5 - count_text.length)).join(" ") + count_text;
+      } else {
+        text += count_text;
+      }
+    }
+  }
+  return text; 
+};
+
+Pspm.prototype.as_probability_matrix = function() {
+  "use strict";
+  var text;
+  var i, j;
+  text = "";
+  for (i = 0; i < this.motif_length; i++) {
+    if (i !== 0) {
+      text += "\n";
+    }
+    for (j = 0; j < this.alph_length; j++) {
+      if (j !== 0) {
+        text += " ";
+      }
+      text += this.pspm[i][j].toFixed(6);
+    }
+  }
+  return text; 
+};
+
+Pspm.prototype.as_score_matrix = function(alphabet, pseudo) {
+  "use strict";
+  var me, score, out, row, col, score_text;
+  me = this;
+  if (typeof this.pssm === "undefined") {
+    if (!(typeof alphabet === "object" && alphabet != null && alphabet instanceof Alphabet)) {
+      throw new Error("The alphabet is required to generate the pssm.");
+    }
+    if (typeof pseudo === "undefined") {
+      pseudo = 0.01;
+    } else if (typeof pseudo !== "number" || pseudo < 0) {
+      throw new Error("Expected positive number for pseudocount");
+    }
+    score = function(row, col) {
+      "use strict";
+      var p, bg, p2;
+      p = me.pspm[row][col];
+      bg = alphabet.get_bg_freq(col);
+      p2 = (p * me.nsites + bg * pseudo) / (me.nsites + pseudo);
+      return (p2 > 0 ? Math.round((Math.log(p2 / bg) / Math.LN2) * 100) : -10000);
+    };
+  } else {
+    score = function(row, col) {
+      "use strict";
+      return me.pssm[row][col];
+    };
+  }
+  out = "";
+  for (row = 0; row < this.motif_length; row++) {
+    for (col = 0; col < this.alph_length; col++) {
+      if (col !== 0) {
+        out += " ";
+      }
+      score_text = "" + score(row, col);
+      // pad out to 6 characters
+      if (score_text.length < 6) {
+        out += (new Array(7 - score_text.length)).join(" ") + score_text;
+      } else {
+        out += score_text;
+      }
+    }
+    out += "\n";
+  }
+  return out;
+}
+
+Pspm.prototype.as_pspm = function() {
+  "use strict";
+  return "letter-probability matrix: alength= " + this.alph_length + 
+      " w= " + this.motif_length + " nsites= " + this.nsites + 
+      (this.pgm === "STREME" ? " P= " : " E= ") + 
+          (typeof this.evalue === "number" ? 
+          this.evalue.toExponential() : this.evalue) + "\n" +
+      this.as_probability_matrix();
+};
+
+Pspm.prototype.as_pssm = function(alphabet, pseudo) {
+  "use strict";
+  return "log-odds matrix: alength= " + this.alph_length + 
+      " w= " + this.motif_length + 
+      " E= " + (typeof this.evalue == "number" ?
+          this.evalue.toExponential() : this.evalue) + "\n" +
+      this.as_score_matrix(alphabet, pseudo);
+};
+
+Pspm.prototype.as_meme = function(options) {
+  var with_header, with_pspm, with_pssm, version, alphabet, bg_source, pseudocount, strands;
+  var out, alen, i;
+  // get the options
+  if (typeof options !== "object" || options === null) {
+    options = {};
+  }
+  with_header = (typeof options["with_header"] === "boolean" ? options["with_header"] : false);
+  with_pspm = (typeof options["with_pspm"] === "boolean" ? options["with_pspm"] : false);
+  with_pssm = (typeof options["with_pssm"] === "boolean" ? options["with_pssm"] : false);
+  if (!with_pspm && !with_pssm) with_pspm = true;
+  if (with_header) {
+    if (typeof options["version"] === "string" && /^\d+(?:\.\d+){0,2}$/.test(options["version"])) {
+      version = options["version"];
+    } else if (typeof options["version"] === "number") {
+      version = options["version"].toFixed(0);
+    } else {
+      version = "4";
+    }
+    if (typeof options["strands"] === "number" && options["strands"] === 1) {
+      strands = 1;
+    } else {
+      strands = 2;
+    }
+    if (typeof options["bg_source"] === "string") {
+      bg_source = options["bg_source"];
+    } else {
+      bg_source = "unknown source";
+    }
+    if (typeof options["alphabet"] === "object" && options["alphabet"] != null
+        && options["alphabet"] instanceof Alphabet) {
+      alphabet = options["alphabet"];
+    } else {
+      throw new Error("The alphabet is required to generate the header.");
+    }
+  }
+  // now create the output
+  out = "";
+  if (with_header) {
+    out = "MEME version " + version + "\n\n";
+    out += alphabet.as_meme() + "\n";
+    if (alphabet.has_complement()) { // assume DNA has both strands unless otherwise specified
+      out += "strands: " + (strands === 1 ? "+" : "+ -") + "\n\n";
+    }
+    out += "Background letter frequencies (from " + bg_source + "):\n";
+    alen = alphabet.get_size_core();
+    for (i = 0; i < alen; i++) {
+      if (i !== 0) {
+        if (i % 9 === 0) { // maximum of nine entries per line
+          out += "\n";
+        } else {
+          out += " ";
+        }
+      }
+      out += alphabet.get_symbol(i) + " " + alphabet.get_bg_freq(i).toFixed(3);
+    }
+  }
+  out += "\n\n";
+  out += "MOTIF " + this.name + (this.alt == null ? "" : " " + this.alt);
+  if (with_pssm) {
+    out += "\n\n";
+    out += this.as_pssm(options["alphabet"], options["pseudocount"]);
+  }
+  if (with_pspm) {
+    out += "\n\n";
+    out += this.as_pspm();
+  }
+  return out;
+}
+
+Pspm.prototype.toString = function() {
+  "use strict";
+  var str, i, row;
+  str = "";
+  for (i = 0; i < this.pspm.length; i++) {
+    row = this.pspm[i];
+    str += row.join("\t") + "\n";
+  }
+  return str;
+};
+
+function parse_pspm_properties(str) {
+  "use strict";
+  var parts, i, eqpos, before, after, properties, prop, num, num_re;
+  num_re = /^((?:[+]?[0-9]*\.?[0-9]+(?:[eE][-+]?[0-9]+)?)|inf)$/;
+  parts = trim(str).split(/\s+/);
+  // split up words containing =
+  for (i = 0; i < parts.length;) {
+    eqpos = parts[i].indexOf("=");
+    if (eqpos != -1) {
+      before = parts[i].substr(0, eqpos);
+      after = parts[i].substr(eqpos+1);
+      if (before.length > 0 && after.length > 0) {
+        parts.splice(i, 1, before, "=", after);
+        i += 3;
+      } else if (before.length > 0) {
+        parts.splice(i, 1, before, "=");
+        i += 2;
+      } else if (after.length > 0) {
+        parts.splice(i, 1, "=", after);
+        i += 2;
+      } else {
+        parts.splice(i, 1, "=");
+        i++;
+      }
+    } else {
+      i++;
+    }
+  }
+  properties = {};
+  for (i = 0; i < parts.length; i += 3) {
+    if (parts.length - i < 3) {
+      throw new Error("Expected PSPM property was incomplete. "+
+          "Remaing parts are: " + parts.slice(i).join(" "));
+    }
+    if (parts[i+1] !== "=") {
+      throw new Error("Expected '=' in PSPM property between key and " +
+          "value but got " + parts[i+1]); 
+    }
+    prop = parts[i].toLowerCase();
+    num = parts[i+2];
+    if (!num_re.test(num)) {
+      throw new Error("Expected numeric value for PSPM property '" + 
+          prop + "' but got '" + num + "'");
+    }
+    properties[prop] = num;
+  }
+  return properties;
+}
+
+function parse_pspm_string(pspm_string) {
+  "use strict";
+  var header_re, lines, first_line, line_num, col_num, alph_length, 
+      motif_length, nsites, evalue, pspm, i, line, match, props, parts,
+      j, prob;
+  header_re = /^letter-probability\s+matrix:(.*)$/i;
+  lines = pspm_string.split(/\n/);
+  first_line = true;
+  line_num = 0;
+  col_num = 0;
+  alph_length;
+  motif_length;
+  nsites;
+  evalue;
+  pspm = [];
+  for (i = 0; i < lines.length; i++) {
+    line = trim(lines[i]);
+    if (line.length === 0) { 
+      continue;
+    }
+    // check the first line for a header though allow matrices without it
+    if (first_line) {
+      first_line = false;
+      match = header_re.exec(line);
+      if (match !== null) {
+        props = parse_pspm_properties(match[1]);
+        if (props.hasOwnProperty("alength")) {
+          alph_length = parseFloat(props["alength"]);
+          if (alph_length != 4 && alph_length != 20) {
+            throw new Error("PSPM property alength should be 4 or 20" +
+                " but got " + alph_length);
+          }
+        }
+        if (props.hasOwnProperty("w")) {
+          motif_length = parseFloat(props["w"]);
+          if (motif_length % 1 !== 0 || motif_length < 1) {
+            throw new Error("PSPM property w should be an integer larger " +
+                "than zero but got " + motif_length);
+          }
+        }
+        if (props.hasOwnProperty("nsites")) {
+          nsites = parseFloat(props["nsites"]);
+          if (nsites <= 0) {
+            throw new Error("PSPM property nsites should be larger than " +
+                "zero but got " + nsites);
+          }
+        }
+        if (props.hasOwnProperty("e")) {
+          evalue = props["e"];
+          if (evalue < 0) {
+            throw new Error("PSPM property evalue should be " +
+                "non-negative but got " + evalue);
+          }
+        }
+        continue;
+      }
+    }
+    pspm[line_num] = [];
+    col_num = 0;
+    parts = line.split(/\s+/);
+    for (j = 0; j < parts.length; j++) {
+      prob = parseFloat(parts[j]);
+      if (prob != parts[j] || prob < 0 || prob > 1) {
+        throw new Error("Expected probability but got '" + parts[j] + "'"); 
+      }
+      pspm[line_num][col_num] = prob;
+      col_num++;
+    }
+    line_num++;
+  }
+  if (typeof motif_length === "number") {
+    if (pspm.length != motif_length) {
+      throw new Error("Expected PSPM to have a motif length of " + 
+          motif_length + " but it was actually " + pspm.length);
+    }
+  } else {
+    motif_length = pspm.length;
+  }
+  if (typeof alph_length !== "number") {
+    alph_length = pspm[0].length;
+    if (alph_length != 4 && alph_length != 20) {
+      throw new Error("Expected length of first row in the PSPM to be " +
+          "either 4 or 20 but got " + alph_length);
+    }
+  }
+  for (i = 0; i < pspm.length; i++) {
+    if (pspm[i].length != alph_length) {
+      throw new Error("Expected PSPM row " + i + " to have a length of " + 
+          alph_length + " but the length was " + pspm[i].length);
+    }
+  }
+  return {"pspm": pspm, "motif_length": motif_length, 
+    "alph_length": alph_length, "nsites": nsites, "evalue": evalue};
+}
+//======================================================================
+// end Pspm object
+//======================================================================
+
+//======================================================================
+// start Logo object
+//======================================================================
+
+var Logo = function(alphabet, options) {
+  "use strict";
+  this.alphabet = alphabet;
+  this.fine_text = "";
+  this.x_axis = 1;
+  this.y_axis = true;
+  this.xlate_nsyms = 1;
+  this.xlate_start = null;
+  this.xlate_end = null;
+  this.pspm_list = [];
+  this.pspm_column = [];
+  this.rows = 0;
+  this.columns = 0;
+  if (typeof options === "string") {
+    // the old method signature had fine_text here so we support that
+    this.fine_text = options;
+  } else if (typeof options === "object" && options != null) {
+    this.fine_text = (typeof options.fine_text === "string" ? options.fine_text : "");
+    this.x_axis = (typeof options.x_axis === "boolean" ? (options.x_axis ? 1 : 0) : 1);
+    if (options.x_axis_hidden != null && options.x_axis_hidden) this.x_axis = -1;
+    this.y_axis = (typeof options.y_axis === "boolean" ? options.y_axis : true);
+    this.xlate_nsyms = (typeof options.xlate_nsyms === "number" ? options.xlate_nsyms : this.xlate_nsyms);
+    this.xlate_start = (typeof options.xlate_start === "number" ? options.xlate_start : this.xlate_start);
+    this.xlate_end = (typeof options.xlate_end === "number" ? options.xlate_end : this.xlate_end);
+  }
+};
+
+Logo.prototype.add_pspm = function(pspm, column) {
+  "use strict";
+  var col;
+  if (typeof column === "undefined") {
+    column = 0;
+  } else if (column < 0) {
+    throw new Error("Column index out of bounds.");
+  }
+  this.pspm_list[this.rows] = pspm;
+  this.pspm_column[this.rows] = column;
+  this.rows++;
+  col = column + pspm.get_motif_length();
+  if (col > this.columns) {
+    this.columns = col;
+  }
+};
+
+Logo.prototype.get_columns = function() {
+  "use strict";
+  return this.columns;
+};
+
+Logo.prototype.get_xlate_nsyms = function() {
+  "use strict";
+  return this.xlate_nsyms;
+};
+
+Logo.prototype.get_xlate_start = function() {
+  "use strict";
+  return (this.xlate_start != null ? this.xlate_start : 0);
+};
+
+Logo.prototype.get_xlate_end = function() {
+  "use strict";
+  return (this.xlate_end != null ? this.xlate_end : this.columns * this.xlate_nsyms);
+};
+
+Logo.prototype.get_xlate_columns = function() {
+  "use strict";
+  return this.get_xlate_end() - this.get_xlate_start();
+};
+
+Logo.prototype.get_rows = function() {
+  "use strict";
+  return this.rows;
+};
+
+Logo.prototype.get_pspm = function(row_index) {
+  "use strict";
+  if (row_index < 0 || row_index >= this.rows) {
+    throw new Error("INDEX_OUT_OF_BOUNDS");
+  }
+  return this.pspm_list[row_index];
+};
+
+Logo.prototype.get_offset = function(row_index) {
+  "use strict";
+  if (row_index < 0 || row_index >= this.rows) {
+    throw new Error("INDEX_OUT_OF_BOUNDS");
+  }
+  return this.pspm_column[row_index];
+};
+
+Logo.prototype._as_eps_data = function(ssc, errbars) {
+  var i, j, pos, stack_pos, pspm, stack, sym, out;
+  out = "";
+  for (i = 0; i < this.rows; i++) {
+    out += "\nStartLine\n";
+    // Indent
+    for (j = 0; j < this.pspm_column[i]; j++) {
+      out += "() startstack\nendstack\n\n";
+    }
+    pspm = this.pspm_list[i];
+    if (pspm.get_left_trim() > 0) {
+      out += "MuteColour\nDrawTrimEdge\n" + pspm.get_left_trim() + " DrawTrimBg\n";
+    }
+    for (pos = 0; pos < pspm.get_motif_length(); pos++) {
+      if (pos != 0 && pos == pspm.get_left_trim()) { // enable full colour
+        out += "DrawTrimEdge\nRestoreColour\n";
+      } else if (pos == (pspm.get_motif_length() - pspm.get_right_trim())) {
+        out += "MuteColour\n" + pspm.get_right_trim() + " DrawTrimBg\n";
+      }
+      out += "(" + (pos + 1) + ") startstack\n";
+      stack = pspm.get_stack(pos, this.alphabet, ssc);
+      for (stack_pos = 0; stack_pos < stack.length; stack_pos++) {
+        sym = stack[stack_pos];
+        out += " " + (sym.get_scale() * this.alphabet.get_ic()) + " (" + sym.get_symbol() + ") numchar\n";
+      }
+      if (errbars) {
+        out += " " + pspm.get_error(this.alphabet) + " Ibeam\n";
+      }
+      out += "endstack\n\n";
+    }
+    if (pspm.get_right_trim() > 0 || pspm.get_left_trim() == pspm.get_motif_length()) {
+      out += "RestoreColour\n";
+    }
+    out += "EndLine\n";
+  }
+  return out;
+};
+
+Logo.prototype.as_eps = function(options) {
+  "use strict";
+  if (this.xlate_nsyms != 1) throw new Error("Unsupported setting xlate_nsyms for EPS");
+  if (this.xlate_start != null) throw new Error("Unsupported setting xlate_start for EPS");
+  if (this.xlate_end != null) throw new Error("Unsupported setting xlate_end for EPS");
+
+  var LOGOHEIGHT = 7.5; // default height of line in cm
+  var cm2pts, height, width, now, ssc, errbars;
+  if (typeof options === "undefined") {
+    options = {};
+  }
+  cm2pts = 72 / 2.54;
+  if (typeof options.logo_height == "number") {
+    height = options.logo_height;
+  } else {
+    height = LOGOHEIGHT * this.rows;
+  }
+  if (typeof options.logo_width == "number") {
+    width = options.logo_width;
+  } else {
+    width = this.columns + 2;
+  }
+  now = new Date();
+  ssc = (typeof options.ssc == "boolean" ? options.ssc : false);
+  errbars = (typeof options.show_error_bar == "boolean" ? options.show_error_bar : ssc);
+  var values = {
+    "LOGOHEIGHT": height,
+    "LOGOWIDTH": width,
+    "BOUNDINGHEIGHT": Math.round(height * cm2pts),
+    "BOUNDINGWIDTH": Math.round(width * cm2pts),
+    "LOGOLINEHEIGHT": (height / this.rows),
+    "CHARSPERLINE": this.columns,
+    "BARBITS": this.alphabet.get_ic(),
+    "LOGOTYPE": (this.alphabet.has_complement() ? "NA" : "AA"),
+    "CREATIONDATE": now.getDate() + "." + (now.getMonth() + 1) + "." + now.getFullYear() + " " + now.getHours() + ":" + now.getMinutes() + ":" + now.getSeconds(),
+    "ERRORBARFRACTION": (typeof options.error_bar_fraction == "number" ? options.error_bar_fraction : 1.0),
+    "TICBITS": (typeof options.ticbits == "number" ? options.ticbits : 1.0),
+    "TITLE": (typeof options.title == "string" ? options.title : ""),
+    "FINEPRINT": (typeof options.fineprint == "string" ? options.fineprint : this.fine_text),
+    "XAXISLABEL": (typeof options.xaxislabel == "string" ? options.xaxislabel : ""),
+    "YAXISLABEL": (typeof options.yaxislabel == "string" ? options.yaxislabel : "bits"),
+    "SSC": ssc,
+    "YAXIS": (typeof options.show_y_axis == "boolean" ? options.show_y_axis : this.y_axis),
+    "SHOWENDS": (typeof options.show_ends == "boolean" ? options.show_ends : false),
+    "ERRBAR": errbars,
+    "OUTLINE": (typeof options.show_outline == "boolean" ? options.show_outline : false),
+    "NUMBERING": (typeof options.show_numbering == "boolean" ? options.show_numbering : this.x_axis != 0),
+    "SHOWINGBOX": (typeof options.show_box == "boolean" ? options.show_box : false),
+    "CREATOR": (typeof options.creator == "string" ? options.creator : "motif_logo.js"),
+    "FONTSIZE": (typeof options.label_font_size == "number" ? options.label_font_size : 12),
+    "TITLEFONTSIZE": (typeof options.title_font_size == "number" ? options.title_font_size : 12),
+    "SMALLFONTSIZE": (typeof options.small_font_size == "number" ? options.small_font_size : 6),
+    "TOPMARGIN" : (typeof options.top_margin == "number" ? options.top_margin : 0.9),
+    "BOTTOMMARGIN": (typeof options.bottom_margin == "number" ? options.bottom_margin : 0.9),
+    "COLORDICT": this.alphabet._as_eps_dict(),
+    "DATA": this._as_eps_data(ssc, errbars)
+  };
+  // now this requires that the script containing the template has been imported!
+  return motif_logo_template(values);
+};
+
+//======================================================================
+// end Logo object
+//======================================================================
+
+// calculate the exact size (in pixels) of an object drawn on the
+// canvas assuming that the background of the canvas is transparent.
+function canvas_bounds(ctx, cwidth, cheight) {
+  "use strict";
+  var data, r, c, top_line, bottom_line, left_line, right_line, 
+      txt_width, txt_height;
+
+  // extract the image data
+  data = ctx.getImageData(0, 0, cwidth, cheight).data;
+
+  // set initial values
+  top_line = -1; bottom_line = -1; left_line = -1; right_line = -1;
+  txt_width = 0; txt_height = 0;
+
+  // Find the top-most line with a non-transparent 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;
+    }
+  }
+  
+  // Only bother looking if we found at least one set pixel... 
+  if (top_line != -1) {
+
+    //find the last line with a non-transparent pixel
+    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;
+      }
+    }
+    // calculate height
+    txt_height = bottom_line - top_line + 1;
+
+    // Find the left-most line with a non-transparent pixel
+    for (c = 0; c < cwidth; c++) {
+      for (r = top_line; r <= bottom_line; 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-transparent pixel
+    for (c = cwidth-1; c >= left_line; c--) {
+      for(r = top_line; r <= bottom_line; 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};
+}
+
+//======================================================================
+// 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).
+var RasterizedAlphabet = function(alphabet, logo_scale, font, width) {
+  "use strict";
+  var default_size, safety_pad, canvas, ctx, middle, baseline, widths, sizes,
+      i, sym, size, tenpercent, avg_width, scale, 
+      target_width, target_height;
+  //variable prototypes
+  this.alphabet = alphabet;
+  this.scale = logo_scale;
+  this.sym_cache = {};
+  this.stack_num_cache = [];
+  this.scale_num_cache = [];
+  // size of canvas
+  default_size = 60; // size of measuring canvas
+  safety_pad = 20; // pixels to pad around so we don't miss the edges
+  // create a canvas to do our measuring
+  canvas = document.createElement("canvas");
+  if (!canvas.getContext) throw new Error("No canvas support");
+  canvas.width = default_size + 2 * safety_pad;
+  canvas.height = default_size + 2 * safety_pad;
+  middle = Math.round(canvas.width / 2);
+  baseline = Math.round(canvas.height - safety_pad);
+  ctx = canvas.getContext('2d');
+  if (!supports_text(ctx)) throw new Error("Canvas does not support text");
+  ctx.font = font;
+  ctx.textAlign = "center";
+  ctx.translate(middle, baseline);
+  // list of widths
+  widths = [];
+  sizes = [];
+  //now measure each letter in the alphabet
+  for (i = 0; i < alphabet.get_size_core(); ++i) {
+    // reset the canvas
+    ctx.clearRect(0, 0, canvas.width, canvas.height);
+    ctx.fillStyle = alphabet.get_colour(i);
+    // draw the test text
+    ctx.fillText(alphabet.get_symbol(i), 0, 0);
+    //measure
+    size = canvas_bounds(ctx, canvas.width, canvas.height);
+    if (size.width === 0) throw new Error("Invisible symbol!");
+    widths.push(size.width);
+    sizes[i] = size;
+  }
+  //sort the widths
+  widths.sort(function(a,b) {return a - b;});
+  //drop 10% of the items off each end
+  tenpercent = Math.floor(widths.length / 10);
+  for (i = 0; i < tenpercent; ++i) {
+    widths.pop();
+    widths.shift();
+  }
+  //calculate average width
+  avg_width = 0;
+  for (i = 0; i < widths.length; ++i) {
+    avg_width += widths[i];
+  }
+  avg_width /= widths.length;
+  // calculate the target width
+  target_width = width * this.scale * 2;
+  // calculate scales
+  for (i = 0; i < alphabet.get_size_core(); ++i) {
+    sym = alphabet.get_symbol(i);
+    size = sizes[i];
+    // calculate scale
+    scale = target_width / Math.max(avg_width, size.width);
+    // estimate scaled height
+    target_height = size.height * scale;
+    // create an appropriately sized canvas
+    canvas = document.createElement("canvas");
+    canvas.width = target_width;
+    canvas.height = target_height + safety_pad * 2;
+    // calculate the middle
+    middle = Math.round(canvas.width / 2);
+    // calculate the baseline
+    baseline = Math.round(canvas.height - safety_pad);
+    // get the context and prepare to draw the rasterized text
+    ctx = canvas.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 text
+    ctx.fillText(sym, 0, 0);
+    ctx.restore();
+    this.sym_cache[sym] = {"image": canvas, "size": canvas_bounds(ctx, canvas.width, canvas.height)};
+  }
+};
+
+RasterizedAlphabet.prototype.get_alphabet = function() {
+  return this.alphabet;
+};
+
+RasterizedAlphabet.prototype.get_scale = function() {
+  return this.scale;
+};
+
+RasterizedAlphabet.prototype.draw_stack_sym = function(ctx, letter, dx, dy, dWidth, dHeight) {
+  "use strict";
+  var entry, image, size;
+  entry = this.sym_cache[letter];
+  image = entry.image;
+  size = entry.size;
+  ctx.drawImage(image, 0, size.bound_top -1, image.width, size.height+1, dx, dy, dWidth, dHeight);
+};
+
+RasterizedAlphabet.prototype.draw_stack_num = function(ctx, font, stack_width, index) {
+  var image, image_ctx, text_length;
+  if (index >= this.stack_num_cache.length) {
+    image = document.createElement("canvas");
+    // measure the text
+    image_ctx = image.getContext('2d');
+    image_ctx.save();
+    image_ctx.font = font;
+    text_length = image_ctx.measureText("" + (index + 1)).width;
+    image_ctx.restore();
+    // resize the canvas to fit
+    image.width = Math.ceil(stack_width);
+    image.height = Math.ceil(text_length);
+    // draw the text
+    image_ctx = image.getContext('2d');
+    image_ctx.translate(Math.round(stack_width / 2), 0);
+    image_ctx.font = font;
+    image_ctx.textBaseline = "middle";
+    image_ctx.textAlign = "right";
+    image_ctx.rotate(-(Math.PI / 2));
+    image_ctx.fillText("" + (index + 1), 0, 0);
+    this.stack_num_cache[index] = image;
+  } else {
+    image = this.stack_num_cache[index];
+  }
+  ctx.drawImage(image, 0, 0);
+}
+
+RasterizedAlphabet.prototype.draw_scale_num = function(ctx, font, num) {
+  var image, image_ctx, text_size, m_length;
+  if (num >= this.scale_num_cache.length) {
+    image = document.createElement("canvas");
+    // measure the text
+    image_ctx = image.getContext('2d');
+    image_ctx.font = font;
+    text_size = image_ctx.measureText("" + num);
+    if (text_size.actualBoundingBoxAscent && text_size.actualBoundingBoxDesent) {
+      // resize the canvas to fit
+      image.width = Math.ceil(text_size.width);
+      image.height = Math.ceil(text_size.actualBoundingBoxAscent + text_size.actualBoundingBoxDesent);
+      // draw the text
+      image_ctx = image.getContext('2d');
+      image_ctx.font = font;
+      image_ctx.textAlign = "right";
+      image_ctx.fillText("" + num, image.width, text_size.actualBoundingBoxAscent);
+    } else {
+      // measure width of 'm' to approximate height, we double it later anyway
+      m_length = image_ctx.measureText("m").width;
+      // resize the canvas to fit
+      image.width = Math.ceil(text_size.width);
+      image.height = Math.ceil(2 * m_length);
+      // draw the text
+      image_ctx = image.getContext('2d');
+      image_ctx.font = font;
+      image_ctx.textAlign = "right";
+      image_ctx.textBaseline = "middle";
+      image_ctx.fillText("" + num, image.width, m_length);
+    }
+    this.scale_num_cache[num] = image;
+  } else {
+    image = this.scale_num_cache[num];
+  }
+  ctx.drawImage(image, -image.width, -Math.round(image.height / 2))
+}
+
+//======================================================================
+// end RasterizedAlphabet
+//======================================================================
+
+//======================================================================
+// start LogoMetrics object
+//======================================================================
+
+var LogoMetrics = function(ctx, logo_columns, logo_rows, has_names, has_finetext, x_axis, y_axis) {
+  "use strict";
+  var i, row_height;
+  //variable prototypes
+  this.pad_top = (has_names ? 5 : 0);
+  this.pad_left = (y_axis ? 10 : 0);
+  this.pad_right = (has_finetext ? 15 : 0);
+  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_axis = y_axis;
+  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_axis = x_axis;
+  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;
+  //calculate the width of the y axis numbers
+  ctx.font = this.y_num_font;
+  for (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)
+  if (x_axis == 1) {
+    ctx.font = this.x_num_font;
+    for (i = 1; i <= logo_columns; i++) {
+      this.x_num_width = Math.max(this.x_num_width, ctx.measureText("" + i).width);
+    }
+  } else if (x_axis == 0) {
+    this.x_num_height = 4;
+    this.x_num_width = 4;
+  } else {
+    this.x_num_height = 0;
+    this.x_num_width = 0;
+  }
+  
+  //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) {
+    row_height = this.stack_height + this.pad_middle;
+    if (has_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_axis ? this.y_num_height/2 : 0);
+
+  var fine_txt_total = (has_finetext ? this.fine_txt_height + this.fine_txt_above : 0);
+  if (has_names) {
+    this.summed_height += fine_txt_total + this.name_height;
+    this.summed_height += Math.max((this.y_axis ? this.y_num_height/2 : 0), 
+        this.x_num_height + this.x_num_above + this.name_spacer);
+  } else {
+    this.summed_height += Math.max((this.y_axis ? this.y_num_height/2 : 0), 
+        this.x_num_height + this.x_num_above + fine_txt_total);
+  }
+
+  //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;
+  if (this.y_axis) {
+    //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;
+
+};
+
+//======================================================================
+// end LogoMetrics object
+//======================================================================
+
+//found this trick at http://talideon.com/weblog/2005/02/detecting-broken-images-js.cfm
+function image_ok(img) {
+  "use strict";
+  // 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) {
+  "use strict";
+  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, raster) {
+  "use strict";
+  var tic_height, i;
+  tic_height = metrics.stack_height / alphabet_ic;
+  ctx.save();
+  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.rotate(-(Math.PI / 2));
+  ctx.textAlign = "center";
+  ctx.fillText("bits", 0, 0);
+  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);
+  for (i = 0; i <= alphabet_ic; i++) {
+    //draw the number
+    ctx.save();
+    ctx.translate(-1, 0);
+    raster.draw_scale_num(ctx, metrics.y_num_font, i);
+    ctx.restore();
+    //draw the tic
+    ctx.fillRect(0, -1, metrics.y_tic_width, 2);
+    //prepare for next tic
+    ctx.translate(0, -tic_height);
+  }
+  ctx.restore();
+
+  ctx.fillRect(metrics.y_tic_width - 2, 0, 2, metrics.stack_height)
+
+  ctx.restore();
+}
+
+function draw_stack_num(ctx, metrics, row_index, raster) {
+  "use strict";
+  ctx.save();
+  ctx.translate(0, Math.round(metrics.stack_height + metrics.x_num_above));
+  if (metrics.x_axis == 1) {
+    raster.draw_stack_num(ctx, metrics.x_num_font, metrics.stack_width, row_index);
+  } else if (metrics.x_axis == 0) {
+    // draw dots instead of the numbers (good for small logos)
+    ctx.beginPath();
+    var radius = Math.round(metrics.x_num_height / 2);
+    ctx.arc(Math.round(metrics.stack_width / 2), radius, radius, 0, 2 * Math.PI, false);
+    ctx.fill();
+  }
+  ctx.restore();
+}
+
+function draw_stack(ctx, metrics, symbols, raster) {
+  "use strict";
+  var preferred_pad, sym_min, i, sym, sym_height, pad;
+  preferred_pad = 0;
+  sym_min = 5;
+
+  ctx.save();//1
+  ctx.translate(0, metrics.stack_height);
+  for (i = 0; i < symbols.length; i++) {
+    sym = symbols[i];
+    sym_height = metrics.stack_height * sym.get_scale();
+    
+    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_stack_sym(ctx, sym.get_symbol(), 0, 0, metrics.stack_width, sym_height);
+    //translate past the padding
+    ctx.translate(0, -(pad/2));
+  }
+  ctx.restore();//1
+}
+
+function draw_dashed_line(ctx, pattern, start, x1, y1, x2, y2) {
+  "use strict";
+  var x, y, len, i, dx, dy, tlen, theta, mulx, muly, lx, ly;
+  dx = x2 - x1;
+  dy = y2 - y1;
+  tlen = Math.pow(dx*dx + dy*dy, 0.5);
+  theta = Math.atan2(dy,dx);
+  mulx = Math.cos(theta);
+  muly = Math.sin(theta);
+  lx = [];
+  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, left_start, left_end, left_divider, right_start, right_end, right_divider) {
+  "use strict";
+  var left_size = left_end - left_start;
+  var right_size = right_end - right_start;
+  var line_x;
+
+  ctx.save();//s8
+  ctx.fillStyle = "rgb(240, 240, 240)";
+  if (left_size > 0) {
+    ctx.fillRect(left_start * metrics.stack_width, 0, left_size * metrics.stack_width, metrics.stack_height);
+  }
+  if (right_size > 0) {
+    ctx.fillRect(right_start * metrics.stack_width, 0, right_size * metrics.stack_width, metrics.stack_height);
+  }
+  ctx.fillStyle = "rgb(51, 51, 51)";
+  if (left_size > 0 && left_divider) {
+    line_x = (left_end * metrics.stack_width) - 0.5;
+    draw_dashed_line(ctx, [3], 0, line_x, 0, line_x, metrics.stack_height);
+  }
+  if (right_size > 0 && right_divider) {
+    line_x = (right_start * metrics.stack_width) + 0.5;
+    draw_dashed_line(ctx, [3], 0, line_x, 0, line_x, metrics.stack_height);
+  }
+  ctx.restore();//s8
+}
+
+function size_logo_on_canvas(logo, canvas, show_names, scale) {
+  "use strict";
+  var draw_name, draw_finetext, metrics;
+  draw_name = (typeof show_names === "boolean" ? show_names : (logo.get_rows() > 1));
+  draw_finetext = (logo.fine_text.length > 0);
+  if (canvas.width !== 0 && canvas.height !== 0) {
+    return;
+  }
+  metrics = new LogoMetrics(canvas.getContext('2d'), 
+      logo.get_xlate_columns(), logo.get_rows(), draw_name, draw_finetext, logo.x_axis, logo.y_axis);
+  if (typeof scale == "number") {
+    //resize the canvas to fit the scaled logo
+    canvas.width = metrics.summed_width * scale;
+    canvas.height = metrics.summed_height * scale;
+  } else {
+    if (canvas.width === 0 && canvas.height === 0) {
+      canvas.width = metrics.summed_width;
+      canvas.height = metrics.summed_height;
+    } else if (canvas.width === 0) {
+      canvas.width = metrics.summed_width * (canvas.height / metrics.summed_height);
+    } else if (canvas.height === 0) {
+      canvas.height = metrics.summed_height * (canvas.width / metrics.summed_width);
+    }
+  }
+}
+
+function draw_logo_on_canvas(logo, canvas, show_names, scale) {
+  "use strict";
+  var i, draw_name, draw_finetext, ctx, metrics, raster, pspm_i, pspm, 
+      offset, col_index, motif_position, ssc;
+  ssc = false;
+  draw_name = (typeof show_names === "boolean" ? show_names : (logo.get_rows() > 1));
+  draw_finetext = (logo.fine_text.length > 0);
+  ctx = canvas.getContext('2d');
+  //assume that the user wants the canvas scaled equally so calculate what the best width for this image should be
+  metrics = new LogoMetrics(ctx, logo.get_xlate_columns(), logo.get_rows(), draw_name, draw_finetext, logo.x_axis, logo.y_axis);
+  if (typeof scale == "number") {
+    //resize the canvas to fit the scaled logo
+    canvas.width = metrics.summed_width * scale;
+    canvas.height = metrics.summed_height * scale;
+  } else {
+    if (canvas.width === 0 && canvas.height === 0) {
+      scale = 1;
+      canvas.width = metrics.summed_width;
+      canvas.height = metrics.summed_height;
+    } else if (canvas.width === 0) {
+      scale = canvas.height / metrics.summed_height;
+      canvas.width = metrics.summed_width * scale;
+    } else if (canvas.height === 0) {
+      scale = canvas.width / metrics.summed_width;
+      canvas.height = metrics.summed_height * scale;
+    } else {
+      scale = Math.min(canvas.width / metrics.summed_width, canvas.height / metrics.summed_height);
+    }
+  }
+  // cache the raster based on the assumption that we will be drawing a lot
+  // of logos the same size and alphabet
+  if (typeof draw_logo_on_canvas.raster_cache === "undefined") {
+    draw_logo_on_canvas.raster_cache = [];
+  }
+  for (i = 0; i < draw_logo_on_canvas.raster_cache.length; i++) {
+    raster = draw_logo_on_canvas.raster_cache[i];
+    if (raster.get_alphabet().equals(logo.alphabet) &&
+        Math.abs(raster.get_scale() - scale) < 0.1) break;
+    raster = null;
+  }
+  if (raster == null) {
+    raster = new RasterizedAlphabet(logo.alphabet, scale, metrics.stack_font, metrics.stack_width);
+    draw_logo_on_canvas.raster_cache.push(raster);
+  }
+  ctx = canvas.getContext('2d');
+  ctx.save();//s1
+  ctx.scale(scale, scale);
+  ctx.save();//s2
+  ctx.save();//s7
+  //create margin
+  ctx.translate(Math.round(metrics.pad_left), Math.round(metrics.pad_top));
+  for (pspm_i = 0; pspm_i < logo.get_rows(); ++pspm_i) {
+    pspm = logo.get_pspm(pspm_i);
+    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(Math.round(metrics.summed_width/2), Math.round(metrics.name_height));
+      ctx.font = metrics.name_font;
+      ctx.textAlign = "center";
+      ctx.fillText(pspm.name, 0, 0);
+      ctx.restore();//s4
+      ctx.translate(0, Math.round(metrics.name_height + 
+          Math.min(0, metrics.name_spacer - metrics.y_num_height/2)));
+    }
+    //draw scale
+    if (logo.y_axis) draw_scale(ctx, metrics, logo.alphabet.get_ic(), raster);
+    ctx.save();//s5
+    //translate across past the scale
+    if (logo.y_axis) {
+      ctx.translate(Math.round(metrics.y_label_height + metrics.y_label_spacer + 
+        metrics.y_num_width + metrics.y_tic_width), Math.round(metrics.y_num_height / 2));
+    }
+    //draw the trimming background
+    if (pspm.get_left_trim() > 0 || pspm.get_right_trim() > 0) {
+      var left_start = offset * logo.get_xlate_nsyms();
+      var left_end = (offset + pspm.get_left_trim()) * logo.get_xlate_nsyms();
+      var left_divider = true;
+      if (left_end < logo.get_xlate_start() || left_start > logo.get_xlate_end()) {
+        // no overlap
+        left_start = 0;
+        left_end = 0;
+        left_divider = false;
+      } else {
+        if (left_start < logo.get_xlate_start()) {
+          left_start = logo.get_xlate_start();
+        }
+        if (left_end > logo.get_xlate_end()) {
+          left_end = logo.get_xlate_end();
+          left_divider = false;
+        }
+        left_start -= logo.get_xlate_start();
+        left_end -= logo.get_xlate_start();
+        if (left_end < left_start) {
+          left_start = 0;
+          left_end = 0;
+          left_divider = false;
+        }
+      }
+      var right_end = (offset + pspm.get_motif_length()) * logo.get_xlate_nsyms();
+      //var right_start = right_end - (pspm.get_left_trim() * logo.get_xlate_nsyms());
+      var right_start = right_end - (pspm.get_right_trim() * logo.get_xlate_nsyms());
+      var right_divider = true;
+      if (right_end < logo.get_xlate_start() || right_start > logo.get_xlate_end()) {
+        // no overlap
+        right_start = 0;
+        right_end = 0;
+        right_divider = false;
+      } else {
+        if (right_start < logo.get_xlate_start()) {
+          right_start = logo.get_xlate_start();
+          right_divider = false;
+        }
+        if (right_end > logo.get_xlate_end()) {
+          right_end = logo.get_xlate_end();
+        }
+        right_start -= logo.get_xlate_start();
+        right_end -= logo.get_xlate_start();
+        if (right_end < right_start) {
+          right_start = 0;
+          right_end = 0;
+          right_divider = false;
+        }
+      }
+      draw_trim_background(ctx, metrics, left_start, left_end, left_divider, right_start, right_end, right_divider);
+    }
+    //draw letters
+    var xlate_col;
+    for (xlate_col = logo.get_xlate_start(); xlate_col < logo.get_xlate_end(); xlate_col++) {
+      ctx.translate(metrics.stack_pad_left,0);
+      col_index = Math.floor(xlate_col / logo.get_xlate_nsyms());
+      if (xlate_col % logo.get_xlate_nsyms() == 0) {
+        if (col_index >= offset && col_index < (offset + pspm.get_motif_length())) {
+          motif_position = col_index - offset;
+          draw_stack_num(ctx, metrics, motif_position, raster);
+          draw_stack(ctx, metrics, pspm.get_stack(motif_position, logo.alphabet, ssc), raster);
+        }
+      } else {
+        if (col_index >= offset && col_index < (offset + pspm.get_motif_length())) {
+          ctx.save();// s5.1
+          ctx.translate(0, Math.round(metrics.stack_height));
+          // TODO draw a dot or dash or something to indicate continuity of the motif
+          ctx.restore(); //s5.1
+        }
+      }
+      ctx.translate(Math.round(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
+  if (logo.fine_text.length > 0) {
+    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) {
+  "use strict";
+  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) {
+  "use strict";
+  var logo = new Logo(alphabet, fine_text);
+  logo.add_pspm(pspm);
+  return logo;
+}
+
+function logo_2(alphabet, fine_text, target, query, query_offset) {
+  "use strict";
+  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) {
+  "use strict";
+  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, null, scale);
+  //replace the image with the canvas
+  image.parentNode.replaceChild(canvas, image);
+}
+
+/*
+ * Specifies 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) {
+  "use strict";
+  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, null, 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) {
+  "use strict";
+  var ws, i;
+  str = str.replace(/^\s\s*/, '');
+  ws = /\s/; i = str.length;
+  while (ws.test(str.charAt(--i)));
+  return str.slice(0, i + 1);
+}
+
+//
+// Delay drawing a logo
+//
+var DelayLogoTask = function(logo, canvas) {
+  "use strict";
+  canvas.width = canvas.width; // clear canvas
+  this.logo = logo;
+  this.canvas = canvas;
+};
+
+DelayLogoTask.prototype.run = function () {
+  "use strict";
+  this.canvas.width = this.canvas.width; // clear canvas
+  draw_logo_on_canvas(this.logo, this.canvas, false);
+};
+
+/*
+ * Make a canvas with the motif logo drawn on it.
+ */
+function make_logo(alphabet, pspm, height, rc, offset, className) {
+  if (rc) pspm = pspm.copy().reverse_complement(alphabet);
+  var logo = new Logo(alphabet);
+  logo.add_pspm(pspm, offset);
+  var canvas = document.createElement('canvas');
+  var sizeit = (height < 0);
+  canvas.height = (sizeit ? -height : height); 
+  canvas.width = 0;
+  canvas.className = className;
+  if (sizeit) size_logo_on_canvas(logo, canvas, false);
+  add_draw_task(canvas, new DelayLogoTask(logo, canvas));
+  return canvas;
+}
+</script>
+    <script>
+
+// PRIVATE GLOBAL (uhoh)
+var _block_colour_lookup = {};
+
+function block_colour(index) {
+  function hsl2rgb(hue, saturation, lightness) {
+    "use strict";
+    function _hue(p, q, t) {
+      "use strict";
+      if (t < 0) t += 1;
+      else if (t > 1) t -= 1;
+      if (t < (1.0 / 6.0)) {
+        return p + ((q - p) * 6.0 * t);
+      } else if (t < 0.5) {
+        return q;
+      } else if (t < (2.0 / 3.0)) {
+        return p + ((q - p) * ((2.0 / 3.0) - t) * 6.0);
+      } else {
+        return p;
+      }
+    }
+    function _pad_hex(value) {
+      var hex = Math.round(value * 255).toString(16);
+      if (hex.length < 2) hex = "0" + hex;
+      return hex;
+    }
+    var r, g, b, p, q;
+    if (saturation == 0) {
+      // achromatic (grayscale)
+      r = lightness;
+      g = lightness;
+      b = lightness;
+    } else {
+      if (lightness < 0.5) {
+        q = lightness * (1 + saturation);
+      } else {
+        q = lightness + saturation - (lightness * saturation);
+      }
+      p = (2 * lightness) - q;
+      r = _hue(p, q, hue + (1.0 / 3.0));
+      g = _hue(p, q, hue);
+      b = _hue(p, q, hue - (1.0 / 3.0));
+    }
+    return "#" + _pad_hex(r) + _pad_hex(g) + _pad_hex(b);
+  }
+  if (typeof index !== "number" || index % 1 !== 0 || index < 0) return "#000000";
+  // check for override
+  if (_block_colour_lookup[index] == null) {
+    var start = 0; //red
+    var sat = 100;
+    var light = 50;
+    var divisions = 1 << Math.ceil(Math.log(index + 1) / Math.LN2);
+    hue = start + (360 / divisions) * ((index - (divisions >> 1)) * 2 + 1);
+    // colour input fields only support values in the form #RRGGBB
+    _block_colour_lookup[index] = hsl2rgb(hue / 360, sat / 100, light / 100);
+  }
+  return _block_colour_lookup[index];
+}
+
+function set_block_colour(index, new_colour) {
+  _block_colour_lookup[index] = new_colour;
+  var blocks = document.querySelectorAll("div.block_motif[data-colour-index=\"" + index + "\"]");
+  var i;
+  for (i = 0; i < blocks.length; i++) {
+    blocks[i].style.backgroundColor = new_colour;
+  }
+  var swatches = document.querySelectorAll("div.legend_swatch[data-colour-index=\"" + index + "\"]");
+  var picker;
+  for (i = 0; i < swatches.length; i++) {
+    swatches[i].style.backgroundColor = new_colour;
+    picker = swatches[i].querySelector("input[type=\"color\"]");
+    if (picker != null) picker.value = new_colour;
+  }
+}
+
+function make_block_legend_entry(motif_name, motif_colour_index) {
+  if (typeof make_block_legend_entry.has_colour_picker !== "boolean") {
+    // test if colour picker is supported, based off Modernizer
+    // see http://stackoverflow.com/a/7787648/66387
+    make_block_legend_entry.has_colour_picker = (function() {
+      var doc_ele = document.documentElement;
+      // We first check to see if the type we give it sticks..
+      var input_ele = document.createElement('input');
+      input_ele.setAttribute('type', 'color');
+      var value_ok = input_ele.type !== 'text';
+      if (value_ok) {
+        // If the type does, we feed it a textual value, which shouldn't be valid.
+        // If the value doesn't stick, we know there's input sanitization which infers a custom UI
+        var smile = ':)';
+        input_ele.value = smile;
+        input_ele.style.cssText = 'position:absolute;visibility:hidden;';
+        // chuck into DOM and force reflow for Opera bug in 11.00
+        // github.com/Modernizr/Modernizr/issues#issue/159
+        doc_ele.appendChild(input_ele);
+        doc_ele.offsetWidth;
+        value_ok = input_ele.value != smile;
+        doc_ele.removeChild(input_ele);
+      }
+      return value_ok;
+    })();
+  }
+  var entry = document.createElement("div");
+  entry.className = "legend_entry";
+  var swatch;
+  swatch = document.createElement("div");
+  swatch.className = "legend_swatch";
+  swatch.setAttribute("data-colour-index", motif_colour_index);
+  swatch.style.backgroundColor = block_colour(motif_colour_index);
+  if (make_block_legend_entry.has_colour_picker) {
+    var picker = document.createElement("input");
+    picker.type = "color";
+    picker.value = block_colour(motif_colour_index);
+    picker.addEventListener("change", function(e) {
+      set_block_colour(motif_colour_index, picker.value);
+    }, false);
+    swatch.addEventListener("click", function(e) {
+      picker.click();
+    }, false);
+    swatch.appendChild(picker);
+  }
+  entry.appendChild(swatch);
+  var name = document.createElement("div");
+  name.className = "legend_text";
+  name.appendChild(document.createTextNode(motif_name));
+  entry.appendChild(name);
+  return entry;
+}
+
+function make_block_ruler(max_len) {
+  var container = document.createElement("div");
+  container.className = "block_container";
+  var step;
+  if (max_len < 50) {
+    step = 1;
+  } else if (max_len < 100) {
+    step = 2;
+  } else if (max_len < 200) {
+    step = 4;
+  } else if (max_len < 500) {
+    step = 10;
+  } else if (max_len < 1000) {
+    step = 20;
+  } else if (max_len < 2000) {
+    step = 40;
+  } else if (max_len < 5000) {
+    step = 100;
+  } else if (max_len < 10000) {
+    step = 200;
+  } else if (max_len < 20000) {
+    step = 400;
+  } else {
+    step = Math.floor(max_len / 20000) * 400;
+  }
+  var peroid;
+  if (max_len < 10) {
+    peroid = 1;
+  } else if (max_len < 20) {
+    peroid = 2;
+  } else {
+    peroid = 5;
+  }
+  var i, cycle, offset, tic, label;
+  for (i = 0, cycle = 0; i < max_len; i += step, cycle = (cycle + 1) % peroid) {
+    offset = "" + ((i / max_len) * 100) + "%";
+    tic = document.createElement("div");
+    tic.style.left = offset;
+    tic.className = (cycle == 0 ? "tic_major" : "tic_minor");
+    container.appendChild(tic);
+    if (cycle == 0) {
+      label = document.createElement("div");
+      label.className = "tic_label";
+      label.style.left = offset;
+      label.appendChild(document.createTextNode(i));
+      container.appendChild(label);
+    }
+  }
+  return container;
+}
+
+function _calculate_block_needle_drag_pos(e, data) {
+  var mouse;
+  e = e || window.event;
+  if (e.pageX || ev.pageY) {
+    mouse = {"x": e.pageX, "y": e.pageY};
+  } else {
+    mouse = {
+      x:e.clientX + document.body.scrollLeft - document.body.clientLeft, 
+      y:e.clientY + document.body.scrollTop  - document.body.clientTop 
+    };
+  }
+  var cont = data.container;
+  var dragable_length = cont.clientWidth - 
+    (cont.style.paddingLeft ? cont.style.paddingLeft : 0) -
+    (cont.style.paddingRight ? cont.style.paddingRight : 0);
+  //I believe that the offset parent is the body
+  //otherwise I would need to make this recursive
+  //maybe clientLeft would work, but the explanation of
+  //it is hard to understand and it apparently doesn't work
+  //in firefox 2.
+  var diff = mouse.x - cont.offsetLeft;
+  if (diff < 0) diff = 0;
+  if (diff > dragable_length) diff = dragable_length;
+  var pos = Math.round(diff / dragable_length * data.max);
+  if (pos > data.len) pos = data.len;
+  return pos;
+}
+
+function _update_block_needle_drag(e, data, done) {
+  "use strict";
+  var pos = _calculate_block_needle_drag_pos(e, data);
+  // read the needle positions
+  var left = parseInt(data.llabel.textContent, 10) - data.off - 1;
+  var right = parseInt(data.rlabel.textContent, 10) - data.off;
+  // validate needle positions
+  if (left >= data.len) left = data.len - 1;
+  if (left < 0) left = 0;
+  if (right > data.len) right = data.len;
+  if (right <= left) right = left + 1;
+  // calculate the new needle positions
+  if (data.moveboth) {
+    var size = right - left;
+    if (data.isleft) {
+      if ((pos + size) > data.len) pos = data.len - size;
+      left = pos;
+      right = pos + size;
+    } else {
+      if ((pos - size) < 0) pos = size;
+      left = pos - size;
+      right = pos;
+    }
+  } else {
+    if (data.isleft) {
+      if (pos >= right) pos = right - 1;
+      left = pos;
+    } else {
+      if (pos <= left) pos = left + 1;
+      right = pos;
+    }
+  }
+  // update the needle positions
+  data.lneedle.style.left = "" + (left / data.max * 100) + "%";
+  data.llabel.textContent = "" + (left + data.off + 1);
+  data.rneedle.style.left = "" + (right / data.max * 100) + "%";
+  data.rlabel.textContent = "" + (right + data.off);
+  data.handler(left, right, done);
+}
+
+function _make_block_needle_drag_start_handler(isleft, data) {
+  return function (e) {
+    data.isleft = isleft;
+    data.moveboth = !(e.shiftKey);
+    document.addEventListener("mousemove", data.drag_during, false);
+    document.addEventListener("mouseup", data.drag_end, false);
+  };
+}
+
+function _make_block_needle_drag_end_handler(data) {
+  return function (e) {
+    document.removeEventListener("mousemove", data.drag_during, false);
+    document.removeEventListener("mouseup", data.drag_end, false);
+    _update_block_needle_drag(e, data, true);
+  };
+}
+
+function _make_block_needle_drag_during_handler(data) {
+  return function (e) {
+    _update_block_needle_drag(e, data, false);
+  };
+}
+
+// private function used by make_block_container
+function _make_block_needle(isleft, value, data) {
+  var vbar = document.createElement('div');
+  vbar.className = "block_needle " + (isleft ? "left" : "right");
+  vbar.style.left = "" + (value / data.max * 100)+ "%";
+  var label = document.createElement('div');
+  label.className = "block_handle " + (isleft ? "left" : "right");
+  // The needles sit between the sequence positions, so the left one sits at the
+  // start and the right at the end. This is why 1 is added to the displayed
+  // value for a left handle as the user doesn't need to know about this detail
+  label.textContent = "" + (isleft ? value + data.off + 1 : value + data.off);
+  label.unselectable = "on"; // so IE and Opera don't select the text, others are done in css
+  label.title = "Drag to move the displayed range. Hold shift and drag to change " + (isleft ? "lower" : "upper") + " bound of the range.";
+  vbar.appendChild(label);
+  if (isleft) {
+    data.lneedle = vbar;
+    data.llabel = label;
+  } else {
+    data.rneedle = vbar;
+    data.rlabel = label;
+  }
+  label.addEventListener("mousedown", _make_block_needle_drag_start_handler(isleft, data), false);
+  return vbar;
+}
+
+function make_block_container(is_stranded, has_both_strands, max_len, show_len, offset, range_handler) {
+  offset = (offset != null ? offset : 0);
+  // make the container for the block diagram
+  var container = document.createElement("div");
+  container.className = "block_container";
+  container.setAttribute("data-max", max_len);
+  container.setAttribute("data-off", offset);
+  if (is_stranded) {
+    var plus = document.createElement("div");
+    plus.appendChild(document.createTextNode("+"));
+    plus.className = "block_plus_sym";
+    container.appendChild(plus);
+    if (has_both_strands) {
+      var minus = document.createElement("div");
+      minus.appendChild(document.createTextNode("-"));
+      minus.className = "block_minus_sym";
+      container.appendChild(minus);
+    }
+  }
+  var rule = document.createElement("div");
+  rule.className = "block_rule";
+  rule.style.width = ((show_len / max_len) * 100) + "%";
+  container.appendChild(rule);
+  if (range_handler != null) {
+    var range_data = {
+      "max": max_len,
+      "len": show_len,
+      "off": offset,
+      "handler": range_handler,
+      "container": container,
+      "lneedle": null, "llabel": null,
+      "rneedle": null, "rlabel": null,
+      "isleft": false, "moveboth" : false
+    };
+    range_data.drag_during = _make_block_needle_drag_during_handler(range_data);
+    range_data.drag_end = _make_block_needle_drag_end_handler(range_data);
+    container.appendChild(_make_block_needle(false, 1, range_data)); // add right first so z-index works
+    container.appendChild(_make_block_needle(true, 0, range_data));
+  }
+  return container;
+}
+
+function make_block_label(container, max_len, pos, length, message) {
+  "use strict";
+  var label = document.createElement("div");
+  label.className = "block_label";
+  label.style.left = (((pos + (length / 2)) / max_len) * 100) + "%";
+  label.appendChild(document.createTextNode(message));
+  container.appendChild(label);
+}
+
+function make_block(container, max_len,
+    site_pos, site_len, site_pvalue, site_rc, site_colour_index, site_secondary) {
+  "use strict";
+  var block_height, block, block_region1, block_region2;
+  var max_block_height = 12;
+  var max_pvalue = 1e-10;
+  // calculate the height of the block
+  block_height = (site_pvalue < max_pvalue ? max_block_height : 
+      (Math.log(site_pvalue) / Math.log(max_pvalue)) * max_block_height);
+  if (block_height < 1) block_height = 1;
+  // create a block to represent the motif
+  block = document.createElement("div");
+  block.className = "block_motif" + (site_secondary ? " scanned_site" : "") + (site_rc ? " bottom" : " top");
+  block.style.left = ((site_pos / max_len) * 100) + "%";
+  block.style.top = (!site_rc ? max_block_height - block_height : 
+      max_block_height + 1) + "px";
+  block.style.width = ((site_len / max_len) * 100) + "%";
+  block.style.height = block_height + "px";
+  block.style.backgroundColor = block_colour(site_colour_index);
+  block.setAttribute("data-colour-index", site_colour_index);
+  // add to container
+  container.appendChild(block);
+  var activator = function (e) {
+    toggle_class(block, "active", true);
+    var new_e = new e.constructor(e.type, e);
+    block.dispatchEvent(new_e);
+  };
+  var deactivator = function (e) {
+    toggle_class(block, "active", false);
+    var new_e = new e.constructor(e.type, e);
+    block.dispatchEvent(new_e);
+  }
+  // create a larger region to detect mouseover for the block
+  block_region1 = document.createElement("div");
+  block_region1.className = "block_region top" + 
+    (site_secondary ? " scanned_site" : "") + (site_rc ? "" : " main");
+  block_region1.style.left = block.style.left;
+  block_region1.style.width = block.style.width;
+  block_region1.addEventListener('mouseover', activator, false);
+  block_region1.addEventListener('mouseout', deactivator, false);
+  container.appendChild(block_region1);
+  block_region2 = document.createElement("div");
+  block_region2.className = "block_region bottom" + 
+    (site_secondary ? " scanned_site" : "") + (site_rc ? " main" : "");
+  block_region2.style.left = block.style.left;
+  block_region2.style.width = block.style.width;
+  block_region2.addEventListener('mouseover', activator, false);
+  block_region2.addEventListener('mouseout', deactivator, false);
+  container.appendChild(block_region2);
+  return block;
+}
+
+function set_block_needle_positions(containingNode, start, end) {
+  var container, lneedle, llabel, rneedle, rlabel, max, off, left, right;
+  container = (/\bblock_container\b/.test(containingNode.className) ? containingNode : containingNode.querySelector(".block_container"));
+  max = parseInt(container.getAttribute("data-max"), 10);
+  off = parseInt(container.getAttribute("data-off"), 10);
+  left = start - off;
+  right = end - off;
+  lneedle = containingNode.querySelector(".block_needle.left");
+  llabel = lneedle.querySelector(".block_handle.left");
+  rneedle = containingNode.querySelector(".block_needle.right");
+  rlabel = rneedle.querySelector(".block_handle.right");
+  // update the needle positions
+  lneedle.style.left = "" + (left / max * 100) + "%";
+  llabel.textContent = "" + (left + off + 1);
+  rneedle.style.left = "" + (right / max * 100) + "%";
+  rlabel.textContent = "" + (right + off);
+}
+
+function get_block_needle_positions(containingNode) {
+  var container, llabel, rlabel, max, off, left, right;
+  container = (/\bblock_container\b/.test(containingNode.className) ? containingNode : containingNode.querySelector(".block_container"));
+  max = parseInt(container.getAttribute("data-max"), 10);
+  off = parseInt(container.getAttribute("data-off"), 10);
+  llabel = containingNode.querySelector(".block_needle.left > .block_handle.left");
+  rlabel = containingNode.querySelector(".block_needle.right > .block_handle.right");
+  left = parseInt(llabel.textContent, 10) - off - 1;
+  right = parseInt(rlabel.textContent, 10) - off;
+  return {"start": left + off, "end": right + off};
+}
+</script>
+    <script>
+function make_alpha_bg_table(alph, freqs) {
+  function colour_symbol(index) {
+    var span = document.createElement("span");
+    span.appendChild(document.createTextNode(alph.get_symbol(index)));
+    span.style.color = alph.get_colour(index);
+    span.className = "alpha_symbol";
+    return span;
+  }
+  var table, thead, tbody, row, th, span, i;
+  // create table
+  table = document.createElement("table");
+  table.className = "alpha_bg_table";
+  // create header
+  thead = document.createElement("thead");
+  table.appendChild(thead);
+  row = thead.insertRow(thead.rows.length);
+  if (alph.has_complement()) {
+    add_text_header_cell(row, "Name", "pop_alph_name");
+    if (freqs != null) add_text_header_cell(row, "Freq.", "pop_alph_freq");
+    if (alph.has_bg()) add_text_header_cell(row, "Bg.", "pop_alph_bg");
+    add_text_header_cell(row, "");
+    add_text_header_cell(row, "");
+    add_text_header_cell(row, "");
+    if (alph.has_bg()) add_text_header_cell(row, "Bg.", "pop_alph_bg");
+    if (freqs != null) add_text_header_cell(row, "Freq.", "pop_alph_freq");
+    add_text_header_cell(row, "Name", "pop_alph_name");
+  } else {
+    add_text_header_cell(row, "");
+    add_text_header_cell(row, "Name", "pop_alph_name");
+    if (freqs != null) add_text_header_cell(row, "Freq.", "pop_alph_freq");
+    if (alph.has_bg()) add_text_header_cell(row, "Bg.", "pop_alph_bg");
+  }
+  // add alphabet entries
+  tbody = document.createElement("tbody");
+  table.appendChild(tbody);
+  if (alph.has_complement()) {
+    for (i = 0; i < alph.get_size_core(); i++) {
+      var c = alph.get_complement(i);
+      if (i > c) continue;
+      row = tbody.insertRow(tbody.rows.length);
+      add_text_cell(row, alph.get_name(i));
+      if (freqs != null) add_text_cell(row, "" + freqs[i]);
+      if (alph.has_bg()) add_text_cell(row, "" + alph.get_bg_freq(i));
+      add_cell(row, colour_symbol(i)); 
+      add_text_cell(row, "~");
+      add_cell(row, colour_symbol(c)); 
+      if (alph.has_bg()) add_text_cell(row, "" + alph.get_bg_freq(c));
+      if (freqs != null) add_text_cell(row, "" + freqs[c]);
+      add_text_cell(row, alph.get_name(c));
+    }
+  } else {
+    for (i = 0; i < alph.get_size_core(); i++) {
+      row = tbody.insertRow(tbody.rows.length);
+      add_cell(row, colour_symbol(i)); 
+      add_text_cell(row, alph.get_name(i));
+      if (freqs != null) add_text_cell(row, "" + freqs[i]);
+      if (alph.has_bg()) add_text_cell(row, "" + alph.get_bg_freq(i));
+    }
+  }
+  return table;
+}
+
+</script>
+    <script>
+//
+// simple-shared-doc.js
+//
+
+//
+// Function to redirect to appropriate doc file.
+//
+function get_doc_text(pgm, doc_type, extra, extra2) {
+  switch (pgm) {
+    case 'shared':
+      return(get_shared_doc_text(doc_type, extra, extra2));
+    case 'ame':
+      return(get_ame_doc_text(doc_type, extra, extra2));
+    case 'centrimo':
+      return(get_centrimo_doc_text(doc_type, extra, extra2));
+    case 'discovery':
+      return(get_discovery_doc_text(doc_type, extra, extra2));
+    case 'fimo':
+      return(get_fimo_doc_text(doc_type, extra, extra2));
+    case 'gomo':
+      return(get_gomo_doc_text(doc_type, extra, extra2));
+    case 'mcast':
+      return(get_mcast_doc_text(doc_type, extra, extra2));
+    case 'meme-chip':
+      return(get_meme_chip_doc_text(doc_type, extra, extra2));
+    case 'momo':
+      return(get_momo_doc_text(doc_type, extra, extra2));
+    case 'sea':
+      return(get_sea_doc_text(doc_type, extra, extra2));
+    case 'spamo':
+      return(get_spamo_doc_text(doc_type, extra, extra2));
+    case 'streme':
+      return(get_streme_doc_text(doc_type, extra, extra2));
+    case 'tgene':
+      return(get_tgene_doc_text(doc_type, extra, extra2));
+    case 'tomtom':
+      return(get_tomtom_doc_text(doc_type, extra, extra2));
+    case 'xstreme':
+      return(get_xstreme_doc_text(doc_type, extra, extra2));
+    default:
+      return("<b>Unknown program type: <font color=red>" + pgm + "</font></b>");
+  }
+} // get_doc_text
+
+//
+// Function to replace the innerHTML of element "id" with the HTML indicated by "doc_type".
+// Easier to read and update than the more flexible approach in shared-doc.js. 
+//
+function print_doc(id, pgm, doc_type, extra) {
+  document.getElementById(id).insertAdjacentHTML('beforeend', get_doc_text(pgm, doc_type, extra));
+} // print_doc
+
+//
+// Function to replace the innerHTML of element "id" with an HTML paragraph
+// containing the text for 'pgm' and 'doc_type'.
+// This function can be used in help pop-ups.
+//
+function print_doc_para(id, pgm, doc_type, extra, extra2) {
+  html = "<p>" + get_doc_text(pgm, doc_type, extra, extra2) + "</p>"; 
+  document.getElementById(id).insertAdjacentHTML('beforeend', html);
+} // print_doc_para
+
+//
+// Function to return the Shared HTML text of a given type.
+// This function can be used directly to document the output format (xx-output-format.html)
+// and indirectly via print_doc_para for help pop-ups in the actual output HTML,
+// to prevent duplication of documentation.
+//
+function get_shared_doc_text(doc_type, extra, extra2) {
+  if (extra == undefined) {extra = ""};
+  if (extra2 == undefined) {extra2 = ""};
+  switch (doc_type) {
+    case 'fasta-coordinates-name':
+      return(`
+        The sequence IDs in the FASTA header lines are used as the source of sequence names. 
+        The sequence ID is the string following the initial '>' up to the first white space character. 
+        If the sequence ID is in an accepted <a href="` + site_url + `/doc/fasta-coordinates-format.html">FASTA Coordinates Format</a>
+        (e.g., UCSC or Galaxy format), and you did NOT specify the <code>` + extra + `-no-pgc</code> option, 
+        then the coordinates are removed from the sequence ID to create the sequence name.
+      `);
+    case 'fasta-coordinates-brief':
+      return(`
+        The sequence IDs in the FASTA header lines are used as the source of sequence names. 
+        The sequence ID is the string following the initial '>' up to the first white space character. 
+        If the sequence ID is in an accepted <a href="` + site_url + `/doc/fasta-coordinates-format.html">FASTA Coordinates Format</a>
+        (e.g., UCSC or Galaxy format), and you did NOT specify the <code>` + extra + `-no-pgc</code> option, 
+        then the coordinates are removed from the sequence ID to create the sequence name,
+	and the starting coordinate given in the sequence ID will be used as the 
+        coordinate of the first position of the sequence. 
+        Otherwise, the coordinate of the first position of the sequence is taken as 1 and the entire
+	sequence ID is used as the sequence name. 
+      `);
+    case 'fasta-coordinates':
+      return(`
+	For sequence coordinates embedded in FASTA sequence headers to be parsed 
+        correctly by MEME Suite programs, the sequence ID in the FASTA header should have one of the two
+	following formats:
+
+	<h4>UCSC Format</h4>
+	<div style='margin: 5px 0'>
+	  &gt;<span class='pdat'>sequence name</span>:<span class='pdat'
+	  >starting position</span>-<span class='pdat'>ending position</span>
+	</div>
+	where
+	<ul style='margin-top: 0; margin-bottom: 5px'>
+	  <li><span class='pdat'>sequence name</span> is the name of the genomic sequence,</li>
+	  <li><span class='pdat'>starting position</span> is the genomic position of the first base and</li>
+	  <li><span class='pdat'>ending position</span> is the genomic position of the final base.</li>
+	</ul>
+        <b>Example:</b> <span class="pdata">chr1:156887119-156887619</span>
+
+	<h4>Galaxy Format</h4>
+	<div style='margin: 5px 0'>
+	  &gt;<span class='pdat'>assembly name</span>_<span class='pdat'
+	  >sequence name</span>_<span class='pdat'
+	  >starting position</span>_<span class='pdat'
+	  >ending position</span>_<span class='pdat'
+	  >strand</span>
+	</div>
+	where
+	<ul style='margin-top: 0; margin-bottom: 5px'>
+	  <li><span class='pdat'>assembly name</span> is the name of the genomic assembly,</li>
+	  <li><span class='pdat'>sequence name</span> is the name of the genomic sequence,</li>
+	  <li><span class='pdat'>starting position</span> is the genomic position of the first base and</li>
+	  <li><span class='pdat'>ending position</span> is the genomic position of the final base.</li>
+	</ul>
+        <b>Example:</b> <span class="pdata">>mm9_chr18_75759530_7575972_-</span>
+
+	<p>	
+	For both formats, the following rules also apply:
+        <ul>
+	  <li>The the coordinates are 1-start, fully-closed.  This means
+	  that the first base of the chromosome is position "1", and the bases at the
+	  first and last positions of the given range are included.</li>
+	  <li>The <span class='pdat'>sequence name</span> may not contain any white space.</li>
+	  <li>The <span class='pdat'>assembly name</span> is not optional.</li>
+	  <li>The <span class='pdat'>strand</span> is ignored.</li>
+	  <li>When no valid genomic coordinates are found in a FASTA sequence header, the starting
+	  position of the sequence is taken to be position 1.</li>
+        </ul>
+        </p>
+      `);
+    case 'motif-db':
+      return(`
+	The name of ` + extra2 + ` a file of motifs ("motif database file") that contains ` + extra + `
+      `);
+    case 'motif-id':
+      return(`
+	The name of the ` + extra + ` motif, which is unique ` + extra2 + ` in the motif database file.
+      `);
+    case 'motif-alt-id':
+      return(`
+	An alternate name for the ` + extra + ` motif that may be provided ` + extra2 + ` in the motif database file.
+      `);
+    case 'motif-width':
+      return(`
+	The width of the motif. No gaps are allowed in motifs supplied to ` + extra + `
+        as it only works for motifs of a fixed width.
+      `);
+    case 'motif-cons':
+      return(`
+	A consensus sequence computed from the ` + extra + ` motif (as described <a href="#consensus_doc">below</a>).
+      `);
+    case 'motif-match-score':
+     return(`
+	` + extra2 + ` The motif match score of a position in a sequence is
+	computed by summing the appropriate entry from each column of the
+	position-dependent scoring matrix that represents the motif. ` + extra + `
+     `);
+    case 'motif-match-p-value':
+      return(`
+	The <i>p</i>-value of a motif match is the probability of a single random
+	subsequence of the length of the motif <a href="javascript:help_refine('pop_motif_match_score')">scoring</a>
+	at least as well as the observed match.
+      `);
+    case 'bh-q-value':
+      if (extra2 == "") extra2 = "match";
+      return(`
+	The q-value is the minimum False Discovery Rate (FDR) required to consider this
+        ` + extra2 + ` significant.</br>` +
+        get_shared_doc_text('bh-q-value-method', extra, extra2) + `
+      `);
+    case 'bh-q-value-method':
+      return(`
+        <br>` + extra + ` estimates q-values from all the ` + extra2 + ` <i>p</i>-values 
+	using the method proposed by Benjamini & Hochberg (<i>Journal of the Royal Statistical Society B</i>, 57:289-300, 1995).
+	See also Storey JD, Tibshirani R. Statistical significance for
+	genome-wide studies, <i>Proc. Natl. Acad. Sci. USA</i> (2003) <b>100</b>:9440&ndash;9445.
+      `);
+    case 'sdb-name':
+      return(`
+	The name of the (FASTA) sequence database file.
+      `);
+    case 'sdb-psp':
+      return(`
+	The name of the position specific priors (PSP) file.
+      `);
+    case 'sdb-dist':
+      return(`
+	The name of the binned distribution of priors file.
+      `);
+    case 'sdb-count':
+      return(`
+	The number of sequences in the database.
+      `);
+    case 'sdb-letters':
+      return(`
+	The number of letters in the sequence database.
+      `);
+    case 'lastmod':
+      return(`
+	The date of the last modification to the ` + extra + ` database.
+      `);
+    case 'sequence-id':
+      return(`
+        The identifier of the sequence (from the FASTA sequence header line)` + extra + `
+      `);
+    case 'sequence-desc':
+      return(`
+        The description appearing after the identifier of the sequence in the FASTA header line.
+      `);
+    case 'alph-name':
+      return(`
+	The name of the alphabet symbol.
+      `);
+    case 'alph-bg':
+      return(`
+	The frequency of the alphabet symbol as defined by the background model.
+      `);
+    case 'match-start':
+      return(`
+	The start position of the ` + extra + `.
+      `);
+    case 'match-stop':
+      return(`
+	The end position of the ` + extra + `.
+      `);
+    case 'match-start-seq':
+      return(`
+	The start position of the ` + extra + `; 1-based sequence coordinates.
+      `);
+    case 'match-stop-seq':
+      return(`
+	The end position of the ` + extra + `; 1-based sequence coordinates.
+      `);
+    case 'match-start-genomic':
+      return(`
+	The start position of the ` + extra + `; genomic coordinates.
+      `);
+    case 'match-stop-genomic':
+      return(`
+	The end position of the ` + extra + `; genomic coordinates.
+      `);
+    case 'motif-consensus':
+      return(`
+        <p id="consensus_doc">
+           A <b>consensus sequence</b> is constructed from each column in a
+           motif's frequency matrix using the <b>"50% rule"</b>
+           as follows:
+        </p>
+        <ol>
+          <li>The letter frequencies in the column are sorted in decreasing order.</li>
+          <li>Letters with frequency less 50% of the maximum are discarded.</li>
+          <li>The letter used in this position in the consensus sequence is determined
+          by the first rule below that applies:</li>
+          <ul>
+            <li>If there is only one letter left, or if the remaining letters exactly match
+            an ambiguous symbol in the alphabet, the <b>letter</b> or <b>ambiguous symbol</b>,
+            respectively, is used.</li>
+            <li>Otherwise, if the remaining set contains at least 50% of the core
+            symbols in the alphabet, the alphabet's <b>wildcard</b>
+            (e.g., "N" for DNA or RNA, and "X" for protein) is used.</li>
+            <li>Otherwise, the letter with the <b>maximum frequency</b> is used.</li>
+          </ul>
+        </ol>
+      `);
+    default:
+      return("Error--Unrecognized shared doc_type: " + doc_type);
+  }
+} // get_shared_doc_text
+</script>
+    <script>
+//
+// discovery_doc.js
+// Documentation common to motif discovery tools.
+//
+
+//
+// Function to return the HTML text of a given type.
+// This function can be used directly to document the output format (xx-output-format.html)
+// and indirectly via print_doc_para for help pop-ups in the actual output HTML,
+// to prevent duplication of documentation.
+//
+function get_discovery_doc_text(doc_type, extra, extra2) {
+  if (extra == undefined) {extra = ""};
+  if (extra2 == undefined) {extra2 = ""};
+
+  switch (doc_type) {
+    case 'motif_logo':
+      return(`
+	The sequence logo of the motif.
+	  The rules for construction logos are given in
+	  the <i>Description</i> section of the documentation for the MEME Suite utility
+          <a href="` + extra + `/doc/ceqlogo.html#description">ceqlogo</a>.
+      `);
+    case 'motif_rc_logo':
+      return(`
+	The sequence logo of the reverse complement motif.
+	  The rules for construction logos are given in
+	  the <i>Description</i> section of the documentation for the MEME Suite utility
+          <a href="` + extra + `/doc/ceqlogo.html#description">ceqlogo</a>.
+      `);
+    case 'more':
+      return(`
+	Click on the blue symbol below to reveal detailed information about the motif.
+      `);
+    case 'submit_dl':
+      return(`
+	Click on the blue symbol below to reveal options allowing you
+	  to submit this motif to another MEME Suite motif analysis program, to download this
+	  motif in various text formats, or to download a sequence "logo" of
+	  this motif PNG or EPS format.</p>
+	  <h5>Supported Programs</h5>
+	  <dl>
+	    <dt>Tomtom</dt>
+	    <dd>Tomtom is a tool for searching for similar known motifs.
+	      [<a href="` + extra + `/doc/tomtom.html?man_type=web">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="` + extra + `/doc/mast.html?man_type=web">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="` + extra + `/doc/fimo.html?man_type=web">manual</a>]</dd>
+	    <dt>GOMo</dt>
+	    <dd>GOMo is a tool for identifying possible roles (Gene Ontology
+	      terms) for DNA binding motifs.
+	      [<a href="` + extra + `/doc/gomo.html?man_type=web">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="` + extra + `/doc/spamo.html?man_type=web">manual</a>]</dd>
+	  </dl>
+      `);
+    case 'site_distr':
+      return(`
+        This plot shows the positional distribution of the best match to the motif in the ` +
+        extra + ` sequences. 
+        Only matches with scores at least the ` +
+        extra2 + ` score threshold are considered.
+        The plot is smoothed with a triangular function whose width is 5% of the maximum ` +
+	extra + ` sequence length.
+        The position of the dotted vertical line indicates whether the sequences were
+	aligned on their left ends, centers, or right ends, respectively.  
+      `);
+    case 'site_hist':
+      return(`
+        This histogram shows the distribution of the <b>number</b> of matches to the motif in the ` +
+        extra + ` sequences with at least one match.
+        Only matches with scores at least the ` +
+        extra2 + ` score threshold are considered.
+      `);
+    default:
+      return("Error--Unrecognized discovery doc_type: " + doc_type);
+  }
+} // get_discovery_doc_text
+</script>
+    <script>
+//
+// submit_or_download_motif.js
+//
+
+function make_submit_or_download_motif_form(id, site_url, program) {
+  var html = `
+    <div class="popup_wrapper">
+      <div class="popup" style="display:none; top: -150px;" id="download">
+	<div>
+	  <div style="float:right; ">
+	    <div id="outpop_close" class="close" tabindex="0">x</div>
+	  </div>
+	  <h2 class="mainh" style="margin:0; padding:0;">Submit or Download</h2>
+	  <div style="clear:both"></div>
+	</div>
+	<div style="height:100px">
+	  <div style="float:right; width: 30px;">
+	    <div id="outpop_prev" class="navarrow" tabindex="0">
+	      <span class="inactive">&#8679;</span><span class="active">&#11014;</span>
+	    </div>
+	    <div id="outpop_num" class="navnum"></div>
+	    <div id="outpop_next" class="navarrow" tabindex="0">
+	      <span class="inactive">&#8681;</span><span class="active">&#11015;</span>
+	    </div>
+	  </div>
+	  <div id="logo_box" style="height: 100px; margin-right: 40px;">
+	    <canvas id="outpop_logo" height="100" width="250"></canvas>
+	    <canvas id="outpop_logo_rc" height="100" width="250"></canvas>
+	  </div>
+	</div>
+	<!-- tabs start -->
+	<div class="tabArea top">
+	  <span id="outpop_tab_1" class="tab">Submit Motif</span><span
+	    id="outpop_tab_2" class="tab middle">Download Motif</span><span
+	    id="outpop_tab_3" class="tab middle">Download Logo</span>
+	</div>
+	<div class="tabMain top">
+	  <!-- Submit to another program -->
+	  <div id="outpop_pnl_1">
+	    <h4 class="compact">Submit to program</h4>
+	    <table id="programs" class="programs">
+	      <tr>
+		<td><input type="radio" name="program" value="tomtom" id="submit_tomtom"></td>
+		<td><label for="submit_tomtom">Tomtom</label></td>
+		<td><label for="submit_tomtom">Find similar motifs in
+		    published libraries or a library you supply.</label></td>
+	      </tr>
+	      <tr>
+		<td><input type="radio" name="program" value="fimo" id="submit_fimo"></td>
+		<td><label for="submit_fimo">FIMO</label></td>
+		<td><label for="submit_fimo">Find motif occurrences in
+		    sequence data.</label></td>
+	      </tr>
+	      <tr>
+		<td><input type="radio" name="program" value="mast" id="submit_mast"></td>
+		<td><label for="submit_mast">MAST</label></td>
+		<td><label for="submit_mast">Rank sequences by affinity to
+		    groups of motifs.</label></td>
+	      </tr>
+	      <tr class="dna_only">
+		<td><input type="radio" name="program" value="gomo" id="submit_gomo"></td>
+		<td><label for="submit_gomo">GOMo</label></td>
+		<td><label for="submit_gomo">Identify possible roles (Gene
+		    Ontology terms) for motifs.</label></td>
+	      </tr>
+	      <tr class="dna_only">
+		<td><input type="radio" name="program" value="spamo" id="submit_spamo"></td>
+		<td><label for="submit_spamo">SpaMo</label></td>
+		<td><label for="submit_spamo">Find other motifs that are
+		    enriched at specific close spacings which might imply the existence of a complex.</label></td>
+	      </tr>
+	    </table>
+	  </div>
+	  <!-- download text format  -->
+	  <div id="outpop_pnl_2">
+	    <div>
+	      <label for="text_format">Format:</label>
+	      <select id="text_format">
+		<option value="0">Count Matrix</option>
+		<option value="1">Probability Matrix</option>
+		<option value="2">Minimal MEME</option> ` + 
+		(program == "MEME" ? `
+		<option value="3">FASTA</option>
+		<option value="4">Raw</option> ` : ``) + `
+	      </select>
+	    </div>
+	    <textarea id="outpop_text" name="content"
+	      style="width:99%; white-space: pre; word-wrap: normal; overflow-x: scroll;"
+	      rows="8" readonly="readonly" wrap="off"></textarea>
+	    <a id="outpop_text_dl" download="meme.txt" href=""></a>
+	  </div>
+	  <!-- download logo format -->
+	  <div id="outpop_pnl_3">
+	    <form id="logo_form" method="post" action="">
+	      <input type="hidden" name="program" value=" ` + program + `"/>
+	      <input type="hidden" id="logo_motifs" name="motifs" value=""/>
+	      <input type="hidden" id="logo_id1" name="id1" value=""/>
+	      <table>
+		<tr>
+		  <td><label for="logo_format">Format:</label></td>
+		  <td>
+		    <select id="logo_format" name="png">
+		      <option value="1">PNG (for web)</option>
+		      <option value="0">EPS (for publication)</option>
+		    </select>
+		  </td>
+		</tr>
+		<tr>
+		  <td><label for="logo_rc">Orientation:</label></td>
+		  <td>
+		    <select id="logo_rc" name="rc1">
+		      <option value="0">Normal</option>
+		      <option value="1" id="logo_rc_option">Reverse Complement</option>
+		    </select>
+		  </td>
+		</tr>
+		<tr>
+		  <td><label for="logo_ssc">Small Sample Correction:</label></td>
+		  <td>
+		    <input type="hidden" id="logo_err" name="errbars" value="0"/>
+		    <select id="logo_ssc" name="ssc">
+		      <option value="0">Off</option>
+		      <option value="1">On</option>
+		    </select>
+		  </td>
+		</tr>
+		<tr>
+		  <td><label for="logo_width">Width:</label></td>
+		  <td>
+		    <input type="text" id="logo_width" size="4" placeholder="default" name="width"/>&nbsp;cm
+		  </td>
+		</tr>
+		<tr>
+		  <td><label for="logo_height">Height:</label></td>
+		  <td>
+		    <input type="text" id="logo_height" size="4" placeholder="default" name="height"/>&nbsp;cm
+		  </td>
+		</tr>
+	      </table>
+	    </form>
+	  </div>
+	  <!-- Buttons -->
+	  <div>
+	    <div style="float:left;">
+	      <input type="button" id="outpop_do" value="Submit" />
+	    </div>
+	    <div style="float:right;">
+	      <input id="outpop_cancel" type="button" value="Cancel" />
+	    </div>
+	    <div style="clear:both;"></div>
+	  </div>
+	</div>
+      </div>
+    </div>
+  `;
+  document.getElementById(id).insertAdjacentHTML('beforeend', html);
+  $("logo_form").action = site_url + "/utilities/generate_logo";
+} // make_submit_or_download_motif_form
+
+//
+// Functions to update the submit_or_download_motif form.
+//
+
+//
+// Initialise and display the download popup.
+//
+function action_show_outpop(e, ordinal) {
+  "use strict";
+  function init() {
+    "use strict";
+    var close_btn, next_btn, prev_btn, cancel_btn, do_btn;
+    var tab1, tab2, tab3;
+    var pnl1, pnl2, pnl3;
+    var format_list;
+    var tbl_submit, inputs, i, default_prog;
+    close_btn = $("outpop_close");
+    close_btn.addEventListener("click", action_hide_outpop, false);
+    close_btn.addEventListener("keydown", action_hide_outpop, false);
+    next_btn = $("outpop_next");
+    next_btn.addEventListener("click", action_outpop_next, false);
+    next_btn.addEventListener("keydown", action_outpop_next, false);
+    prev_btn = $("outpop_prev");
+    prev_btn.addEventListener("click", action_outpop_prev, false);
+    prev_btn.addEventListener("keydown", action_outpop_prev, false);
+    cancel_btn = $("outpop_cancel");
+    cancel_btn.addEventListener("click", action_hide_outpop, false);
+    do_btn = $("outpop_do");
+    do_btn.addEventListener("click", action_outpop_submit, false);
+    tab1 = $("outpop_tab_1");
+    tab1.tabIndex = 0;
+    tab1.addEventListener("click", action_outpop_tab, false);
+    tab1.addEventListener("keydown", action_outpop_tab, false);
+    tab2 = $("outpop_tab_2");
+    tab2.tabIndex = 0;
+    tab2.addEventListener("click", action_outpop_tab, false);
+    tab2.addEventListener("keydown", action_outpop_tab, false);
+    tab3 = $("outpop_tab_3");
+    tab3.tabIndex = 0;
+    tab3.addEventListener("click", action_outpop_tab, false);
+    tab3.addEventListener("keydown", action_outpop_tab, false);
+    pnl1 = $("outpop_pnl_1");
+    pnl2 = $("outpop_pnl_2");
+    pnl3 = $("outpop_pnl_3");
+    toggle_class(tab1, "activeTab", true);
+    toggle_class(tab2, "activeTab", false);
+    toggle_class(tab3, "activeTab", false);
+    pnl1.style.display = "block";
+    pnl2.style.display = "none";
+    pnl3.style.display = "none";
+    format_list = $("text_format");
+    format_list.addEventListener("change", action_outpop_format, false);
+    // setup program selection
+    tbl_submit = $("programs");
+    // when not dna, hide the inputs for programs that require dna motifs
+    toggle_class(tbl_submit, "alphabet_dna", current_alphabet.has_complement());//TODO alphabet_dna is a bad name for a field when allowing custom alphabets
+    // add a click listener for the radio buttons
+    inputs = tbl_submit.querySelectorAll("input[type='radio']");
+    for (i = 0; i < inputs.length; i++) {
+      inputs[i].addEventListener("click", action_outpop_program, false);
+    }
+    // ensure that a default program option is selected for DNA and Protein
+    default_prog = document.getElementById(current_alphabet.has_complement() ? "submit_tomtom" : "submit_fimo"); //TODO Tomtom might require a more strict definition of DNA
+    default_prog.checked = true;
+    action_outpop_program.call(default_prog);
+    // disable reverse-complement when not DNA
+    $("logo_rc_option").disabled = !current_alphabet.has_complement();
+    // set errorbars on when ssc is on
+    $("logo_ssc").addEventListener("change", action_outpop_ssc, false);
+  }
+  // store the focused element
+  action_hide_outpop.last_active = document.activeElement;
+  if (!e) e = window.event;
+  if (e.type === "keydown") {
+    if (e.keyCode !== 13 && e.keyCode !== 32) {
+      return;
+    }
+    // stop a submit or something like that
+    e.preventDefault();
+  }
+  // hide the help popup
+  help_popup();
+  // on first load initilize the popup
+  if (!action_show_outpop.ready) {
+    init();
+    action_show_outpop.ready = true;
+  }
+  update_outpop_motif(ordinal - 1);
+  // display the download popup
+  $("grey_out_page").style.display = "block";
+  $("download").style.display = "block";
+  $("outpop_close").focus();
+} // action_show_output
+
+//
+// Hide the submit or download popup.
+//
+function action_hide_outpop(e) {
+  if (!e) e = window.event;
+  if (e.type === "keydown") {
+    if (e.keyCode !== 13 && e.keyCode !== 32) {
+      return;
+    }
+    // stop a submit or something like that
+    e.preventDefault();
+  }
+  $("download").style.display = "none";
+  $("grey_out_page").style.display = "none";
+  if (typeof action_hide_outpop.last_active !== "undefined") {
+    action_hide_outpop.last_active.focus();
+  }
+} // action_hide_outpop
+
+/*
+ * Show the next motif in the download popup.
+ */
+function action_outpop_next(e) {
+  if (!e) e = window.event;
+  if (e.type === "keydown") {
+    if (e.keyCode !== 13 && e.keyCode !== 32) {
+      return;
+    }
+    // stop a submit or something like that
+    e.preventDefault();
+  }
+  update_outpop_motif(current_motif + 1);
+} // action_outpop_next
+
+/*
+ * Show the previous motif in the download popup.
+ */
+function action_outpop_prev(e) {
+  if (!e) e = window.event;
+  if (e.type === "keydown") {
+    if (e.keyCode !== 13 && e.keyCode !== 32) {
+      return;
+    }
+    // stop a submit or something like that
+    e.preventDefault();
+  }
+  update_outpop_motif(current_motif - 1);
+} // action_outpop_prev
+
+/*
+ * Highlight the selected row in the program list.
+ */
+function action_outpop_program() {
+  "use strict";
+  var table, tr, rows, i;
+  tr = find_parent_tag(this, "TR");
+  table = find_parent_tag(tr, "TABLE");
+  rows = table.querySelectorAll("tr");
+  for (i = 0; i < rows.length; i++) {
+    toggle_class(rows[i], "selected", rows[i] === tr);
+  }
+} // action_outpop_program
+
+/*
+ * Submit the motif to the selected program.
+ */
+function action_outpop_submit(e) {
+  "use strict";
+  var form, input, program, motifs;
+  // find out which program is selected
+  var radios, i;
+  radios = document.getElementsByName("program");
+  program = "fimo"; // default to fimo, since it works with all alphabet types
+  for (i = 0; i < radios.length; i++) {
+    if (radios[i].checked) program = radios[i].value;
+  }
+
+  motifs = motif_minimal_meme(data.motifs[current_motif]);
+  form = document.createElement("form");
+  form.setAttribute("method", "post");
+  form.setAttribute("action", site_url + "/tools/" + program);
+
+  input = document.createElement("input");
+  input.setAttribute("type", "hidden");
+  input.setAttribute("name", "motifs_embed");
+  input.setAttribute("value", motifs);
+  form.appendChild(input);
+
+  var current_file = location.pathname.substring(location.pathname.lastIndexOf('/')+1);
+  input = document.createElement("input");
+  input.setAttribute("type", "hidden");
+  input.setAttribute("name", "motifs_name");
+  input.setAttribute("value", "motif number " + (current_motif+1) + " from " + current_file);
+  form.appendChild(input);
+
+  document.body.appendChild(form);
+  form.submit();
+  document.body.removeChild(form);
+} // action_outpop_submit(e)
+
+/*
+ * Enable error bars when small sample correction is enabled.
+ */
+function action_outpop_ssc() {
+  "use strict";
+  $("logo_err").value = $("logo_ssc").value;
+} // action_outpop_ssc
+
+//
+// Update the motif logos and format download text in the popup.
+// This is called whenever the current motif changes.
+// 
+function update_outpop_motif(index) {
+  "use strict";
+  var motifs, motif, pspm, logo, canvas, num;
+  motifs = data["motifs"];
+  if (index < 0 || index >= motifs.length) {return;}
+  current_motif = index;
+  motif = motifs[index];
+  pspm = new Pspm(motif["pwm"]);
+  logo = new Logo(current_alphabet, "");
+  logo.add_pspm(pspm, 0);
+  canvas = $("outpop_logo");
+  canvas.width = canvas.width; // clear canvas
+  draw_logo_on_canvas(logo, canvas, false);
+  canvas = $("outpop_logo_rc");
+  canvas.width = canvas.width; // clear rc canvas
+  if (data.options.strands === "both" || data.options.revcomp) {
+    pspm.reverse_complement(current_alphabet);
+    logo = new Logo(current_alphabet, "");
+    logo.add_pspm(pspm, 0);
+    draw_logo_on_canvas(logo, canvas, false);
+  }
+  num = $("outpop_num");
+  num.innerHTML = "";
+  num.appendChild(document.createTextNode("" + (index + 1)));
+  update_outpop_format(index);
+} // action_outpop_motif
+
+//
+// Create the download menu.
+//
+function update_outpop_format(index) {
+  var motif = data.motifs[index];
+  var fn = [motif_count_matrix, motif_prob_matrix, motif_minimal_meme, motif_fasta, motif_raw];
+  var suffix = ["_counts.txt", "_freqs.txt", ".meme", "_fasta.txt", "_raw.txt"];
+  var format = parseInt($("text_format").value);
+  var text = fn[format](motif);
+  prepare_download(text, "text/plain", motif.id + suffix[format], $("outpop_text_dl"));
+  $("outpop_text").value = text;
+} // update_outpop_format
+
+/*
+ * Update the text in the download format popup.
+ */
+function action_outpop_format() {
+  update_outpop_format(current_motif);
+} // action_outpop_format
+
+/*
+ * Download the format text.
+ * Wire the link containing the data URI text to a download button so it looks
+ * the same as the server submit stuff.
+ */
+function action_outpop_download_motif(e) {
+  $("outpop_text_dl").click();
+} // action_outpop_download_motif
+
+/*
+ * Download the motif logo.
+ * The EPS format can be calculated locally in Javascript
+ */
+function action_outpop_download_logo(e) {
+  "use strict";
+  var motif = data.motifs[current_motif];
+  if ($("logo_format").value === "0") { // EPS
+    var pspm, logo, eps;
+    var logo_rc, logo_ssc, logo_width, logo_height;
+    logo_rc = ($("logo_rc").value === "1");
+    logo_ssc = ($("logo_ssc").value === "1");
+    logo_width = parseFloat($("logo_width").value);
+    if (isNaN(logo_width) || !isFinite(logo_width) || logo_width <= 0) logo_width = null;
+    logo_height = parseFloat($("logo_height").value);
+    if (isNaN(logo_height) || !isFinite(logo_height) || logo_height <= 0) logo_height = null;
+    // create a PSPM from the motif
+    pspm = motif_pspm(motif);
+    if (logo_rc) pspm.reverse_complement(current_alphabet);
+    logo = new Logo(current_alphabet);
+    logo.add_pspm(pspm, 0);
+    eps = logo.as_eps({"ssc": logo_ssc, "logo_width": logo_width, "logo_height": logo_height});
+    prepare_download(eps, "application/postscript", motif.id + (logo_rc ? "_rc" : "") + ".eps");
+  } else {
+    $("logo_motifs").value = motif_minimal_meme(motif);
+    $("logo_id1").value = motif.id;
+    $("logo_form").submit();
+  }
+} // action_outpop_download_logo
+
+/*
+ * Change the selected tab in the download popup.
+ */
+function action_outpop_tab(e) {
+  "use strict";
+  var tab1, tab2, tab3, pnl1, pnl2, pnl3, do_btn;
+  if (!e) e = window.event;
+  if (e.type === "keydown") {
+    if (e.keyCode !== 13 && e.keyCode !== 32) {
+      return;
+    }
+    // stop a submit or something like that
+    e.preventDefault();
+  }
+  tab1 = $("outpop_tab_1");
+  tab2 = $("outpop_tab_2");
+  tab3 = $("outpop_tab_3");
+  pnl1 = $("outpop_pnl_1");
+  pnl2 = $("outpop_pnl_2");
+  pnl3 = $("outpop_pnl_3");
+  do_btn = $("outpop_do");
+
+  toggle_class(tab1, "activeTab", (this === tab1));
+  toggle_class(tab2, "activeTab", (this === tab2));
+  toggle_class(tab3, "activeTab", (this === tab3));
+  pnl1.style.display = ((this === tab1) ? "block" : "none");
+  pnl2.style.display = ((this === tab2) ? "block" : "none");
+  pnl3.style.display = ((this === tab3) ? "block" : "none");
+  do_btn.value = ((this === tab1) ? "Submit" : "Download");
+  do_btn.removeEventListener("click", action_outpop_submit, false);
+  do_btn.removeEventListener("click", action_outpop_download_logo, false);
+  do_btn.removeEventListener("click", action_outpop_download_motif, false);
+  if (this === tab1) {
+    do_btn.addEventListener("click", action_outpop_submit, false);
+  } else if (this === tab2) {
+    do_btn.addEventListener("click", action_outpop_download_motif, false);
+  } else {
+    do_btn.addEventListener("click", action_outpop_download_logo, false);
+  }
+} // action_outpop_tab
+
+function motif_fasta(motif) {
+  "use strict";
+  var sites, site, seq, sequences, sequence, i, num, counter, out;
+  counter = {};
+  sequences = data["sequence_db"]["sequences"];
+  sites = motif["sites"];
+  out = "";
+  for (i = 0; i < sites.length; i++) {
+    site = sites[i];
+    seq = site["seq"];
+    sequence = sequences[seq];
+    counter[seq] = (num = counter[seq]) ? (++num) : (num = 1); // inc counter
+    if (i !== 0) {out += "\n";}
+    out += ">" + sequence["name"] + "_site_" + num + " offset= " + site["pos"] +
+      (site["rc"] ? " RC\n" : "\n");
+    out += site["match"];
+  }
+  return out;
+} // motif_fasta
+
+function motif_raw(motif) {
+  "use strict";
+  var sites, i, out;
+  sites = motif["sites"];
+  out = "";
+  for (i = 0; i < sites.length; i++) {
+    if (i !== 0) {out += "\n";}
+    out += sites[i]["match"];
+  }
+  return out;
+} // motif_raw
+
+/*
+ * Create a pspm for the given motif data
+ */
+function motif_pspm(motif) {
+  var pwm = motif.pwm;
+  var name = motif.id;
+  var ltrim = 0;
+  var rtrim = 0;
+  var nsites = motif.nsites;
+  var sig = (current_program === "STREME" ? motif.test_pvalue : motif.evalue);
+  return new Pspm(pwm, name, ltrim, rtrim, nsites, sig, null, motif.alt, current_program);
+} // motif_pspm
+
+/*
+ * Create a count matrix from the given motif data
+ */
+function motif_count_matrix(motif) {
+  return motif_pspm(motif).as_count_matrix();
+} // motif_count_matrix
+
+/*
+ * Create a probablity matrix from the given motif data
+ */
+function motif_prob_matrix(motif) {
+  return motif_pspm(motif).as_probability_matrix();
+} // motif_prob_matrix
+
+function motif_minimal_meme(motif) {
+  var strands;
+  if (current_program === "STREME") {
+    strands = (data.options.strands === "both" ? 2 : 1);
+  } else {
+    strands = (data.options.revcomp ? 2 : 1);
+  }
+  return motif_pspm(motif).as_meme({
+    "with_header": true,
+    "with_pspm": true,
+    "with_pssm": (current_program === "MEME" ? true : false),
+    "version": data["version"],
+    "alphabet": current_alphabet,
+    "strands": strands
+  });
+}
+</script>
+    <script>
+var current_program = "MEME";
+var current_alphabet = new Alphabet(data.alphabet, data.background.freqs);
+var current_motif = 0;
+//var new_icon_src = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABwAAAAQCAMAAAAyEe/dAAAACVBMVEX//wAAAAD////s2cV/AAAAdUlEQVQYlXVRBxLAIAhL+P+jC2HZhXcBZEWEldDsZcLIcAhHWWnK8SDcWQhMFUHdAQ1CqQ5+CWPmlHojl+nCJNRtzu4qRc3IUzmTVpXYK0nox0z0PI1stgchdK7lEv7ekhvalw8WW547Gyzedt/2/gLx8WXjXF/1AYFriNAWAAAAAElFTkSuQmCC";
+
+var DelayLogoTask = function(logo, canvas) {
+  this.logo = logo;
+  this.canvas = canvas;
+};
+
+DelayLogoTask.prototype.run = function () {
+  draw_logo_on_canvas(this.logo, this.canvas, false);
+};
+
+function clone_template(template) {
+  "use strict";
+  var node, help_btns, i, button;
+  node = $(template).cloneNode(true);
+  toggle_class(node, "template", false);
+  node.id = "";
+  help_btns = node.querySelectorAll(".help");
+  for (i = 0; i < help_btns.length; i++) {
+    button = help_btns[i];
+    if (button.hasAttribute("data-topic")) {
+      button.tabIndex = "0";
+      button.addEventListener("click", __toggle_help, false);
+      button.addEventListener("keydown", __toggle_help, false);
+    }
+  }
+  return node;
+}
+
+function make_small_logo(alphabet, pspm, options) {
+  if (typeof options === "undefined") options = {};
+  if (options.rc) pspm = pspm.copy().reverse_complement(alphabet);
+  var logo = new Logo(alphabet, {x_axis: false, y_axis: false});
+  logo.add_pspm(pspm, (typeof options.offset === "number" ? options.offset : 0));
+  var canvas = document.createElement('canvas');
+  if (typeof options.className === "string") canvas.className = options.className;
+  if (typeof options.width === "number" && options.width > 0) {
+    canvas.height = 0;
+    canvas.width = options.width;
+    draw_logo_on_canvas(logo, canvas, false);
+  } else {
+    draw_logo_on_canvas(logo, canvas, false, 1/3);
+  }
+  return canvas;
+}
+
+function make_large_logo(alphabet, pspm, rc, offset, className) {
+  if (rc) pspm = pspm.copy().reverse_complement(alphabet);
+  var logo = new Logo(alphabet, "");
+  logo.add_pspm(pspm, offset);
+  var canvas = document.createElement('canvas');
+  canvas.height = 200;
+  canvas.width = 0;
+  canvas.className = className;
+  size_logo_on_canvas(logo, canvas, false);
+  add_draw_task(canvas, new DelayLogoTask(logo, canvas));
+  return canvas;
+}
+
+function make_sym_btn(symbol, title, action) {
+  var box;
+  box = document.createElement("div");
+  box.tabIndex = 0;
+  box.className = "sym_btn";
+  box.appendChild(document.createTextNode(symbol));
+  box.title = title;
+  box.addEventListener('click', action, false);
+  box.addEventListener('keydown', action, false);
+  return box;
+}
+
+function make_seq(alphabet, seq) {
+  var i, j, letter, lbox, sbox;
+  sbox = document.createElement("span");
+  for (i = 0; i < seq.length; i = j) {
+    letter = seq.charAt(i);
+    for (j = i+1; j < seq.length; j++) {
+      if (seq.charAt(j) !== letter) {
+        break;
+      }
+    }
+    lbox = document.createElement("span");
+    lbox.style.color = alphabet.get_colour(alphabet.get_index(letter));
+    lbox.appendChild(document.createTextNode(seq.substring(i, j)));
+    sbox.appendChild(lbox);
+  }
+  return sbox;
+}
+
+//
+// make_pv_text
+//
+// Returns the string p-value, with the p italicised.
+///
+function make_pv_text() {
+  var pv_text = document.createElement("span");
+  var pv_italic_text = document.createElement("span");
+  pv_italic_text.appendChild(document.createTextNode("p"));
+  pv_italic_text.style.fontStyle = "italic";
+  pv_text.appendChild(pv_italic_text);
+  pv_text.appendChild(document.createTextNode("-value"));
+  return pv_text;
+}
+
+function append_site_entries(tbody, motif, site_index, count) {
+  "use strict";
+  var i, end;
+  var sites, site, sequences, sequence;
+  var rbody;
+  if (typeof count !== "number") {
+    count = 20;
+  }
+  sequences = data["sequence_db"]["sequences"];
+  sites = motif["sites"];
+  end = Math.min(site_index + count, sites.length);
+  for (i = site_index; i < end; i++) {
+    site = sites[i];
+    sequence = sequences[site["seq"]];
+
+    rbody = tbody.insertRow(tbody.rows.length);
+    add_text_cell(rbody, "" + (site["seq"] + 1) + ".", "site_num");
+    add_text_cell(rbody, sequence["name"], "site_name");
+    add_text_cell(rbody, site["rc"] ? "-" : "+", "site_strand");
+    add_text_cell(rbody, site["pos"] + 1, "site_start");
+    add_text_cell(rbody, site["pvalue"].toExponential(2), "site_pvalue");
+    add_text_cell(rbody, site["lflank"], "site lflank");
+    add_cell(rbody, make_seq(current_alphabet, site["match"]), "site match");
+    add_text_cell(rbody, site["rflank"], "site rflank");
+  }
+  return i;
+}
+
+function make_site_entries() {
+  "use strict";
+  var region;
+  region = this;
+  if (region.data_site_index >= region.data_motif["sites"].length) {
+    // all sites created
+    region.removeEventListener('scroll', make_site_entries, false);
+    return;
+  }
+  // if there's still 100 pixels to scroll than don't do anything yet
+  if (region.scrollHeight - (region.scrollTop + region.offsetHeight) > 100) {
+    return;
+  }
+
+  region.data_site_index = append_site_entries(
+      find_child(region, "sites_tbl").tBodies[0], 
+      region.data_motif, region.data_site_index, 20
+    ); 
+}
+
+function make_sites(motif) {
+  "use strict";
+  function add_site_header(row, title, nopad, help_topic, tag_class) {
+    var div, divcp, th;
+    th = document.createElement("th");
+    div = document.createElement("div");
+    div.className = "sites_th_inner";
+    if (typeof title !== "object") {
+      title = document.createTextNode("" + title);
+    }
+    div.appendChild(title);
+    if (help_topic) {
+      div.appendChild(document.createTextNode("\xA0"));
+      div.appendChild(help_button(help_topic));
+    }
+    divcp = div.cloneNode(true);
+    divcp.className = "sites_th_hidden";
+    th.appendChild(div);
+    th.appendChild(divcp);
+    if (nopad) {
+      th.className = "nopad";
+    }
+    if (tag_class) {
+      th.className += " " + tag_class;
+    }
+    row.appendChild(th);
+  }
+  var outer_tbl, inner_tbl, tbl, thead, tbody, rhead;
+
+  outer_tbl = document.createElement("div");
+  outer_tbl.className = "sites_outer";
+
+  inner_tbl = document.createElement("div");
+  inner_tbl.className = "sites_inner";
+  outer_tbl.appendChild(inner_tbl);
+
+  tbl = document.createElement("table");
+  tbl.className = "sites_tbl";
+  inner_tbl.appendChild(tbl);
+
+  thead = document.createElement("thead");
+  tbl.appendChild(thead);
+  tbody = document.createElement("tbody");
+  tbl.appendChild(tbody);
+
+  rhead = thead.insertRow(thead.rows.length);
+  add_site_header(rhead, "", true);
+  add_site_header(rhead, "Name", false, "pop_seq_name");
+  add_site_header(rhead, "Strand", false, "pop_site_strand", "site_strand_title");
+  add_site_header(rhead, "Start", false, "pop_site_start");
+  add_site_header(rhead, make_pv_text(), false, "pop_site_pvalue");
+  add_site_header(rhead, "", false);
+  add_site_header(rhead, "Sites", true, "pop_site_match");
+  add_site_header(rhead, "", false);
+
+  inner_tbl.data_motif = motif;
+  inner_tbl.data_site_index = append_site_entries(tbody, motif, 0, 20);
+  if (inner_tbl.data_site_index < motif["sites"].length) {
+    inner_tbl.addEventListener('scroll', make_site_entries, false);
+  }
+  return outer_tbl;
+}
+
+function make_motif_table_entry(row, alphabet, ordinal, motif, colw) {
+  "use strict";
+  function ev_sig(evalue_str) {
+    "use strict";
+    var ev_re, match, sig, exp, num;
+    ev_re = /^(.*)e(.*)$/;
+    if (match = ev_re.exec(evalue_str)) {
+      sig = parseFloat(match[1]);
+      exp = parseInt(match[2]);
+      if (exp >= 0) {
+        return false;
+      } else if (exp <= -3) {
+        return true;
+      } else {
+        return sig * Math.pow(10, exp) <= 0.05;
+      }
+    }
+    return true;
+  }
+  function make_preview(alphabet, motif) {
+    "use strict";
+    var pspm, preview, preview_rc;
+    var box, btn_box, logo_box, btn_plus, btn_minus;
+    if (motif["preview_logo"]) {
+      preview = motif["preview_logo"];
+      preview_rc = motif["preview_logo_rc"];
+    } else {
+      pspm = new Pspm(motif["pwm"]);
+      preview = make_logo(alphabet, pspm, 50, false, 0);
+      motif["preview_logo"] = preview;
+      if (alphabet.has_complement()) {
+        preview_rc = make_logo(alphabet, pspm, 50, true, 0, "logo_rc");
+        motif["preview_logo_rc"] = preview_rc;
+      }
+    }
+    if (preview_rc) {
+      btn_plus = document.createElement("div");
+      btn_plus.appendChild(document.createTextNode("+"));
+      btn_plus.className = "preview_btn plus";
+      btn_plus.tabIndex = "0";
+      btn_plus.addEventListener("click", action_btn_rc, false);
+      btn_plus.addEventListener("keydown", action_btn_rc, false);
+      btn_minus = document.createElement("div");
+      btn_minus.appendChild(document.createTextNode("-"));
+      btn_minus.className = "preview_btn minus";
+      btn_minus.tabIndex = "0";
+      btn_minus.addEventListener("click", action_btn_rc, false);
+      btn_minus.addEventListener("keydown", action_btn_rc, false);
+      btn_box = document.createElement("div");
+      btn_box.className = "preview_btn_box";
+      btn_box.appendChild(btn_plus);
+      btn_box.appendChild(btn_minus);
+    }
+    logo_box = document.createElement("div");
+    logo_box.className = "preview_logo_box";
+    logo_box.appendChild(preview);
+    if (preview_rc) logo_box.appendChild(preview_rc);
+    box = document.createElement("div");
+    box.className = "preview_box";
+    if (preview_rc) box.appendChild(btn_box);
+    box.appendChild(logo_box);
+    if (preview_rc) {
+      if (motif["rc"]) {
+        btn_minus.className += " active";
+        logo_box.className += " show_rc_logo";
+      } else {
+        btn_plus.className += " active";
+      }
+    }
+    return box;
+  }
+  var pspm, preview, preview_rc, c;
+  row.data_motif = motif;
+  row.id = motif["alt"];
+  row.data_ordinal = ordinal;
+  if (!ev_sig(motif["evalue"])) {
+    row.style.opacity = 0.4;
+  }
+  add_text_cell(row, "" + ordinal + ".", "motif_ordinal");
+  add_cell(row, make_preview(alphabet, motif), "motif_logo");
+  add_text_cell(row, motif["evalue"], "motif_evalue");
+  add_text_cell(row, motif["nsites"], "motif_nsites");
+  add_text_cell(row, motif["len"], "motif_width");
+  add_cell(row, make_sym_btn("\u21A7", "Show more information.", 
+    action_show_more), "motif_more");
+  add_cell(row, make_sym_btn("\u21E2", "Submit the motif to another MEME Suite program or download it.", function(e) { action_show_outpop(e, ordinal); }), "motif_submit");
+  if (colw) {
+    for (c = 0; c < row.cells.length; c++) {
+      row.cells[c].style.minWidth = colw[c] + "px";
+    }
+  }
+}
+
+function make_motifs_table(alphabet, start_ordinal, motifs, colw, stop_reason) {
+  var i, j;
+  var tbl, thead, tbody, tfoot, row, preview;
+  var motif, pspm;
+
+  tbl = document.createElement("table");
+  
+  thead = document.createElement("thead");
+  tbl.appendChild(thead);
+  tbody = document.createElement("tbody");
+  tbl.appendChild(tbody);
+  tfoot = document.createElement("tfoot");
+  tbl.appendChild(tfoot);
+
+  row = thead.insertRow(thead.rows.length);
+  add_text_header_cell(row, "", "", "motif_ordinal");
+  add_text_header_cell(row, "Logo", "pop_logo", "motif_logo");
+  add_text_header_cell(row, "E-value", "pop_ev", "motif_evalue");
+  add_text_header_cell(row, "Sites", "pop_sites", "motif_nsites");
+  add_text_header_cell(row, "Width", "pop_width", "motif_width");
+  add_text_header_cell(row, "More", "pop_more", "motif_more");
+  add_text_header_cell(row, "Submit/Download", "pop_submit_dl", "motif_submit");
+
+  for (i = 0; i < motifs.length; i++) {
+    row = tbody.insertRow(tbody.rows.length);
+    make_motif_table_entry(row, alphabet, start_ordinal + i, motifs[i], colw);
+  }
+
+  row = tfoot.insertRow(tfoot.rows.length);
+  add_text_header_cell(row, stop_reason, "", "stop_reason", "", 6);
+
+  return tbl;
+}
+
+function make_expanded_motif(alphabet, ordinal, motif, less_x, submit_x) {
+  "use strict";
+  var box, pspm, logo_box, large_logo, large_logo_rc, tab_logo, tab_logo_rc;
+  var btn, offset, norc;
+
+  box = clone_template("tmpl_motif_expanded");
+  box.data_motif = motif;
+  box.data_ordinal = ordinal;
+
+  pspm = new Pspm(motif["pwm"]);
+  if (typeof motif["rc"] !== "boolean") {
+    motif["rc"] = false;
+  }
+  if (motif["large_logo"]) {
+    large_logo = motif["large_logo"];
+    large_logo_rc = motif["large_logo_rc"];
+  } else {
+    large_logo = make_large_logo(alphabet, pspm, false, 0);
+    motif["large_logo"] = large_logo;
+    if (alphabet.has_complement()) {
+      large_logo_rc = make_large_logo(alphabet, pspm, true, 0, "logo_rc");
+      motif["large_logo_rc"] = large_logo_rc;
+    }
+  }
+  norc = (large_logo_rc == null);
+  toggle_class(box, "norc", norc);
+
+  logo_box = find_child(box, "tvar_logo");
+  logo_box.appendChild(large_logo);
+  if (large_logo_rc) logo_box.appendChild(large_logo_rc);
+  toggle_class(logo_box, "show_rc_logo", motif["rc"]);
+
+  tab_logo = find_child(box, "tvar_tab");
+  tab_logo_rc = find_child(box, "tvar_tab_rc");
+
+  toggle_class(tab_logo, "activeTab", !motif["rc"]);
+  toggle_class(tab_logo_rc, "activeTab", motif["rc"]);
+
+  tab_logo.addEventListener('click', action_rc_tab, false);
+  tab_logo.addEventListener('keydown', action_rc_tab, false);
+  tab_logo_rc.addEventListener('click', action_rc_tab, false);
+  tab_logo_rc.addEventListener('keydown', action_rc_tab, false);
+
+  set_tvar(box, "tvar_ordinal", ordinal); 
+  set_tvar(box, "tvar_evalue", motif["evalue"]);
+  set_tvar(box, "tvar_width", motif["len"]);
+  set_tvar(box, "tvar_site_count", motif["nsites"]);
+  set_tvar(box, "tvar_llr", motif["llr"]);
+  set_tvar(box, "tvar_ic", motif["ic"]);
+  set_tvar(box, "tvar_re", motif["re"]);
+  set_tvar(box, "tvar_bt", motif["bt"]);
+  if (data.sequence_db.primary_count > data.options.brief) {
+    if (data.options.brief == 1000) {
+      set_tvar(box, "tvar_sites", "Output of sites suppressed because there were more than 1000 (primary) sequences.");
+    } else {
+      set_tvar(box, "tvar_sites", "Output of sites suppressed by -brief option.");
+    }
+  } else {
+    set_tvar(box, "tvar_sites", make_sites(motif));
+  }
+
+  offset = 32; // 1* 5px padding + 2 * 10px padding + 2 * 2px border + 3px ??
+
+  btn = find_child(box, "tvar_less");
+  btn.style.left = (less_x - offset) + "px";
+  btn.addEventListener('click', action_show_less, false);
+  btn.addEventListener('keydown', action_show_less, false);
+  btn = find_child(box, "tvar_submit");
+  btn.style.left = (submit_x - offset) + "px";
+  btn.addEventListener('click', action_show_outpop, false);
+  btn.addEventListener('keydown', action_show_outpop, false);
+  return box;
+}
+
+//
+//
+//
+function make_motifs() {
+  "use strict";
+  function pixel_value(str_in) {
+    "use strict";
+    var px_re, match;
+    px_re = /^(\d+)px$/;
+    if (match = px_re.exec(str_in)) {
+      return parseInt(match[1], 10);
+    }
+    return 0;
+  }
+  var container, tbl;
+  var colw, r, row, c, cell, cell_style, pad_left, pad_right;
+
+  // make the motifs table
+  container = $("motifs");
+  container.innerHTML = ""; // clear content
+
+  tbl = make_motifs_table(current_alphabet, 1, data["motifs"], colw, data["stop_reason"]);
+  container.appendChild(tbl);
+
+  // measure table column widths
+  colw = [];
+  row = tbl.tBodies[0].rows[0];
+  for (c = 0; c < row.cells.length; c++) {
+    var padLeft, padRight;
+    cell = row.cells[c];
+    cell_style = window.getComputedStyle(cell, null);
+    pad_left = pixel_value(cell_style.getPropertyValue("padding-left"));
+    pad_right = pixel_value(cell_style.getPropertyValue("padding-right"));
+    colw[c] = cell.clientWidth - pad_left - pad_right;
+    if (typeof colw[c] !== "number" || colw[c] < 0) {
+      colw[c] = 1;
+    }
+  }
+
+  // set minimum table column widths on each row so later when we remove rows it still aligns
+  for (r = 0; r < tbl.tBodies[0].rows.length; r++) {
+    row = tbl.tBodies[0].rows[r];
+    for (c = 0; c < row.cells.length; c++) {
+      row.cells[c].style.minWidth = colw[c] + "px";
+    }
+  }
+
+  // store the table column widths so we can create rows latter with the same minimums
+  container.data_colw = colw;
+
+  // calculate the x offset for the buttons
+  row = tbl.tBodies[0].rows[0];
+  container.data_more_x = coords(find_child(find_child(row, "motif_more"), "sym_btn"))[0];
+  container.data_submit_x = coords(find_child(find_child(row, "motif_submit"), "sym_btn"))[0];
+
+  draw_on_screen();
+}
+
+function make_meme_block(container, max_seq_len, is_scan, site) {
+  "use strict";
+  var motif = data.motifs[site.motif];
+  var block = make_block(container, max_seq_len, site.pos, motif.len,
+      site.pvalue, site.rc, site.motif, is_scan);
+  var handler = (is_scan ?
+      make_scan_popup(site, motif, block) :
+      make_block_popup(site, motif, block));
+  block.addEventListener("mouseover", handler, false);
+  block.addEventListener("mouseout", handler, false);
+}
+
+function append_blocks_entries(tbody, seq_index, count) {
+  "use strict";
+  var i, end, j;
+  var max_pvalue, max_block_height, max_seq_len, sequences;
+  var sequence, sites, scans, scan;
+  var container, plus, minus, rule, row;
+  // define some constants
+  max_seq_len = data.sequence_db.max_length;
+  // determine how many to load
+  end = Math.min(seq_index + count, data.sequence_db.sequences.length);
+  for (i = seq_index; i < end; i++) {
+    // get the sequence
+    sequence = data.sequence_db.sequences[i];
+    // make the containers for the block diagram
+    container = make_block_container(current_alphabet.has_complement(),
+        data.options.revcomp, max_seq_len, sequence.length);
+    // create blocks for the motif sites
+    sites = sequence["sites"];
+    for (j = 0; j < sites.length; j++)
+      make_meme_block(container, max_seq_len, false, sites[j]);
+    // create blocks for the scanned sites
+    scan = data.scan[i];
+    for (j = 0; j < scan.sites.length; j++)
+      make_meme_block(container, max_seq_len, true, scan.sites[j]);
+    // create a row for the sequence
+    row = tbody.insertRow(tbody.rows.length);
+    toggle_class(row, "empty_seq", sites.length == 0 && scan.sites.length == 0);
+    toggle_class(row, "only_scan", sites.length == 0 && scan.sites.length > 0);
+    add_text_cell(row, (i + 1) + ".", "blockdiag_num");
+    add_text_cell(row, sequence["name"], "blockdiag_name");
+    add_text_cell(row, scan["pvalue"].toExponential(2), "blockdiag_pvalue");
+    add_cell(row, container, "block_td"); 
+  }
+  return end;
+}
+
+function make_blocks_entries() {
+  "use strict";
+  var region;
+  region = this;
+  if (region.data_blocks_index >= data["sequence_db"]["sequences"].length) {
+    // all sites created
+    region.removeEventListener('scroll', make_blocks_entries, false);
+    return;
+  }
+  // if there's still 100 pixels to scroll then don't do anything yet
+  if (region.scrollHeight - (region.scrollTop + region.offsetHeight) > 100) {
+    return;
+  }
+
+  region.data_blocks_index = append_blocks_entries(
+      find_child(region, "blocks_tbl").tBodies[0], 
+      region.data_blocks_index, 20
+    ); 
+}
+
+// Apply opacity alpha to color rgb with backrgound bkg.
+function RGBAtoRGB(rgb, bkg, opacity) {
+  var i;
+  var rgb_new = [];
+  for (i=0; i<3; i++) {
+    rgb_new[i] = Math.round(((1-opacity) * bkg[i]) + (opacity * rgb[i]));
+  }
+  return rgb_new;
+}
+
+// Function to measure the size of text on a canvas.
+var MeasureText = function(font, text) {
+  var image = document.createElement("canvas");
+  var image_ctx = image.getContext('2d');
+  image_ctx.save();
+  image_ctx.font = font;
+  var text_length = image_ctx.measureText(text).width;
+  image.remove();
+  return text_length;
+} // MeasureText
+
+// Functions to download the motif block diagram as a PDF or SVG file.
+function download_PDF_block_diagram() {
+  downloadBlockDiagram(true, 'bitbucket');
+}
+function download_SVG_block_diagram() {
+  downloadBlockDiagram(false, 'bitbucket');
+}
+
+// Helper function to create a script element for downloading javascript.
+function createScriptElement(url, file, integrity)
+{
+  console.log('Downloading ' + file + ' from ' + url + '.');
+  const script = document.createElement('script');
+  script.setAttribute('src', url + '/' + file);
+  if (integrity) script.setAttribute('integrity', integrity);
+  script.setAttribute('crossorigin', 'anonymous');
+  script.setAttribute('async', '');
+  document.head.appendChild(script);
+}
+
+// Helper function to download the motif block diagram as a PDF or SVG file.
+var downloadBlockDiagram = function(
+  make_pdf,
+  next_source
+) {
+  var script_file, integrity_key;
+  // Check if necessary javascript has been loaded.
+  if ( (make_pdf && typeof jsPDF === 'undefined') ||
+    (!make_pdf && typeof d3 === 'undefined') ) {
+    if (next_source === 'bitbucket') {
+      if (make_pdf) {
+        script_file = 'jspdf.min.js';
+      } else {
+        script_file = 'd3.v5.min.js';
+      }
+      createScriptElement('https://memesuite.bitbucket.io/javascript', script_file);
+      // Wait 3 seconds and then try to create the diagram.
+      setTimeout(downloadBlockDiagram, 3000, make_pdf, 'cloudflare');
+    } else if (next_source === 'cloudflare') {
+      if (make_pdf) {
+        script_file = 'jspdf/1.5.3/jspdf.min.js';
+        integrity_key = 'sha512-ToRWKKOvhBSS8EtqSflysM/S7v9bB9V0X3B1+E7xo7XZBEZCPL3VX5SFIp8zxY19r7Sz0svqQVbAOx+QcLQSAQ=='
+      } else {
+        script_file = 'd3/5.16.0/d3.min.js';
+        integrity_key = 'sha512-FHsFVKQ/T1KWJDGSbrUhTJyS1ph3eRrxI228ND0EGaEp6v4a/vGwPWd3Dtd/+9cI7ccofZvl/wulICEurHN1pg==';
+      }
+      createScriptElement('https://cdnjs.cloudflare.com/ajax/libs', script_file, integrity_key);
+      // Wait 3 seconds and then try to create the diagram.
+      setTimeout(downloadBlockDiagram, 3000, make_pdf, 'none');
+    } else {
+      // No more sources for javascript.  Call so error message will be shown.
+      downloadBlockDiagramMain(make_pdf);
+    }
+  } else {
+    // Create the diagram.
+    downloadBlockDiagramMain(make_pdf);
+  }
+}
+
+// Main function to download the motif block diagram as a PDF or SVG file.
+var downloadBlockDiagramMain= function(
+  make_pdf
+) {
+  // Check that necessary javascript was downloaded.
+  if ( (make_pdf && typeof jsPDF === 'undefined') ||
+    (!make_pdf && typeof d3 === 'undefined') ) {
+    var id = make_pdf ? $("pdfButton") : $("svgButton");
+    help_popup(id, "pop_offline");
+    return;
+  }
+
+  // Determine which lines are visible in the HTML inner scroll window.
+  var inner_tbl = $("blocks_scroll");
+  var pix_per_sequence = 27;		// (vertical) pixels per sequence diagram line
+  var first = Math.round(inner_tbl.scrollTop / pix_per_sequence) + 1;
+  var last = first + Math.round(inner_tbl.offsetHeight / pix_per_sequence) - 1;
+
+  // Get the contents of the HTML inner scroll window while saving the sequences to be printed.
+  var numbers = document.getElementsByClassName("blockdiag_num");
+  var bars = {};
+  var visible_motifs = {};
+  var seq_index = 0;
+  var rgb;
+  for (var i=0; i<numbers.length && seq_index < last; i++) {
+    var row_node = numbers[i].parentNode;
+    // Check if the sequence is displayed in the outer scrolling window.
+    var seq_name = numbers[i].nextSibling.innerHTML;
+    if (
+      ($("rdo_sites_only").checked && row_node.getAttribute("class").includes("only_scan"))
+      || 
+      (! $("rdo_all_seqs").checked && row_node.getAttribute("class").includes("empty_seq"))
+    ) { continue; }
+    seq_index++;
+
+    if (seq_index < first) { continue; }		// sequence not in HTML inner scrolling window 
+
+    var pvalue = numbers[i].nextSibling.nextSibling.innerHTML;
+    var far = numbers[i].nextSibling.nextSibling.nextSibling.children[0].children;
+    var seq_length = data.sequence_db.sequences[i].length;
+
+    var seqObj = [];
+    seqObj["length"] = seq_length;
+    seqObj["pvalue"] = pvalue;
+    seqObj["pn"] = [];
+    seqObj["width"] = [];
+    seqObj["left"] = [];
+    seqObj["height"] = [];
+    seqObj["color"] = [];
+    seqObj["opacity"] = [];
+    for (var x = 0; x < far.length; x++) {
+      if ((far[x].getAttribute("style") != null)
+        && (
+          ( $("rdo_sites_only").checked && ! far[x].getAttribute("class").includes("scanned"))
+          || ( $("rdo_sites_and_scan").checked || $("rdo_all_seqs").checked )
+        )
+      ) {
+        if (far[x].getAttribute("style").includes("rgb")) {
+          var compStyles = far[x].style;
+	  // Make scanned sites get displayed first so they will not "cover" regular sites.
+	  var site_pn = far[x].getAttribute("class").includes("top") ? "+" : "-";
+	  var site_width = parseFloat(compStyles.width.slice(0, -1));
+	  var site_left = parseFloat(compStyles.left.slice(0, -1));
+	  var site_height = parseFloat(compStyles.height.slice(0, -2));
+	  var site_color = compStyles.backgroundColor.slice(4, -1).replace(/ /g, "");
+          if (far[x].getAttribute("class").includes("scanned")) {
+	    seqObj["pn"].unshift(site_pn);
+	    seqObj["width"].unshift(site_width);
+	    seqObj["left"].unshift(site_left);
+	    seqObj["height"].unshift(site_height);
+	    seqObj["color"].unshift(site_color);
+            seqObj["opacity"].unshift(0.3);
+          } else {
+	    seqObj["pn"].push(site_pn);
+	    seqObj["width"].push(site_width);
+	    seqObj["left"].push(site_left);
+	    seqObj["height"].push(site_height);
+	    seqObj["color"].push(site_color);
+            seqObj["opacity"].push(1);
+          }
+	  visible_motifs[far[x].getAttribute("data-colour-index")] = site_color;
+        }
+      }
+    }
+    // Save the sequence data if it has motifs (or rdo_all_seqs is checked)
+    if ($("rdo_all_seqs").checked || seqObj["width"].length > 0) { 
+      bars[seq_name] = seqObj; 
+    }
+  }
+
+  // jsPDF coordinates are always in points.
+  var font_size = 13;
+  var nbars = Object.keys(bars).length;
+  var legend_font_size = 0.8 * font_size;
+
+  // Initialize field widths in points by measuring header text.
+  var font = "bold " + font_size + "pt Helvetica, sans-serif";
+  var max_name_width = MeasureText(font, "Name");
+  var max_pvalue_width = MeasureText(font, "p-value");
+
+  var max_seq_length = 0;		// in characters
+  var has_complement = current_alphabet.has_complement();
+  var revcomp = data.options["revcomp"];
+
+  // Measure text of numbers, names and p-values, convert to points and save the max.
+  font = font_size + "pt Helvetica, sans-serif";
+  var seq_name;
+  for (seq_name in bars) {
+    var seq_name_width = MeasureText(font, seq_name);
+    var pvalue_width = MeasureText(font, pvalue);
+    var seq_length = bars[seq_name]["length"];
+    if (seq_length > max_seq_length) { max_seq_length = seq_length; }
+    if (seq_name_width > max_name_width) { max_name_width = seq_name_width; }
+    if (pvalue_width > max_pvalue_width) { max_pvalue_width = pvalue_width; }
+  }
+
+  // Get the length in characters of the longest visible motif.
+  var max_motif_length = 0;
+  var motif_index, motif_length;
+  for (motif_index in visible_motifs) {
+    motif_length = data.motifs[motif_index].len;
+    if (motif_length > max_motif_length) { max_motif_length = motif_length; }
+  }
+
+  // Sort the motif indices.
+  var motif_indices = [];
+  var sorted_motif_indices = [];
+  for (motif_index in visible_motifs) {
+    motif_indices.push(Number(motif_index));
+  }
+  sorted_motif_indices = motif_indices.sort(function(a, b){return a-b;});
+
+  // Set up values for main section.
+  var height = (nbars+1) * (2.6*font_size);
+  var nmotifs = Object.keys(visible_motifs).length;
+  var name_field_width = max_name_width + font_size;
+  var pvalue_field_width = max_pvalue_width + font_size;
+  var plus_minus_field_width = has_complement ? 2*font_size : font_size;
+  var non_diagram_width = name_field_width + pvalue_field_width + plus_minus_field_width;
+  var diagram_width = 47 * font_size;
+  var pix_per_char = diagram_width/max_seq_length;
+  var x_scale_factor = data.sequence_db.max_length/100;	// Scale factor comes from function make_block().
+  var diagram_line_height = (height-2*font_size)/nbars; 
+  var doc_width = diagram_width + non_diagram_width + 2*font_size;
+  var doc_height = height + 0.5*font_size;
+
+  // Set up values for the legend.
+  var tmp_font = legend_font_size + "pt Courier, normal";
+  var courier_width = MeasureText(tmp_font, "A");
+
+  var legend_line_height = 1.2 * legend_font_size;
+  var index_field_width = 3 * legend_font_size;
+  var symbol_field_width = 5 * legend_font_size;
+  var legend_non_consensus_width = index_field_width + symbol_field_width + 3*legend_font_size;
+  var legend_hdr_font = legend_font_size + "pt Helvetica, sans-serif";
+  var consensus_hdr_width = MeasureText(legend_hdr_font, "Motif Consensus");
+  var consensus_field_width = doc_width - legend_non_consensus_width - legend_font_size;
+  // Get number of characters that will fit in legend consensus field.
+  var legend_split_length = Math.floor(consensus_field_width/courier_width);
+  // Get number of lines in legend.
+  var n_legend_lines = 0;
+  for (motif_index in visible_motifs) {
+    motif_length = data.motifs[motif_index].len;
+    n_legend_lines += Math.ceil(motif_length/legend_split_length);
+  }
+  if (n_legend_lines > 0) { n_legend_lines += 3; }	// header line + 2*space
+  var legend_width = legend_non_consensus_width + Math.min(legend_split_length, max_motif_length)*courier_width;
+  var legend_height = n_legend_lines * legend_line_height;
+  doc_height += legend_height + 1*font_size;
+
+  if (make_pdf) {
+    // Now create the PDF document.
+    // This next line is necessary because jsPDF silently swaps width and height.
+    var orient = doc_width > doc_height ? 'landscape' : 'portrait';
+    doc = new jsPDF(
+      {
+	orientation: orient,
+	unit: 'pt',
+	format: [doc_width, doc_height]
+      }
+    );
+
+    // Set the font size for the PDF.
+    doc.setFontSize(1.33*font_size);
+
+    // Create the header.
+    var offset = font_size;
+    var liney = 1.5*font_size;
+    // .. Name hdr ..
+    doc.setFont("Helvetica", "bold");
+    doc.text("Name", offset, liney);
+    offset += name_field_width;
+
+    // p-value hdr
+    doc.setFont("Helvetica", "bolditalic");
+    doc.text("p", offset + font_size, liney);
+    doc.setFont("Helvetica", "bold");
+    doc.text("-value", offset + 2*font_size, liney);
+    offset += pvalue_field_width + plus_minus_field_width;
+
+    // Motif Location hdr
+    doc.text("Motif Locations", offset, liney);
+
+    // Generate the data object for the PDF.
+    liney -= 0.5*font_size;
+    var dy = font_size/3.5;
+    for (var seq_name in bars) {
+      liney += diagram_line_height;
+      offset = font_size;
+
+      //
+      // Generate the text fields.
+      //
+      doc.setFont("Helvetica", "normal");
+
+      // Sequence name text
+      doc.text(seq_name, offset, liney + dy);
+      offset += name_field_width;
+
+      // p-value text
+      doc.text(bars[seq_name]["pvalue"], offset + pvalue_field_width, liney + dy, {align: "right"});
+      offset += pvalue_field_width;
+
+      // +/- text (optional)
+      if (has_complement) {
+	doc.text("+", offset+font_size, liney + dy - font_size/2);
+	if (revcomp) {
+	  doc.text("-", offset+1.15*font_size, liney + dy + font_size/2);
+	}
+      }
+      offset += plus_minus_field_width;
+
+      // Generate the base line.
+      doc.setLineWidth(0.35);
+      doc.line(offset, liney, offset + (bars[seq_name]["length"] * pix_per_char), liney);
+
+      // Generate the blocks.
+      for (var i = 0; i < bars[seq_name]["width"].length; i++) {
+	if (bars[seq_name]["pn"][i] == undefined) { continue; }
+	rgb = bars[seq_name]["color"][i].split(",").map(Number);
+	var opacity =  bars[seq_name]["opacity"][i]; 
+	if (opacity != 1) { rgb = RGBAtoRGB(rgb, [255,255,255], opacity); }
+	var bar_x = offset + (bars[seq_name]["left"][i] * x_scale_factor * pix_per_char);
+	var bar_y = (bars[seq_name]["pn"][i] == "+") ? (liney - 0.1*font_size*bars[seq_name]["height"][i]) : liney;
+	doc.setFillColor(rgb[0], rgb[1], rgb[2]);
+	doc.rect(bar_x, bar_y, bars[seq_name]["width"][i] * x_scale_factor * pix_per_char, 0.1*font_size*bars[seq_name]["height"][i], 'FD');
+      }
+    }
+
+    //
+    // Generate the legend.
+    //
+    if (n_legend_lines > 0) {
+      doc.setFontSize(1.33*legend_font_size);
+      dy = 0.8 * legend_font_size;
+
+      // The legend header.
+      var legend_top = liney + 2*legend_font_size;
+      liney += 4.5*legend_font_size;
+      offset = legend_font_size;
+      doc.setFont("Helvetica", "bold");
+      doc.text("Motif", offset, liney);
+      offset += index_field_width + legend_font_size;
+      doc.text("Symbol", offset, liney);
+      offset += symbol_field_width + legend_font_size;
+      doc.text("Motif Consensus", offset, liney);
+      liney -= 0.5*legend_font_size;
+      liney += legend_line_height;
+
+      for (var i=0; i<motif_indices.length; i++) {
+	motif_index = sorted_motif_indices[i];
+	offset = legend_font_size;
+
+	// Motif Name
+	doc.setFont("Helvetica", "normal");
+	var motif_index_string = (motif_index+1).toString();
+	motif_index_string = motif_index_string + ".";
+	var dx = 3 * legend_font_size;
+	doc.text(motif_index_string, offset+dx, liney+dy, {align: "right"});
+	offset += index_field_width + legend_font_size;
+
+	// Motif Symbol
+	motif_length = data.motifs[motif_index].len;
+	rgb = visible_motifs[motif_index].split(",").map(Number);
+	var bar_x = offset;
+	var bar_y = liney;
+	doc.setFillColor(rgb[0], rgb[1], rgb[2]);
+	doc.rect(bar_x, bar_y, symbol_field_width*(motif_length/max_motif_length), legend_font_size, 'FD');
+	offset += symbol_field_width + legend_font_size;
+
+	// Motif Consensus Sequence
+	doc.setFont("Courier", "normal");
+	var motif_consensus = data.motifs[motif_index].id;
+	doc.text(motif_consensus, offset, liney+dy, {maxWidth: legend_split_length*courier_width});
+	liney += Math.ceil(motif_length/legend_split_length) * legend_line_height;
+      }
+
+      // Draw box around legend.
+      doc.rect(
+	0.5*legend_font_size, 
+	legend_top + 0.5*legend_font_size, 
+	Math.max(legend_width, legend_non_consensus_width + consensus_hdr_width + courier_width),
+	legend_height
+      );
+    } // legend
+
+    doc.save('motif_locations.pdf');
+
+  } else {
+    // Download an SVG document.
+    var body = d3.select("#blocks").append("svg")
+      .attr("width", (diagram_width + non_diagram_width) + "pt")
+      .attr("height", (doc_height+legend_font_size).toString())
+      .attr("background-color", "lightgrey")
+      .attr("id", "memeSVG")
+      .attr("xmlns", "http://www.w3.org/2000/svg");
+
+    // Create the header.
+    var x = 0;
+    var offset = font_size;
+    var liney = 1.5*font_size;
+
+    // .. Name hdr ..
+    body.append("text")
+      .attr("x", offset)
+      .attr("y", liney)
+      .attr("font-family", "Helvetica, sans-serif")
+      .attr("font-size", font_size+"pt")
+      .attr("font-weight", "bold")
+      .text("Name");
+      offset += name_field_width;
+
+    // p-value hdr
+    body.append("text")
+      .attr("x", offset + 2*font_size)
+      .attr("y", liney)
+      .attr("font-family", "Helvetica, sans-serif")
+      .attr("font-size", font_size+"pt")
+      .attr("font-weight", "bold")
+      .attr("font-style", "italic")
+      .text("p");
+    body.append("text")
+      .attr("x", offset + 3*font_size)
+      .attr("y", liney)
+      .attr("font-family", "Helvetica, sans-serif")
+      .attr("font-size", font_size+"pt")
+      .attr("font-weight", "bold")
+      .text("-value");
+    offset += pvalue_field_width + plus_minus_field_width + font_size;
+
+    // Motif Location hdr
+    body.append("text")
+      .attr("x", offset)
+      .attr("y", liney)
+      .attr("font-family", "Helvetica, sans-serif")
+      .attr("font-size", font_size+"pt")
+      .attr("font-weight", "bold")
+      .text("Motif Locations");
+
+    // Generate the data for the SVG.
+    liney -= 0.5*font_size;
+    var dy = font_size/3.5;
+    for (var seq_name in bars) {
+      liney += diagram_line_height;
+      offset = font_size;
+
+      //
+      // Generate the text fields.
+      //
+
+      // Sequence name text
+      body.append("text")
+	.attr("x", offset)
+	.attr("y", liney + dy)
+	.attr("font-family", "Helvetica, sans-serif")
+	.attr("font-size", font_size+"pt")
+	.text(seq_name);
+      offset += name_field_width;
+
+      // p-value text
+      body.append("text")
+	.attr("x", offset + font_size+ pvalue_field_width)
+	.attr("y", liney + dy)
+	.attr("font-family", "Helvetica, sans-serif")
+	.attr("font-size", font_size+"pt")
+	.attr("text-anchor", "end")
+	.text(bars[seq_name]["pvalue"]);
+      offset += pvalue_field_width + font_size;
+
+      // +/- text (optional)
+      if (has_complement) {
+	body.append("text")
+	  .attr("x", offset+font_size)
+	  .attr("y", liney + dy - font_size/2)
+	  .attr("font-family", "Helvetica, sans-serif")
+	  .attr("font-size", font_size+"pt")
+	  .text("+");
+	if (revcomp) {
+	  body.append("text")
+	    .attr("x", offset+1.15*font_size)
+	    .attr("y", liney + dy + font_size/2)
+	    .attr("font-family", "Helvetica, sans-serif")
+	    .attr("font-size", font_size+"pt")
+	    .text("-");
+	}
+      }
+      offset += plus_minus_field_width;
+
+      // Generate the base line.
+      body.append("line")
+	.attr("x1", offset)
+	.attr("x2", offset + (bars[seq_name]["length"] * pix_per_char))
+	.attr("y1", liney)
+	.attr("y2", liney)
+	.attr("stroke-width", 0.5)
+	.attr("stroke","black");
+
+      // Generate the blocks.
+      for (var i = 0; i < bars[seq_name]["width"].length; i++) {
+	if (bars[seq_name]["pn"][i] == undefined) { continue; }
+	body.append("rect")
+	  .attr("x", offset + (bars[seq_name]["left"][i] * x_scale_factor * pix_per_char) )
+	  .attr("y", (bars[seq_name]["pn"][i] == "+") ? (liney - 0.1*font_size*bars[seq_name]["height"][i]) : liney)
+	  .attr("width", bars[seq_name]["width"][i] * x_scale_factor * pix_per_char) 
+	  .attr("height", 0.1*font_size*bars[seq_name]["height"][i])
+	  .attr("fill", "rgb("+bars[seq_name]["color"][i] + ")")
+	  .attr("fill-opacity", bars[seq_name]["opacity"][i])
+	  .attr("stroke-width", 0.5)
+	  .attr("stroke","black");
+      }
+    }
+    
+    //
+    // Generate the legend.
+    //
+    if (n_legend_lines > 0) {
+      dy = 0.8 * legend_font_size;
+
+      // The legend header.
+      var legend_top = liney + 2*legend_font_size;
+      liney += 4.5*legend_font_size;
+      offset = legend_font_size;
+      body.append("text")
+	.attr("x", offset)
+	.attr("y", liney)
+	.attr("font-family", "Helvetica, sans-serif")
+	.attr("font-size", legend_font_size+"pt")
+        .attr("font-weight", "bold")
+	.text("Motif");
+      offset += index_field_width + legend_font_size;
+      body.append("text")
+	.attr("x", offset)
+	.attr("y", liney)
+	.attr("font-family", "Helvetica, sans-serif")
+	.attr("font-size", legend_font_size+"pt")
+        .attr("font-weight", "bold")
+	.text("Symbol");
+      offset += symbol_field_width + legend_font_size;
+      body.append("text")
+	.attr("x", offset)
+	.attr("y", liney)
+	.attr("font-family", "Helvetica, sans-serif")
+	.attr("font-size", legend_font_size+"pt")
+        .attr("font-weight", "bold")
+	.text("Motif Consensus");
+      liney -= 0.5*legend_font_size;
+      liney += legend_line_height;
+
+      for (var i=0; i<motif_indices.length; i++) {
+	motif_index = sorted_motif_indices[i];
+	offset = legend_font_size;
+
+	// Motif Name
+	var motif_index_string = (motif_index+1).toString();
+	motif_index_string = motif_index_string + ".";
+	var dx = 3.3 * legend_font_size;
+	body.append("text")
+	  .attr("x", offset+dx)
+	  .attr("y", liney+dy)
+	  .attr("font-family", "Helvetica, sans-serif")
+	  .attr("font-size", legend_font_size+"pt")
+	  .attr("text-anchor", "end")
+	  .text(motif_index_string);
+	offset += index_field_width + legend_font_size;
+
+	// Motif Symbol
+	motif_length = data.motifs[motif_index].len;
+	var bar_x = offset;
+	var bar_y = liney;
+	body.append("rect")
+	  .attr("x", bar_x )
+	  .attr("y", liney)
+	  .attr("width", symbol_field_width*(motif_length/max_motif_length)) 
+	  .attr("height", legend_font_size)
+	  .attr("fill", "rgb("+ visible_motifs[motif_index] + ")")
+	  .attr("stroke-width", 0.5)
+	  .attr("stroke","black");
+	offset += symbol_field_width + legend_font_size;
+
+	// Motif Consensus Sequence
+	var motif_consensus = data.motifs[motif_index].id;
+	var cons_length = motif_consensus.length;
+        var start_index = 0;
+        while (start_index < cons_length) {
+	  body.append("text")
+	    .attr("x", offset)
+	    .attr("y", liney+dy)
+	    .attr("font-family", "Courier")
+	    .attr("font-size", legend_font_size+"pt")
+	    .text(motif_consensus.slice(start_index, Math.min(cons_length, start_index+legend_split_length)))
+	  liney += legend_line_height;
+	  start_index += legend_split_length;
+        }
+      }
+
+      // Draw box around legend.
+      body.append("rect")
+	.attr("x", 0.5*legend_font_size)
+	.attr("y", legend_top + 0.5*legend_font_size)
+	.attr("width", Math.max(legend_width, legend_non_consensus_width + consensus_hdr_width + courier_width))
+	.attr("height", legend_height)
+	.attr("fill", "none")
+	.attr("stroke-width", 1)
+	.attr("stroke", "black");
+
+    } // legend
+
+    var svg = document.getElementsByTagName("svg")[0].outerHTML;
+    var svgBlob = new Blob([svg], {type:"image/svg+xml;charset=utf-8"});
+    var svgUrl = URL.createObjectURL(svgBlob);
+    var downloadLink = document.createElement("a");
+    downloadLink.href = svgUrl;
+    downloadLink.download = "meme-motif-locations.svg";
+    document.getElementById("sites_sec").appendChild(downloadLink);
+    downloadLink.click();
+    downloadLink.remove();
+    document.getElementById("memeSVG").remove();
+
+  } // SVG
+
+};
+
+function make_blocks() {
+  "use strict";
+  function add_seqs_filter(container, id, checked, label_text, help_topic) {
+    "use strict";
+    var label, radio;
+    radio = document.createElement("input");
+    radio.type = "radio";
+    radio.name = "seqs_display";
+    radio.id = id;
+    radio.checked = checked;
+    radio.addEventListener('click', action_seqs_filter, false);
+    label = document.createElement("label");
+    label.appendChild(document.createTextNode(label_text));
+    label.htmlFor = id;
+    container.appendChild(radio);
+    container.appendChild(label);
+    if (help_topic) {
+      container.appendChild(document.createTextNode("\xA0"));
+      container.appendChild(help_button(help_topic));
+    }
+  }
+  function add_block_diagram_button(container, id, buttonText, help_topic) {
+    var button, label;
+    button = document.createElement("button");
+    button.id = id;
+    label = document.createTextNode(buttonText);
+    button.appendChild(label);
+    button.onclick = (id === "pdfButton") ? download_PDF_block_diagram : download_SVG_block_diagram;
+    container.appendChild(document.createTextNode("  "));
+    container.appendChild(button);
+    if (help_topic) {
+      container.appendChild(document.createTextNode("\xA0"));
+      container.appendChild(help_button(help_topic));
+    }
+    //var new_icon = document.createElement("img");
+    //new_icon.src = new_icon_src;
+    //new_icon.alt = "NEW";
+    //container.appendChild(document.createTextNode("  "));
+    //container.appendChild(new_icon);
+  }
+  function add_blocks_header(row, title, nopad, help_topic) {
+    "use strict";
+    var div, divcp, th;
+    th = document.createElement("th");
+    div = document.createElement("div");
+    div.className = "blocks_th_inner";
+    if (typeof title !== "object") {
+      title = document.createTextNode("" + title);
+    }
+    div.appendChild(title);
+    if (help_topic) {
+      div.appendChild(document.createTextNode("\xA0"));
+      div.appendChild(help_button(help_topic));
+    }
+    divcp = div.cloneNode(true);
+    divcp.className = "blocks_th_hidden";
+    th.appendChild(div);
+    th.appendChild(divcp);
+    if (nopad) {
+      th.className = "nopad";
+    }
+    row.appendChild(th);
+  }
+  var container;
+  var page, view_height, outer_tbl, inner_tbl, tbl, thead, tbody, rhead;
+  var in_view, i, seq_count;
+  
+  page = (document.compatMode === "CSS1Compat") ? document.documentElement : document.body;
+  view_height = Math.max(page.clientHeight - 300, 300);
+
+  container = $("blocks");
+  toggle_class(container, "hide_empty_seqs", true);
+  toggle_class(container, "hide_only_scan", true);
+  container.innerHTML = "";
+  add_seqs_filter(container, "rdo_sites_only", true, "Only Motif Sites", "pop_motif_sites");
+  add_seqs_filter(container, "rdo_sites_and_scan", false, "Motif Sites+Scanned Sites", "pop_scanned_sites");
+  add_seqs_filter(container, "rdo_all_seqs", false, "All Sequences", "pop_all_sequences");
+  add_block_diagram_button(container, "pdfButton", "Download PDF", "pop_download_pdf_motif_locations");
+  add_block_diagram_button(container, "svgButton", "Download SVG", "pop_download_svg_motif_locations");
+
+  outer_tbl = document.createElement("div");
+  outer_tbl.className = "blocks_outer";
+
+  inner_tbl = document.createElement("div");
+  inner_tbl.id = "blocks_scroll";
+  inner_tbl.className = "blocks_inner";
+  inner_tbl.style.maxHeight = view_height + "px";
+  outer_tbl.appendChild(inner_tbl);
+
+  tbl = document.createElement("table");
+  tbl.className = "blocks_tbl";
+  inner_tbl.appendChild(tbl);
+
+  thead = document.createElement("thead");
+  tbl.appendChild(thead);
+  tbody = document.createElement("tbody");
+  tbl.appendChild(tbody);
+
+  rhead = thead.insertRow(thead.rows.length);
+  add_blocks_header(rhead, "", true);
+  add_blocks_header(rhead, "Name", false, "pop_seq_name");
+  add_blocks_header(rhead, make_pv_text(), false, "pop_seq_pvalue");
+  add_blocks_header(rhead, "Motif Locations", false, "pop_motif_location");
+
+  container.appendChild(outer_tbl);
+
+  seq_count = data["sequence_db"]["sequences"].length;
+  in_view = Math.max(Math.ceil(view_height / 25), 1);
+  i = append_blocks_entries(tbody, 0, in_view);
+
+  while (i < seq_count && inner_tbl.scrollHeight - (inner_tbl.scrollTop + inner_tbl.offsetHeight) < 400) {
+    i = append_blocks_entries(tbody, i, 20);
+  }
+  inner_tbl.data_blocks_index = i;
+  if (i < seq_count) {
+    inner_tbl.addEventListener('scroll', make_blocks_entries, false);
+  }
+}
+
+function make_scan_popup(site, motif) {
+  return function (e) {
+    "use strict";
+    var pop, xy, padding, edge_padding, pop_left, pop_top, page_width;
+    var lflank, match, rflank, pspm;
+    if (!e) var e = window.event;
+    pop = make_scan_popup.pop;
+    if (e.type === "mouseover") {
+      if (pop) return;
+      pop = clone_template("tmpl_scan_info");
+      pspm = new Pspm(motif.pwm);
+      if (site.rc) pspm.reverse_complement(current_alphabet);
+      set_tvar(pop, "tvar_logo", make_small_logo(current_alphabet, pspm, {"className": "scan_logo"}));
+      set_tvar(pop, "tvar_motif", motif.id);
+      set_tvar(pop, "tvar_pvalue", site.pvalue.toExponential(2));
+      set_tvar(pop, "tvar_start", site.pos + 1);
+      set_tvar(pop, "tvar_end", site.pos + motif.len);
+
+      document.body.appendChild(pop);
+      position_popup(this, pop);
+      make_scan_popup.pop = pop;
+    } else if (e.type === "mouseout") {
+      if (pop) {
+        pop.parentNode.removeChild(pop);
+        make_scan_popup.pop = null;
+      }
+    }
+  };
+}
+
+function make_block_popup(site, motif, block) {
+  return function (e) {
+    "use strict";
+    var pop;
+    var lflank, match, rflank, pspm, ruler, match_seq, match_width;
+    if (!e) var e = window.event;
+    pop = make_block_popup.pop;
+    if (e.type === "mouseover") {
+      if (pop) return;
+      pop = clone_template("tmpl_block_info");
+      pspm = new Pspm(motif.pwm);
+      if (site.rc) { // must be dna
+        pspm.reverse_complement(current_alphabet);
+        lflank = current_alphabet.invcomp_seq(site.rflank);
+        match = current_alphabet.invcomp_seq(site.match);
+        rflank = current_alphabet.invcomp_seq(site.lflank);
+      } else {
+        lflank = site.lflank;
+        match = site.match;
+        rflank = site.rflank;
+      }
+      ruler = document.getElementById("measure_match");
+      match_seq = make_seq(current_alphabet, match);
+      ruler.innerHTML = "";
+      ruler.appendChild(match_seq);
+      match_width = ruler.clientWidth;
+      ruler.removeChild(match_seq);
+      set_tvar(pop, "tvar_lflank", lflank);
+      set_tvar(pop, "tvar_match", match_seq);
+      set_tvar(pop, "tvar_rflank", rflank);
+      set_tvar(pop, "tvar_logo_pad", lflank);
+      set_tvar(pop, "tvar_logo", make_small_logo(current_alphabet, pspm, {"width": match_width}));
+      set_tvar(pop, "tvar_motif", motif.id);
+      set_tvar(pop, "tvar_pvalue", site.pvalue.toExponential(2));
+      set_tvar(pop, "tvar_start", site.pos + 1);
+      set_tvar(pop, "tvar_end", site.pos + motif.len);
+
+      document.body.appendChild(pop);
+      position_popup(block, pop);
+      make_block_popup.pop = pop;
+    } else if (e.type === "mouseout") {
+      if (pop) {
+        pop.parentNode.removeChild(pop);
+        make_block_popup.pop = null;
+      }
+    }
+  };
+}
+
+//
+// action_show_more
+//
+// Show more information on the motif.
+///
+function action_show_more(e) {
+  var node, tr, tbody, table, container, motif, ordinal;
+  var expanded_motif;
+  if (!e) e = window.event;
+  if (e.type === "keydown") {
+    if (e.keyCode !== 13 && e.keyCode !== 32) {
+      return;
+    }
+    // stop a submit or something like that
+    e.preventDefault();
+  }
+  // find the row that contains the cell
+  node = this;
+  do {
+    if (node.tagName === "TR") break;
+  } while (node = node.parentNode);
+  if (!node) throw new Error("Expected to find row!?");
+  tr = node;
+  // get info
+  motif = tr.data_motif;
+  ordinal = tr.data_ordinal;
+  // find tbody
+  do {
+    if (node.tagName === "TBODY") break;
+  } while (node = node.parentNode);
+  if (!node) throw new Error("Expected to find tbody!?");
+  tbody = node;
+  // find table
+  do {
+    if (node.tagName === "TABLE") break;
+  } while (node = node.parentNode);
+  if (!node) throw new Error("Expected to find table!?");
+  table = node;
+  // find container
+  container = node.parentNode;
+  // make a expanded motif
+  motif["expanded"] = true;
+  expanded_motif = make_expanded_motif(current_alphabet, ordinal, motif, 
+      container.data_more_x, container.data_submit_x);
+  // now determine how to place it
+  if (tbody.rows.length === 1) {
+    // only us in the table so the table can be replaced
+    container.replaceChild(expanded_motif, table);
+  } else if (tbody.rows[0] === tr) {
+    // first row, so remove and insert an expanded motif before
+    table.deleteRow(tr.rowIndex);
+    container.insertBefore(expanded_motif, table);
+  } else if (tbody.rows[tbody.rows.length - 1] === tr) {
+    // last row, so remove and insert an expanded motif after
+    table.deleteRow(tr.rowIndex);
+    container.insertBefore(expanded_motif, table.nextSibling);
+  } else {
+    var table2, tbody2;
+    table2 = table.cloneNode(false);
+    table2.appendChild(table.tHead.cloneNode(true));
+    tbody2 = table.tBodies[0].cloneNode(false);
+    table2.appendChild(tbody2);
+    container.insertBefore(table2, table.nextSibling);
+    for (i = tbody.rows.length - 1; i >= 0; i--) {
+      row = tbody.rows[i];
+      row.parentNode.removeChild(row);
+      if (row === tr) {
+        break;
+      }
+      tbody2.insertBefore(row, tbody2.rows[0]);
+    }
+    container.insertBefore(expanded_motif, table2);
+  }
+  find_child(expanded_motif, "tvar_less").focus();
+}
+
+//
+// action_show_less
+//
+// Show less information on the motif.
+///
+function action_show_less(e) {
+  var btn;
+  var expanded_motif, container, motif, ordinal, colw, focus_target;
+  var table, tbody, tbody2, row, table_before, table_after;
+  if (!e) e = window.event;
+  if (e.type === "keydown") {
+    if (e.keyCode !== 13 && e.keyCode !== 32) {
+      return;
+    }
+    // stop a submit or something like that
+    e.preventDefault();
+  }
+  btn = this;
+  // find expanded motif
+  expanded_motif = find_parent(btn, "expanded_motif");
+  if (!expanded_motif) throw new Error("Expected expanded motif.");
+  // find the container
+  container = expanded_motif.parentNode;
+  // get data
+  motif = expanded_motif.data_motif;
+  ordinal = expanded_motif.data_ordinal;
+  colw = container.data_colw;
+  // get the table before
+  table_before = expanded_motif.previousSibling;
+  if (table_before && table_before.tagName !== "TABLE") {
+    table_before = null;
+  }
+  // get the table after
+  table_after = expanded_motif.nextSibling;
+  if (table_after && table_after.tagName !== "TABLE") {
+    table_after = null;
+  }
+  // see if there is a table below or above that we can put this in.
+  // if there is a table both below and above then add this motif and
+  // all ones below to the above table
+  motif["expanded"] = false;
+  if (table_before && table_after) {
+    tbody = table_before.tBodies[0];
+    row = tbody.insertRow(tbody.rows.length);
+    make_motif_table_entry(row, current_alphabet, ordinal, motif, colw);
+    focus_target = find_child(row.cells[5], "sym_btn");
+    container.removeChild(expanded_motif);
+    tbody2 = table_after.tBodies[0];
+    while (tbody2.rows.length > 0) {
+      row = tbody2.rows[0];
+      row.parentNode.removeChild(row);
+      tbody.appendChild(row);
+    }
+    container.removeChild(table_after);
+  } else if (table_before) {
+    tbody = table_before.tBodies[0];
+    row = tbody.insertRow(tbody.rows.length);
+    make_motif_table_entry(row, current_alphabet, ordinal, motif, colw);
+    focus_target = find_child(row.cells[5], "sym_btn");
+    container.removeChild(expanded_motif);
+  } else if (table_after) {
+    tbody = table_after.tBodies[0];
+    row = tbody.insertRow(0);
+    make_motif_table_entry(row, current_alphabet, ordinal, motif, colw);
+    focus_target = find_child(row.cells[5], "sym_btn");
+    container.removeChild(expanded_motif);
+  } else {
+    //no table above or below!
+    // make a new table
+    table = make_motifs_table(current_alphabet, ordinal, [motif], colw, data["stop_reason"]);
+    focus_target = find_child(table.tBodies[0].rows[0].cells[5], "sym_btn");
+    container.replaceChild(table, expanded_motif);
+  }
+  focus_target.focus();
+}
+
+//TODO -- can we delete this junk?
+//function action_show_outpop(e) {
+function fred_action_show_outpop(e) {
+  "use strict";
+  function init() {
+    "use strict";
+    var close_btn, next_btn, prev_btn, cancel_btn, do_btn;
+    var tab1, tab2, tab3;
+    var pnl1, pnl2, pnl3;
+    var format_list;
+    var tbl_submit, inputs, i, default_prog;
+    close_btn = $("outpop_close");
+    close_btn.addEventListener("click", action_hide_outpop, false);
+    close_btn.addEventListener("keydown", action_hide_outpop, false);
+    next_btn = $("outpop_next");
+    next_btn.addEventListener("click", action_outpop_next, false);
+    next_btn.addEventListener("keydown", action_outpop_next, false);
+    prev_btn = $("outpop_prev");
+    prev_btn.addEventListener("click", action_outpop_prev, false);
+    prev_btn.addEventListener("keydown", action_outpop_prev, false);
+    cancel_btn = $("outpop_cancel");
+    cancel_btn.addEventListener("click", action_hide_outpop, false);
+    do_btn = $("outpop_do");
+    do_btn.addEventListener("click", action_outpop_submit, false);
+    tab1 = $("outpop_tab_1");
+    tab1.tabIndex = 0;
+    tab1.addEventListener("click", action_outpop_tab, false);
+    tab1.addEventListener("keydown", action_outpop_tab, false);
+    tab2 = $("outpop_tab_2");
+    tab2.tabIndex = 0;
+    tab2.addEventListener("click", action_outpop_tab, false);
+    tab2.addEventListener("keydown", action_outpop_tab, false);
+    tab3 = $("outpop_tab_3");
+    tab3.tabIndex = 0;
+    tab3.addEventListener("click", action_outpop_tab, false);
+    tab3.addEventListener("keydown", action_outpop_tab, false);
+    pnl1 = $("outpop_pnl_1");
+    pnl2 = $("outpop_pnl_2");
+    pnl3 = $("outpop_pnl_3");
+    toggle_class(tab1, "activeTab", true);
+    toggle_class(tab2, "activeTab", false);
+    toggle_class(tab3, "activeTab", false);
+    pnl1.style.display = "block";
+    pnl2.style.display = "none";
+    pnl3.style.display = "none";
+    format_list = $("text_format");
+    format_list.addEventListener("change", action_outpop_format, false);
+    // setup program selection
+    tbl_submit = $("programs");
+    // when not dna, hide the inputs for programs that require dna motifs
+    toggle_class(tbl_submit, "alphabet_dna", current_alphabet.has_complement());//TODO alphabet_dna is a bad name for a field when allowing custom alphabets
+    // add a click listener for the radio buttons
+    inputs = tbl_submit.querySelectorAll("input[type='radio']");
+    for (i = 0; i < inputs.length; i++) {
+      inputs[i].addEventListener("click", action_outpop_program, false);
+    }
+    // ensure that a default program option is selected for DNA and Protein
+    default_prog = document.getElementById(current_alphabet.has_complement() ? "submit_tomtom" : "submit_fimo"); //TODO Tomtom might require a more strict definition of DNA
+    default_prog.checked = true;
+    action_outpop_program.call(default_prog);
+    // disable reverse-complement when not DNA
+    $("logo_rc_option").disabled = !current_alphabet.has_complement(); 
+    // set errorbars on when ssc is on
+    $("logo_ssc").addEventListener("change", action_outpop_ssc, false);
+  }
+  var node;
+  // store the focused element
+  action_hide_outpop.last_active = document.activeElement;
+  if (!e) e = window.event;
+  if (e.type === "keydown") {
+    if (e.keyCode !== 13 && e.keyCode !== 32) {
+      return;
+    }
+    // stop a submit or something like that
+    e.preventDefault();
+  }
+  // hide the help popup
+  help_popup();
+  // on first load initilize the popup
+  if (!action_show_outpop.ready) {
+    init();
+    action_show_outpop.ready = true;
+  }
+  // load the motif logo
+  node = this;
+  do {
+    if (/\bexpanded_motif\b/.test(node.className) || node.tagName === "TR") break;
+  } while (node = node.parentNode);
+  if (node === null) throw new Error("Expected node!");
+  update_outpop_motif(node.data_ordinal - 1);
+  // display the download popup
+  $("grey_out_page").style.display = "block";
+  $("download").style.display = "block";
+  $("outpop_close").focus();
+} // fred_action_show_outpop
+
+function action_btn_rc(e) {
+  "use strict";
+  var node, tr, motif, box, logo_box, tab_st, tab_rc, rc;
+  if (!e) e = window.event;
+  if (e.type === "keydown") {
+    if (e.keyCode !== 13 && e.keyCode !== 32) {
+      return;
+    }
+    // stop a submit or something like that
+    e.preventDefault();
+  }
+  node = this;
+  do {
+    if (node.tagName === "TR") break;
+  } while (node = node.parentNode);
+  if (!node) throw new Error("Expected to find row!?");
+  tr = node;
+  // get info
+  motif = tr.data_motif;
+  box = find_parent(this, "preview_box");
+  logo_box = find_child(box, "preview_logo_box");
+  tab_st = find_child(box, "plus");
+  tab_rc = find_child(box, "minus");
+  rc = (this === tab_rc);
+  motif["rc"] = rc;
+  toggle_class(logo_box, "show_rc_logo", rc);
+  toggle_class(tab_st, "active", !rc);
+  toggle_class(tab_rc, "active", rc);
+}
+
+function action_rc_tab(e) {
+  "use strict";
+  var box, logo_box, tab_st, tab_rc, rc;
+  if (!e) e = window.event;
+  if (e.type === "keydown") {
+    if (e.keyCode !== 13 && e.keyCode !== 32) {
+      return;
+    }
+    // stop a submit or something like that
+    e.preventDefault();
+  }
+  box = find_parent(this, "expanded_motif");
+  logo_box = find_child(box, "tvar_logo");
+  tab_st = find_child(box, "tvar_tab");
+  tab_rc = find_child(box, "tvar_tab_rc");
+  rc = (this === tab_rc);
+  box.data_motif["rc"] = rc;
+  toggle_class(logo_box, "show_rc_logo", rc);
+  toggle_class(tab_st, "activeTab", !rc);
+  toggle_class(tab_rc, "activeTab", rc);
+}
+
+function action_seqs_filter() {
+  "use strict";
+  var block_container;
+  block_container = $("blocks");
+  if ($("rdo_all_seqs").checked) {
+    toggle_class(block_container, "hide_empty_seqs", false);
+    toggle_class(block_container, "hide_only_scan", false);
+  } else if ($("rdo_sites_and_scan").checked) {
+    toggle_class(block_container, "hide_empty_seqs", true);
+    toggle_class(block_container, "hide_only_scan", false);
+  } else if ($("rdo_sites_only").checked) {
+    toggle_class(block_container, "hide_empty_seqs", true);
+    toggle_class(block_container, "hide_only_scan", true);
+  }
+}
+
+//
+// page_loaded
+//
+// Called when the page has loaded for the first time.
+///
+function page_loaded() {
+  post_load_setup();
+}
+
+//
+// page_loaded
+//
+// Called when a cached page is reshown.
+///
+function page_shown(e) {
+  if (e.persisted) post_load_setup();
+}
+
+//
+// page_loaded
+//
+// Called when the page is resized
+///
+function page_resized() {
+  var page, blocks_scroll;
+  update_scroll_pad();
+  page = (document.compatMode === "CSS1Compat") ? document.documentElement : document.body;
+  blocks_scroll = $("blocks_scroll");
+  if (blocks_scroll) {
+    blocks_scroll.style.maxHeight = Math.max(page.clientHeight - 300, 300) + "px";
+  }
+}
+
+//
+// pre_load_setup
+//
+// Run before the page is displayed
+///
+function pre_load_setup() {
+  var start, hue, sat, light, divisions;
+  var i, j, motifs, motif, sites, site, sequences, sequence;
+  var max_seq_len;
+  motifs = data["motifs"];
+  sequences = data["sequence_db"]["sequences"];
+  max_seq_len = 1;
+  if (sequences) {		// no sequences if -brief
+    for (i = 0; i < sequences.length; i++) {
+      sequence = sequences[i];
+      sequence["sites"] = [];
+      if (sequence["length"] > max_seq_len) {
+	max_seq_len = sequence["length"];
+      }
+   }
+  }
+  data["sequence_db"]["max_length"] = max_seq_len;
+  // use hsl colours
+  start = 0; //red
+  sat = 100;
+  light = 50;
+  for (i = 0; i < motifs.length; i++) {
+    motif = motifs[i];
+    // give the motif a colour
+    divisions = 1 << Math.ceil(Math.log(i + 1) / Math.LN2);
+    hue = start + (360 / divisions) * ((i - (divisions >> 1)) * 2 + 1);
+    motif["colour"] = "hsl(" + hue + ", " + sat + "%, " + light + "%)";
+    // associate sites with sequences as well 
+    // to make generating the block diagram easier
+    sites = motif["sites"];
+    for (j = 0; j < sites.length; j++) {
+      site = sites[j];
+      sequence = sequences[site["seq"]];
+      // record the motif index
+      site["motif"] = i;
+      // add the site to the sequence
+      sequence["sites"].push(site);
+    }
+  }
+}
+
+//
+// post_load_setup
+//
+// Run when the page has loaded, or been reloaded.
+//
+function post_load_setup() {
+  update_scroll_pad();
+  if (data["motifs"].length > 0) {
+    make_motifs();
+    if (data.sequence_db.primary_count > data.options.brief) {
+      if (data.options.brief == 1000) {
+        $("blocks").innerHTML = "<p>Output of sites suppressed because there were more than 1000 (primary) sequences.</p>";
+      } else {
+        $("blocks").innerHTML = "<p>Output of motif locations suppressed by -brief option.</p>";
+      }
+    } else {
+      make_blocks();
+    }
+  } else {
+    $("motifs").innerHTML = "<p>No significant motifs found!</p>"; // clear content
+    $("motifs").innerHTML += "<p><b>" + data["stop_reason"] + "</b></p>";
+    $("blocks").innerHTML = "<p>No significant motifs found!</p>";
+  }
+}
+
+pre_load_setup();
+</script>
+    <script>
+//
+// template.js
+//
+
+/*
+ * Fill in a template variable
+ */
+function set_tvar(template, tvar, value) {
+  var node;
+  node = find_child(template, tvar);
+  if (node === null) {
+    throw new Error("Template does not contain variable " + tvar);
+  }
+  node.innerHTML = "";
+  if (typeof value !== "object") {
+    node.appendChild(document.createTextNode(value));
+  } else {
+    node.appendChild(value);
+  }
+} // set_tvar
+
+/*
+ * Get the text contained within the element.
+ */
+function elem_text(elem, separator) {
+  if (separator === undefined) separator = '';
+  return text_nodes(elem).map(node_text).join(separator);
+}
+
+/*
+ * Get the text out of a specific text node.
+ */
+function node_text(node) {
+  if (node === undefined) {
+    return '';
+  } else if (node.textContent) {
+    return node.textContent;
+  } else if (node.innerText) {
+    return node.innerText;
+  } else {
+    return '';
+  }
+}
+
+/*
+ * Find all text nodes in the given container.
+ */
+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;
+}
+
+/*
+ * Create a button designed to contain a single symbol
+ */
+function make_sym_btn(symbol, title, action) {
+  var box, sbox;
+  box = document.createElement("div");
+  box.tabIndex = 0;
+  box.className = "sym_btn";
+  sbox = document.createElement("span");
+  if (typeof symbol === "string") {
+    sbox.appendChild(document.createTextNode(symbol));
+  } else {
+    sbox.appendChild(symbol);
+  }
+  box.appendChild(sbox);
+  box.title = title;
+  box.addEventListener('click', action, false);
+  box.addEventListener('keydown', action, false);
+  return box;
+}
+
+/*
+ * Create a pair of text spans with different classes.
+ * This is useful when using CSS to only display one of them.
+ */
+function text_pair(txt1, cls1, txt2, cls2) {
+  var container, part1, part2;
+  container = document.createElement("span");
+  part1 = document.createElement("span");
+  part1.appendChild(document.createTextNode(txt1));
+  part1.className = cls1;
+  container.appendChild(part1);
+  part2 = document.createElement("span");
+  part2.appendChild(document.createTextNode(txt2));
+  part2.className = cls2;
+  container.appendChild(part2);
+  return container;
+}
+</script>
+    <script>
+//
+// citation.js
+//
+function get_citation_text(doc_type, extra) {
+  var html;
+
+  switch (doc_type) {
+    case 'AMA':
+      return(get_citation_text("GOMo", extra));
+    case 'AME':
+      return(extra + `
+        <span class="citation">
+          Robert C. McLeay and Timothy L. Bailey,
+          &quot;Motif Enrichment Analysis: a unified framework and an evaluation on ChIP data&quot;,
+          <i>BMC Bioinformatics</i>, <b>11</b>:165, 2010.
+          <a href="http://www.biomedcentral.com/1471-2105/11/165">[full text]</a>
+        </span>
+      `);
+    case 'CentriMo':
+      return(extra + `
+        <span class="citation">
+          Timothy L. Bailey and Philip Machanick,
+          &quot;Inferring direct DNA binding from ChIP-seq&quot;,
+          <i>Nucleic Acids Research</i>, <b>40</b>:e128, 2012.
+          <a href="http://nar.oxfordjournals.org/content/40/17/e128">[Full Text]</a>
+        </span>
+      `);
+    case 'DREME':
+      return(extra + `
+        <span class="citation">
+          Timothy L. Bailey,
+          &quot;DREME: Motif discovery in transcription factor ChIP-seq data&quot;,
+          <i>Bioinformatics</i>, <b>27</b>(12):1653-1659, 2011.
+          <a href="http://bioinformatics.oxfordjournals.org/content/27/12/1653">[full text]</a>
+        </span>
+      `);
+    case 'FIMO':
+      return(extra + `
+        <span class="citation">
+          Charles E. Grant, Timothy L. Bailey and William Stafford Noble,
+          &quot;FIMO: Scanning for occurrences of a given motif&quot;,
+          <i>Bioinformatics</i> <b>27</b>(7):1017-1018, 2011.
+          <a href="http://bioinformatics.oxfordjournals.org/content/27/7/1017">[full text]</a>
+        </span>
+      `);
+    case 'GLAM2':
+    case 'GLAM2SCAN':
+      return(extra + `
+        <span class="citation">
+          Martin C. Frith, Neil F. W. Saunders, Bostjan Kobe and Timothy L. Bailey,
+          &quot;Discovering sequence motifs with arbitrary insertions and deletions&quot;,
+          <i>PLoS Computational Biology</i>, <b>4</b>(5):e1000071, 2008.
+          <a href="https://journals.plos.org/ploscompbiol/article?id=10.1371/journal.pcbi.1000071">[full text]</a>
+        </span>
+      `);
+    case 'GOMo':
+      return(extra + `
+        <span class="citation">
+          Fabian A. Buske, Mikael Bod&eacute;n, Denis C. Bauer and Timothy L. Bailey,
+          &quot;Assigning roles to DNA regulatory motifs using comparative genomics&quot;,
+          <i>Bioinformatics</i>, <b>26</b>(7), 860-866, 2010.
+          <a href="http://bioinformatics.oxfordjournals.org/cgi/content/full/26/7/860">[full text]</a>
+        </span>
+      `);
+    case 'MAST':
+      return(extra + `
+        <span class="citation">
+          Timothy L. Bailey and Michael Gribskov,
+          &quot;Combining evidence using p-values: application to sequence homology searches&quot;,
+          <i>Bioinformatics</i>, <b>14</b>(1):48-54, 1998.
+          <a href="http://bioinformatics.oxfordjournals.org/content/14/1/48">[full text]</a>
+        </span>
+      `);
+    case 'MCAST':
+      return(extra + `
+        <span class="citation">
+          Timothy Bailey and William Stafford Noble,
+          &quot;Searching for statistically significant regulatory modules&quot;,
+          <i>Bioinformatics (Proceedings of the European Conference on Computational Biology)</i>,
+          <b>19</b>(Suppl. 2):ii16-ii25, 2003.
+          <a href="http://bioinformatics.oxfordjournals.org/cgi/content/abstract/19/suppl_2/ii16">[full text]</a>
+        </span>
+      `);
+    case 'Meta-MEME':
+      return(extra + `
+        <span class="citation">
+	  William N. Grundy, Timothy L. Bailey, Charles P. Elkan and Michael E. Baker.
+	  &quot;Meta-MEME: Motif-based Hidden Markov Models of Protein Families&quot;
+	  <i>Computer Applications in the Biological Sciences (CABIOS)</i>,
+	  <b>13</b>(4):397-406, 1997.
+	  <a href="http://bioinformatics.oxfordjournals.org/content/13/4/397">[full text]</a>
+        </span>
+      `);
+    case 'MEME':
+      return(extra + `
+        <span class="citation">
+          Timothy L. Bailey and Charles Elkan,
+          &quot;Fitting a mixture model by expectation maximization to
+          discover motifs in biopolymers&quot;,
+          <em>Proceedings of the Second International Conference on Intelligent Systems
+          for Molecular Biology</em>, pp. 28-36, AAAI Press, Menlo Park, California, 1994.
+          <a href="http://www.aaai.org/Papers/ISMB/1994/ISMB94-004.pdf">[full text]</a>
+        </span>
+      `);
+    case 'MEME-ChIP':
+      return(extra + `
+        <span class="citation">
+          Philip Machanick and Timothy L. Bailey,
+          &quot;MEME-ChIP: motif analysis of large DNA datasets&quot;,
+          <i>Bioinformatics</i> <b>27</b>(12):1696-1697, 2011.
+        <a href="http://bioinformatics.oxfordjournals.org/content/27/12/1696.full">[full text]</a>
+        </span>
+      `);
+    case 'MEME_SUITE':
+      return(extra + `
+        <span class="citation">
+          Timothy L. Bailey, James Johnson, Charles E. Grant, William S. Noble,
+          &quot;The MEME Suite&quot;,
+          <i>Nucleic Acids Research</i>, <b>43</b>(W1):W39-W49, 2015.
+          <a href="https://academic.oup.com/nar/article/43/W1/W39/2467905">[full text]</a>
+        </span>
+      `);
+    case 'MoMo':
+      return(extra + `
+        <span class="citation">
+          Alice Cheng, Charles Grant, Timothy L. Bailey and William Noble,
+          &quot;MoMo: Discovery of statistically significant post-translational modification motifs&quot;, 
+          <i>Bioinformatics</i>, <b>35</b>(16):2774-2782, 2018.
+          <a href="https://doi.org/10.1093/bioinformatics/bty1058">[full text]</a>
+        </span>
+      `);
+    case 'PSPs':
+      return(extra + `
+        <span class="citation">
+          Timothy L. Bailey, Mikael Bod&eacute;n, Tom Whitington and Philip Machanick,
+          &quot;The value of position-specific priors in motif discovery using MEME&quot;,
+          <i>BMC Bioinformatics</i>, <b>11</b>(1):179, 2010.
+          <a href="http://www.biomedcentral.com/1471-2105/11/179">[full text]</a>
+        </span>
+      `);
+    case 'SEA':
+      return(extra + `
+        <span class="citation">
+          Timothy L. Bailey and Charles E. Grant, &quot;SEA: Simple Enrichment Analysis of motifs&quot;,
+          <i>BioRxiv</i>, August 24, 2021.
+          <a href="https://www.biorxiv.org/content/10.1101/2021.08.23.457422v1">[full text]</a>
+        </span>
+      `);
+    case 'SpaMo':
+      return(extra + `
+        <span class="citation">
+          Tom Whitington, Martin C. Frith, James Johnson and Timothy L. Bailey
+          &quot;Inferring transcription factor complexes from ChIP-seq data&quot;,
+          <i>Nucleic Acids Res.</i> <b>39</b>(15):e98, 2011.
+          <a href="http://nar.oxfordjournals.org/content/39/15/e98">[full text]</a>
+        </span>
+      `);
+    case 'STREME':
+      return(extra + `
+        <span class="citation">
+          Timothy L. Bailey,
+          &quot;STREME: accurate and versatile sequence motif discovery&quot;,
+          <i>Bioinformatics</i>, Mar. 24, 2021.
+          <a href="https://academic.oup.com/bioinformatics/advance-article-abstract/doi/10.1093/bioinformatics/btab203/6184861" >[full text]</a>
+        </span>
+      `);
+    case 'Tomtom':
+      return(extra + `
+        <span class="citation">
+          Shobhit Gupta, JA Stamatoyannopolous, Timothy Bailey and William Stafford Noble,
+          &quot;Quantifying similarity between motifs&quot;,
+          <i>Genome Biology</i>, <b>8</b>(2):R24, 2007.
+          <a href="http://genomebiology.com/2007/8/2/R24">[full text]</a>
+        </span>
+      `);
+    case 'T-Gene':
+      return(extra + `
+        <span class="citation">
+          Timothy O'Connor, Charles E. Grant, Mikael Bod&eacute;n, Timothy L. Bailey,
+          &quot;T-Gene: Improved target gene prediction&quot;,
+            <i>Bioinformatics</i>, <b>36</b>(12):3902-3904, 2020.
+          <a href="https://academic.oup.com/bioinformatics/article/36/12/3902/5815978?guestAccessKey=aa625a49-a2aa-4d7a-858e-8bc82867a534">[Full Text]</a>
+        </span>
+      `);
+    case 'XSTREME':
+      return(extra + `
+        <span class="citation">
+          Charles E. Grant and Timothy L. Bailey, &quot;XSTREME: comprehensive motif analysis of biological sequence datasets&quot;,
+          <i>BioRxiv</i>, September 3, 2021.
+          <a href="https://www.biorxiv.org/content/10.1101/2021.09.02.458722v1">[full text]</a>
+        </span>
+      `);
+    default:
+      return("Unknown program: " + doc_type);
+  }
+} // get_citation_text
+
+//
+// Function to replace the innerHTML of element "id" with an HTML paragraph
+// containing the text for 'program', which is known to function get_citation_text.
+// If "id" is either "citation" or "reference" some extra text is printed.
+//
+function print_citation(id, program) {
+  var extra;
+  switch (id) {
+    case 'citation':
+      extra = "If you use " + program + " in your research, please cite the following paper:<br>";
+      break;
+    case 'reference':
+      extra = "<h5>Reference</h5>";
+      break;
+    default:
+      extra = "";
+      break;
+  };
+  var html = get_citation_text(program, extra);
+  document.getElementById(id).insertAdjacentHTML('beforeend', html);
+} // print_citation
+
+// 
+// Function to convert a citation for a program to a C #define statement.
+//
+function print_citation_define(lang, pgm) {
+  var citation = get_citation_text(pgm, '');
+  citation = citation.replace(/<[^>]*>/g, '');
+  citation = citation.replace(/\[.*\]/g, '');
+  citation = citation.replace(/\n\s*/g, '\\n');
+  citation = citation.replace(/&quot;/g, '\\"');
+  citation = citation.replace(/&eacute;/g, 'e');
+  citation = citation.replace(/^\\n/, '');
+  pgm = pgm.replace(/-/, '');
+  citation = "If you use this program in your research, please cite:\\n\\n" + citation;
+  if (lang == "C") {
+    citation = "#define " + pgm + '_CITE "' + citation + '"';
+  } else if (lang == "perl") {
+    citation = '"' + pgm + '" => "' + citation + '",';
+  }
+  return(citation);
+} // print_citation_define
+
+//
+// Main program (for use with nodejs "node" javascript engine)
+// to create citation.js.h and citation.pm from citation.js.
+// The command line:
+//   node citation.js C > citation.js.h
+// will output the C #define statements for each of the
+// programs listed below, defining macros <program>_CITE.
+// The command line:
+//   node citation.js perl > citation.js.pm
+// will output perl hash <program> => text
+//
+//
+if (typeof process !== 'undefined') {
+  var lang = process.argv[2];
+  var programs = ['AMA', 'AME', 'CentriMo', 'DREME', 'FIMO', 'GLAM2', 
+    'GLAM2SCAN', 'GOMo', 'MAST', 'MCAST', 'Meta-MEME', 'MEME',
+    'MEME-ChIP', 'MEME_SUITE', 'MoMo', 'PSPs', 'SEA', 'SpaMo',
+    'STREME', 'Tomtom', 'T-Gene', 'XSTREME'];
+
+  if (lang == "C") {
+    console.log("// Do not edit this file.  It is created from etc/citation.js.");
+    console.log("#ifndef citation_js_h\n#define citation_js_h\n");
+    for (var i=0; i<programs.length; i++) {
+      console.log(print_citation_define(lang, programs[i]));
+    }
+    console.log("\n#endif");
+  } else if (lang == "perl") {
+    console.log("# Do not edit this file.  It is created from etc/citation.js.");
+    console.log("package Citation;");
+    console.log("sub cite {\n  my ($pgm) = @_;\n  return $citation{$pgm};\n}");
+    console.log("%citation = (");
+    for (var i=0; i<programs.length; i++) {
+      console.log(print_citation_define(lang, programs[i]));
+    }
+    console.log(");");
+  }
+}
+</script>
+    <style>
+/* 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(data:image/gif;base64,R0lGODlhDAANAIABANR0AP///yH5BAEAAAEALAAAAAAMAA0AAAIdhI8Xy22MIFgv1DttrrJ7mlGNNo4c+aFg6SQuUAAAOw==);
+}
+
+div.help:hover {
+  background-image: url(data:image/gif;base64,R0lGODlhDAANAKEAANR0AP///9R0ANR0ACH+EUNyZWF0ZWQgd2l0aCBHSU1QACH5BAEAAAIALAAAAAAMAA0AAAIdDGynCe3PgoxONntvwqz2/z2K2ImjR0KhmSIZUgAAOw==);
+}
+
+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; overflow: hidden;}
+
+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;}
+
+.explain h5 {font-size:1em; margin-left: 1em;}
+
+div.doc {margin-left: 2em; margin-bottom: 3em;}
+
+th.trainingset {
+  border-bottom: thin dashed black; 
+  font-weight:normal; 
+  padding:0px 10px;
+}
+div.pop_content {
+  position:absolute;
+  z-index:50;
+  width:300px;
+  padding: 5px;
+  background: #E4ECEC;
+  font-size: 12px;
+  font-family: Arial;
+  border-style: double;
+  border-width: 3px;
+  border-color: #AA2244;
+  display:none;
+}
+div.pop_content_wide {
+  position:absolute;
+  z-index:1;
+  width:700px;
+  padding: 5px;
+  background: #E4ECEC;
+  font-size: 12px;
+  font-family: Arial;
+  border-style: double;
+  border-width: 3px;
+  border-color: #AA2244;
+  display:none;
+}
+
+div.pop_content > *:first-child {
+  margin-top: 0px;
+}
+
+div.pop_content h1, div.pop_content h2, div.pop_content h3, div.pop_content h4, 
+div.pop_content h5, div.pop_content h6, div.pop_content p {
+  margin: 0px;
+}
+
+div.pop_content p + h1, div.pop_content p + h2, div.pop_content p + h3, 
+div.pop_content p + h4, div.pop_content p + h5, div.pop_content p + h6 {
+  margin-top: 5px;
+}
+
+div.pop_content p + p {
+  margin-top: 5px;
+}
+
+div.pop_content > *:last-child {
+  margin-bottom: 0px;
+}
+
+div.pop_content div.pop_close {
+  /* old definition */
+  float:right;
+  bottom: 0;
+}
+
+div.pop_content span.pop_close, div.pop_content span.pop_back {
+  display: inline-block;
+  border: 2px outset #661429;
+  background-color: #CCC;
+  padding-left: 1px;
+  padding-right: 1px;
+  padding-top: 0px;
+  padding-bottom: 0px;
+  cursor: pointer;
+  color: #AA2244; /*#661429;*/
+  font-weight: bold;
+}
+
+div.pop_content span.pop_close:active, div.pop_content span.pop_back:active {
+  border-style: inset;
+}
+
+div.pop_content span.pop_close {
+  float:right;
+  /*border: 2px outset #AA002B;*/
+  /*color: #AA2244;*/
+}
+
+div.pop_content:not(.nested) .nested_only {
+  display: none;
+}
+
+div.pop_back_sec {
+  margin-bottom: 5px;
+}
+
+div.pop_close_sec {
+  margin-top: 5px;
+}
+
+table.hide_advanced tr.advanced {
+  display: none;
+}
+span.show_more {
+  display: none;
+}
+table.hide_advanced span.show_more {
+  display: inline;
+}
+table.hide_advanced span.show_less {
+  display: none;
+}
+
+
+/*****************************************************************************
+ * Program logo styling
+ ****************************************************************************/
+div.prog_logo {
+  border-bottom: 0.25em solid #0f5f60;
+  height: 4.5em;
+  width: 25em;
+  display:inline-block;
+}
+div.prog_logo img {
+  float:left;
+  width: 4em;
+  border-style: none;
+  margin-right: 0.2em;
+}
+div.prog_logo h1, div.prog_logo h1:hover, div.prog_logo h1:active, div.prog_logo h1:visited {
+  margin:0;
+  padding:0;
+  font-family: Arial, Helvetica,  sans-serif;
+  font-size: 3.2em;
+  line-height: 1em;
+  vertical-align: top;
+  display: block;
+  color: #026666;
+  letter-spacing: -0.06em;
+  text-shadow: 0.04em 0.06em 0.05em #666;
+}
+div.prog_logo h2, div.prog_logo h2:hover, div.prog_logo h2:active, div.prog_logo h2:visited {
+  display: block;
+  margin:0;
+  padding:0;
+  font-family: Helvetica, sans-serif;
+  font-size: 0.9em;
+  line-height: 1em;
+  letter-spacing: -0.06em;
+  color: black;
+}
+div.prog_logo h3, div.prog_logo h3:hover, div.prog_logo h3:active, div.prog_logo h3:visited {
+  display: block;
+  margin:0;
+  padding:0;
+  font-family: Helvetica, sans-serif;
+  font-size: 0.9em;
+  line-height: 1.5em;
+  letter-spacing: -0.06em;
+  color: black;
+}
+
+div.big.prog_logo {
+  font-size: 18px;
+}
+
+/* These are for centered columns in tables */
+td.ctr {
+  text-align: center;
+}
+
+/* These are for the navigation bars at the top of outputs. */
+table.navigation {
+  margin-top: 0px;
+  border-collapse:collapse;
+}
+table.navigation * td
+{
+  padding-left: 0px;
+  padding-right: 10px;
+  padding-top: 0px;
+  padding-bottom: 0px;
+}
+</style>
+    <style>
+.block_td {
+  height:25px;
+}
+.block_container {
+  position:relative;
+  box-sizing: border-box;
+  height: 25px;
+  padding: 0px;
+  margin: 0px;
+  margin-left: 1em;
+}
+.block_label {
+  position: absolute; 
+  display: inline-block;
+  padding: 3px;
+  z-index: 4;
+  top: 6px;
+  height: 12px;
+  line-height: 12px;
+  font-size: 12px;
+  background-color: white;
+  border: 1px solid black;
+  -moz-border-radius: 12px;
+  -webkit-border-radius: 12px;
+  border-radius: 12px;
+  transform: translateX(-50%);
+}
+.block_motif {
+  position: absolute; 
+  z-index: 3;
+  top: 0px;
+  box-sizing: border-box;
+  border: 1px solid black;
+  height: 12px;
+  background-color: cyan;
+}
+.block_motif.top {
+  border-bottom-width: 0;
+}
+.block_motif.bottom {
+  border-top-width: 0;
+}
+.block_motif.scanned_site {
+  opacity: 0.3;
+}
+.block_motif.scanned_site.active {
+  opacity: 0.9;
+}
+.block_region {
+  position:absolute; 
+  z-index:6; 
+  height:25px; 
+  top:0px; 
+}
+.block_region.main {
+  z-index:8;
+}
+.block_region.scanned_site {
+  z-index:5;
+}
+.block_region.scanned_site.main {
+  z-index:7;
+}
+.block_region.top {
+  height:13px;
+}
+.block_region.bottom {
+  height:13px;
+  top:12px;
+}
+.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;
+  line-height:12px;
+  top:0px;
+  left:-1em;
+}
+.block_minus_sym {
+  position:absolute;
+  z-index:4;
+  line-height:12px;
+  top:13px;
+  left:-1em;
+}
+
+.tic_major {
+  position:absolute;
+  top:0em;
+  height:0.5em;
+  width: 2px;
+  margin-left: -1px;
+  background-color: blue;
+}
+.tic_minor {
+  position:absolute;
+  top:0em;
+  height:0.2em;
+  width: 1px;
+  margin-left: -0.5px;
+  background-color: blue;
+}
+.tic_label {
+  position:absolute;
+  display: inline-block;
+  top:0.5em;
+  height: 1em;
+  color: blue;
+  transform: translateX(-50%);
+}
+
+.block_needle {
+  position:absolute;
+  z-index:4;
+  height:30px; 
+  width:1px; 
+  top:-2px; 
+  background-color:gray;
+}
+.block_needle.right {
+  height: 60px;
+}
+.block_handle {
+  position: absolute; 
+  display: inline-block;
+  z-index: 5; 
+  top: 27px; 
+  min-width: 3ex;
+  text-align: center;
+  font-size: 12px;
+  line-height: 12px;
+  transform: translateX(-50%);
+  background-color: LightGrey; 
+  border:3px outset grey;
+  cursor: pointer;
+  -webkit-user-select: none; /* Chrome/Safari */        
+  -moz-user-select: none; /* Firefox */
+  -ms-user-select: none; /* IE10+ */
+  /* Rules below not implemented in browsers yet */
+  -o-user-select: none;
+  user-select: none;
+}
+.block_handle.right {
+  top: 47px;
+}
+
+.legend_container {
+  text-align: right;
+}
+.legend_entry {
+  display: inline-block;
+  padding: 5px;
+}
+div.legend_swatch {
+  box-sizing: border-box;
+  width: 15px;
+  height: 15px;
+  border: 1px solid black;
+  background-color: cyan;
+  float: left;
+}
+div.legend_swatch input {
+  display: none;
+}
+.legend_text {
+  line-height: 15px;
+  margin-left: 20px;
+}
+</style>
+    <style>
+/* meme output specific css */
+
+div.pop_block {
+  position:absolute;
+  z-index:5;
+  padding: 5px;
+  border: 1px solid black;
+  display: inline-block;
+  background-color: white;
+}
+
+#measure_match {
+  position: absolute;
+  visibility: hidden;
+  height: auto;
+  width: auto;
+  white-space: nowrap;
+}
+
+div.template {
+  position: absolute;
+  z-index: 1;
+  left: 0;
+  top: 0;
+  visibility: hidden;
+}
+
+table.block_information {
+  margin-left: auto;
+  margin-right: auto;
+}
+
+table.block_information * th {
+  text-align: right;
+}
+
+*.hide_empty_seqs * tr.empty_seq {
+  display: none;
+}
+
+*.hide_only_scan * tr.only_scan {
+  display: none;
+}
+
+*.hide_only_scan * div.scanned_site {
+  display: none;
+}
+
+td.symaction {
+  text-align: center;
+  text-decoration: underline;
+  font-size: 20px;
+  cursor: pointer;
+}
+div.sym_btn {
+  display:inline-block;
+  text-decoration: underline;
+  cursor: pointer;
+  font-size: 20px;
+  line-height:20px; 
+  text-align: center;
+  width: 20px;
+  height: 20px;
+  color: blue;
+}
+div.sym_btn:hover {
+  color: white;
+  background-color: blue;
+}
+
+div.sym_btn.positioned {
+  position: absolute;
+  top: 0px;
+}
+
+div.actionbutton { 
+  display:inline-block;
+  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.param_box {
+  display: inline-block;
+  margin-right: 20px;
+}
+
+span.param {
+  font-weight: bold;
+}
+
+div.box + div.box {
+  margin-top: 5px;
+}
+
+div.sites_outer {
+  position: relative;
+  padding-top: 20px; /* height of header */
+  display: inline-block;
+}
+
+div.sites_inner {
+  overflow-x: hidden;
+  overflow-y: auto;
+  max-height: 200px;
+}
+table.sites_tbl {
+  border-collapse: collapse;
+}
+
+div.sites_th_inner {
+  position: absolute;
+  top: 0;
+  line-height: 20px; /* height of header */
+  text-align: left;
+  padding-left: 5px;
+}
+th.nopad div.sites_th_inner {
+  padding-left: 0;
+}
+div.sites_th_hidden {
+  visibility: hidden;
+  height: 0;
+  padding: 0 10px;
+}
+th.nopad div.sites_th_hidden {
+  padding: 0;
+}
+div.sites_inner * th {
+  height: 0;
+}
+
+table.sites_tbl {
+  overflow-x: hidden;
+  overflow-y: auto;
+}
+
+.site_num {
+  text-align: right;
+}
+.site_name {
+  padding:0px 5px; 
+  text-align:left;
+}
+.site_strand {
+  padding:0px 5px; 
+  text-align:center;
+}
+.norc .site_strand, .norc .site_strand_title {
+  display: none;
+}
+.site_start {
+  padding:0px 15px; 
+  text-align: right;
+}
+.site_pvalue {
+  text-align:center; 
+  padding:0px 15px; 
+  text-align:right;
+  white-space: nowrap;
+}
+.lflank, .rflank, .match, .alpha_symbol {
+  font-weight:bold; 
+  font-size:15px; 
+  font-family: 'Courier New', Courier, monospace;
+  color:gray; 
+}
+
+.site.lflank {
+  text-align:right; 
+  padding-right:5px; 
+  color:gray;
+}
+.site.match {
+  text-align:center; 
+}
+.site.rflank {
+  text-align:left; 
+  padding-left:5px; 
+  padding-right: 20px;
+}
+
+th.stop_reason {
+  text-align: left;
+  padding-right: 10px;
+}
+
+th.motif_ordinal {
+
+}
+td.motif_ordinal {
+  text-align: right;
+  padding-right: 10px;
+}
+th.motif_logo {
+  padding-right: 10px;
+}
+td.motif_logo {
+  padding-right: 10px;
+}
+th.motif_evalue {
+  text-align:right;
+  padding-right: 10px;
+}
+td.motif_evalue {
+  text-align: right;
+  white-space: nowrap;
+  padding-right: 20px;
+}
+th.motif_nsites {
+  text-align: right;
+  padding-right: 10px;
+}
+td.motif_nsites {
+  text-align: right;
+  padding-right: 20px;
+}
+th.motif_width {
+  text-align: right;
+  padding-right: 5px;
+}
+td.motif_width {
+  text-align: right;
+  padding-right: 15px;
+}
+th.motif_more {
+  padding: 0 5px;
+}
+td.motif_more {
+  text-align: center;
+  padding: 0 5px;
+}
+th.motif_submit {
+  padding: 0 5px;
+}
+td.motif_submit {
+  text-align: center;
+  padding: 0 5px;
+}
+th.motif_download {
+  padding-left: 5px;
+}
+td.motif_download {
+  text-align: center;
+  padding-left: 5px;
+}
+
+
+div.tabArea {
+  font-size: 80%;
+  font-weight: bold;
+}
+
+.norc div.tabArea {
+  display: none;
+}
+
+span.tab, span.tab:visited {
+  cursor: pointer;
+  color: #888;
+  background-color: #ddd;
+  border: 2px solid #ccc;
+  padding: 2px 1em;
+  text-decoration: none;
+}
+span.tab.middle {
+  border-left-width: 0px;
+}
+div.tabArea.base span.tab {
+  border-top-width: 0px;
+}
+div.tabArea.top span.tab {
+  border-bottom-width: 0px;
+}
+
+span.tab:hover {
+  background-color: #bbb;
+  border-color: #bbb;
+  color: #666;
+}
+span.tab.activeTab, span.tab.activeTab:hover, span.tab.activeTab:visited {
+  background-color: white;
+  color: black;
+  cursor: default;
+}
+div.tabMain {
+  border: 2px solid #ccc;
+  background-color: white;
+  padding: 10px;
+}
+div.tabMain.base {
+  margin-top: 5px;
+  display: inline-block;
+  max-width: 98%;
+}
+
+div.tabMain.top {
+  margin-bottom: 5px;
+}
+
+div.tabCenter {
+  max-width: 100%;
+  overflow-x: auto;
+  height: 200px;
+  overflow-y: hidden;
+}
+
+canvas.logo_rc {
+  display:none;
+}
+.show_rc_logo > canvas {
+  display: none;
+}
+.show_rc_logo > canvas.logo_rc {
+  display: block;
+}
+
+canvas.scan_logo {
+  margin-left: 10px;
+}
+
+div.blocks_outer {
+  position: relative;
+  padding-top: 20px; /* height of header */
+}
+
+div.blocks_inner {
+  overflow-x: hidden;
+  overflow-y: auto;
+  max-height: 200px;
+}
+table.blocks_tbl {
+  border-collapse: collapse;
+  width: 100%;
+}
+
+table.blocks_tbl .blockdiag_name {
+  white-space: nowrap
+}
+
+div.blocks_th_inner {
+  position: absolute;
+  top: 0;
+  line-height: 20px; /* height of header */
+  text-align: left;
+  padding-left: 5px;
+}
+th.nopad div.blocks_th_inner {
+  padding-left: 0;
+}
+div.blocks_th_hidden {
+  visibility: hidden;
+  height: 0;
+  padding: 0 10px;
+}
+th.nopad div.blocks_th_hidden {
+  padding: 0;
+}
+div.blocks_inner * th {
+  height: 0;
+}
+
+table.blocks_tbl {
+  overflow-x: hidden;
+  overflow-y: auto;
+}
+td.block_td {
+  width: 99%;
+}
+
+*.blockdiag_num {
+  text-align: right;
+}
+
+td.blockdiag_name {
+  text-align: left;
+  padding:0px 10px; 
+}
+
+td.blockdiag_pvalue {
+  padding:0px 10px; 
+  text-align:right;
+  white-space: nowrap;
+}
+
+div.preview_btn {
+  border: 2px solid white;
+  height: 16px;
+  width: 16px;
+  font-size: 12px;
+  line-height: 16px;
+  text-align: center;
+  cursor: pointer;
+}
+div.preview_btn + div.preview_btn {
+  margin-top: 3px;
+}
+
+div.preview_btn.active {
+  border: 2px solid black;
+  cursor: default;
+}
+
+div.preview_btn:hover {
+  background-color: black;
+  color: white;
+  border-color: black;
+}
+
+div.preview_btn.active:hover {
+  background-color: white;
+  color: black;
+  border-color: black;
+}
+
+
+div.preview_btn_box {
+  position: absolute;
+  left: 0px;
+  top: 0px;
+  padding: 3px;
+}
+
+div.preview_logo_box {
+  height: 50px;
+  overflow-y: hidden;
+}
+
+div.preview_btn_box + div.preview_logo_box {
+  margin-left: 25px;
+}
+
+div.preview_box {
+  position: relative;
+}
+
+div.grey_background {
+  position:fixed; 
+  z-index: 8;
+  background-color: #000;
+  -ms-filter: "progid:DXImageTransform.Microsoft.Alpha(Opacity=50)";
+  opacity: 0.5;
+  left: 0;
+  top: 0;
+  width: 100%;
+  height: 100%;
+}
+
+div.popup_wrapper {
+  position:fixed; 
+  z-index:9;
+  width:100%; 
+  height:0; 
+  top:50%; 
+  left:0;
+}
+
+div.popup {
+  width: 600px; 
+  z-index:9;
+  margin-left: auto;
+  margin-right: auto;
+  padding: 5px;
+  background-color: #FFF;
+  border-style: double;
+  border-width: 5px;
+  border-color: #00666a;
+  position:relative; 
+}
+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;
+}
+
+div.navarrow {
+  font-size: 30px;
+  text-decoration:none;
+  cursor: pointer;
+  -moz-user-select: none;  
+  -webkit-user-select: none;  
+  -ms-user-select: none;
+}
+
+div.navarrow > span.inactive {
+  display: inline;
+}
+div.navarrow > span.active {
+  display: none;
+}
+
+div.navarrow:hover > span.active {
+  display: inline;
+}
+div.navarrow:hover > span.inactive {
+  display: none;
+}
+
+table.programs {
+  width: 100%;
+}
+
+table.programs tr {
+  background-color: #EFE;
+}
+
+table.programs tr.selected {
+  background-color: #262;
+  color: #FFF;
+}
+
+table.programs tr.dna_only {
+  display: none;
+}
+
+table.programs.alphabet_dna tr.dna_only {
+  display: table-row;
+}
+
+div.programs_scroll {
+  width: 100%; 
+  height: 90px; 
+  overflow-y: auto; 
+  overflow-x: hidden;
+  margin: 0 auto; 
+}
+table.inputs, table.alpha_bg_table {
+  margin-top: 20px;
+  border-collapse:collapse;
+}
+table.inputs * td, table.inputs * th, table.alpha_bg_table * td, table.alpha_bg_table * th {
+  padding-left: 15px;
+  padding-right: 15px;
+  padding-top: 1px;
+  padding-bottom: 1px;
+}
+
+table.hide_psp td.col_psp, table.hide_psp th.col_psp {
+  display: none;
+}
+
+table.hide_control td.col_control, table.hide_control th.col_control {
+  display: none;
+}
+
+/* program settings */
+span.mod_oops, span.mod_zoops, span.mod_anr {
+  display: none;
+}
+td.oops span.mod_oops,td.zoops span.mod_zoops, td.anr span.mod_anr  {
+  display: inline;
+}
+span.strand_none, span.strand_given, span.strand_both {
+  display: none;
+}
+td.none span.strand_none, td.given span.strand_given, td.both span.strand_both {
+  display: inline;
+}
+span.spmap_uni, span.spmap_pam {
+  display: none;
+}
+td.uni span.spmap_uni, td.pam span.spmap_pam {
+  display: inline;
+}
+span.prior_dirichlet, span.prior_dmix, span.prior_mega, span.prior_megap, span.prior_addone {
+  display: none;
+}
+td.dirichlet span.prior_dirichlet, td.dmix span.prior_dmix, td.mega span.prior_mega,
+td.megap span.prior_megap, td.addone span.prior_addone {
+  display: inline;
+}
+span.noendgaps_on, span.noendgaps_off {
+  display: none;
+}
+td.on span.noendgaps_on, td.off span.noendgaps_off {
+  display: inline;
+}
+span.substring_on, span.substring_off {
+  display: none;
+}
+td.on span.substring_on, td.off span.substring_off {
+  display: inline;
+}
+</style>
+  </head>
+  <body onload="page_loaded()" onpageshow="page_shown(event)" onresize="page_resized()">
+    <!--  -->
+    <div id="grey_out_page" class="grey_background" style="display:none;">
+    </div>
+    <!-- Help popups -->
+    <div class="pop_content" id="pop_results_txt">
+      <p>MEME results in plain text format.</p>
+      <div style="float:right; bottom:0px;">[
+        <a href="javascript:help_popup()">close</a> ]</div>
+    </div>
+    <div class="pop_content" id="pop_results_xml">
+      <p>MEME results in XML format.</p>
+      <div style="float:right; bottom:0px;">[
+        <a href="javascript:help_popup()">close</a> ]</div>
+    </div>
+    <div class="pop_content" id="pop_">
+      <p>Help poup.</p>
+      <div style="float:right; bottom:0px;">[ 
+        <a href="javascript:help_popup()">close</a> ]</div>
+    </div>
+    <div class="pop_content" id="pop_logo">
+      <script>print_doc_para("pop_logo", "discovery", "motif_logo", site_url);</script>
+      Click on the "+" or "-" buttons to the left of the motif to see
+      the forward or reverse complement of the motif if available.
+      <div class="pop_close">[<a href="javascript:help_popup()">close</a> ]</div>
+    </div>
+    <div class="pop_content" id="pop_ev">
+      <p>The statistical significance of the motif. MEME usually finds the most
+      statistically significant (low E-value) motifs first. It is unusual to
+      consider a motif with an E-value larger than 0.05 significant so, as an
+      additional indicator, MEME displays these greyed out.</p> 
+      <p>The E-value of a motif is based on its log likelihood ratio, width,
+      sites, the background letter frequencies (given in the command line
+      summary), and the size of the training set.</p>
+      <p>The E-value is an estimate of the expected number of motifs with the
+      given log likelihood ratio (or higher), and with the same width and site
+      count, that one would find in a similarly sized set of random
+      sequences (sequences where each position is independent and letters are
+      chosen according to the background letter frequencies).</p>
+      <div style="float:right; bottom:0px;">[ 
+        <a href="javascript:help_popup()">close</a> ]</div>
+    </div>
+    <div class="pop_content" id="pop_sites">
+      <p>The number of sites contributing to the construction of the motif.</p>
+      <div style="float:right; bottom:0px;">[ 
+        <a href="javascript:help_popup()">close</a> ]</div>
+    </div>
+    <div class="pop_content" id="pop_width">
+      <p>The width of the motif. Each motif describes a pattern of a fixed
+      width, as no gaps are allowed in MEME motifs.</p>
+      <div style="float:right; bottom:0px;">[ 
+        <a href="javascript:help_popup()">close</a> ]</div>
+    </div>
+    <div class="pop_content" id="pop_more">
+      <script>print_doc_para("pop_more", "discovery", "more");</script>
+      <div class="pop_close">[<a href="javascript:help_popup()">close</a> ]</div>
+    </div>
+    <div class="pop_content" id="pop_submit_dl">
+      <script>print_doc_para("pop_submit_dl", "discovery", "submit_dl", "https://meme-suite.org/meme");</script>
+      <div style="float:right; bottom:0px;">[ 
+        <a href="javascript:help_popup()">close</a> ]</div>
+    </div>
+    <div class="pop_content" id="pop_llr">
+      <p>The log likelihood ratio of the motif. The log likelihood ratio is the 
+      logarithm of the ratio of the probability of the occurrences of the motif
+      given the motif model (likelihood given the motif) versus their
+      probability given the background model (likelihood given the null model).
+      (Normally the background model is a 0-order Markov model using the
+      background letter frequencies, but higher order Markov models may be
+      specified via the -bfile option to MEME.).</p>
+      <div style="float:right; bottom:0px;">[ 
+        <a href="javascript:help_popup()">close</a> ]</div>
+    </div>
+    <div class="pop_content" id="pop_ic">
+      <p>The information content of the motif in bits. It is equal to the sum
+      of the uncorrected information content, R(), in the columns of the motif.
+      This is equal relative entropy of the motif relative to a uniform
+      background frequency model.</p>
+      <div style="float:right; bottom:0px;">[ 
+        <a href="javascript:help_popup()">close</a> ]</div>
+    </div>
+    <div class="pop_content" id="pop_re">
+      <p>The relative entropy of the motif.</p>
+
+      <p style="font-family: monospace;">re = llr / (sites * ln(2))</p>
+      <div style="float:right; bottom:0px;">[ 
+        <a href="javascript:help_popup()">close</a> ]</div>
+    </div>
+    <div class="pop_content" id="pop_bt">
+      <p>The Bayes Threshold.</p>
+      <div style="float:right; bottom:0px;">[ 
+        <a href="javascript:help_popup()">close</a> ]</div>
+    </div>
+    <div class="pop_content" id="pop_site_strand">
+      <p>The strand used for the motif site.</p>
+      <dl>
+        <dt>+</dt>
+        <dd>The motif site was found in the sequence as it was supplied.</dd>
+        <dt>-</dt>
+        <dd>The motif site was found in the reverse complement of the supplied sequence.</dd>
+      </dl>
+      <div style="float:right; bottom:0px;">[ 
+        <a href="javascript:help_popup()">close</a> ]</div>
+    </div>
+    <div class="pop_content" id="pop_site_start">
+      <p>The position in the sequence where the motif site starts. If a motif
+      started right at the beginning of a sequence it would be described as
+      starting at position 1.</p>
+      <div style="float:right; bottom:0px;">[ 
+        <a href="javascript:help_popup()">close</a> ]</div>
+    </div>
+    <div class="pop_content" id="pop_site_pvalue">
+      <p>The probability that an equal or better site would be found in a
+      random sequence of the same length conforming to the background letter
+      frequencies.</p>
+      <div style="float:right; bottom:0px;">[ 
+        <a href="javascript:help_popup()">close</a> ]</div>
+    </div>
+    <div class="pop_content" id="pop_site_match">
+      <p>A motif site with the 10 flanking letters on either side.</p> 
+      <p>When the site is not on the given strand then the site
+      and both flanks are reverse complemented so they align.</p>
+      <div style="float:right; bottom:0px;">[ 
+        <a href="javascript:help_popup()">close</a> ]</div>
+    </div>
+
+    <div class="pop_content" id="pop_seq_name">
+      <p>The name of the sequences as given in the FASTA file.</p>
+      <p>The number to the left of the sequence name is the position
+      of the sequence in the input sequence file.</p>
+      <div style="float:right; bottom:0px;">[ 
+        <a href="javascript:help_popup()">close</a> ]</div>
+    </div>
+
+    <div class="pop_content" id="pop_motif_sites">
+      <p>These are the motif sites predicted by MEME and used to build the motif.</p>
+      <p>These sites are shown in solid color and hovering the cursor
+      over a site will reveal details about the site.  Only sequences
+      that contain a motif site are shown.</p>
+      <div style="float:right; bottom:0px;">[ 
+        <a href="javascript:help_popup()">close</a> ]</div>
+    </div>
+
+    <div class="pop_content" id="pop_scanned_sites">
+      <p>These are the motif sites predicted by MEME plus
+      any additional sites detected using a motif scanning
+      algorithm.</p>
+      <p>These MEME sites are shown in solid color and 
+      additional scanned sites are shown greyed out.
+      Hovering the cursor over a site will reveal details about the site.
+      Only sequences containing a predicted or scanned motif site are shown.</p>
+      <p>The scanned sites are predicted using a
+      log-odds scoring matrix constructed from the MEME sites.
+      Only scanned sites with position <i>p</i>-values less
+      than 0.0001 are shown.</p>
+      <div style="float:right; bottom:0px;">[ 
+        <a href="javascript:help_popup()">close</a> ]</div>
+    </div>
+
+    <div class="pop_content" id="pop_all_sequences">
+      <p>These are the same sites as shown by selecting the
+      "Motif Sites + Scanned Sites" button except that all
+      sequences, including those with no sites, are included
+      in the diagram.</p>
+      <div style="float:right; bottom:0px;">[ 
+        <a href="javascript:help_popup()">close</a> ]</div>
+    </div>
+
+    <div class="pop_content" id="pop_seq_pvalue">
+      <p>This is the combined match <i>p</i>-value.</p>
+      <p>The combined match <i>p</i>-value is defined as the probability that a
+      random sequence (with the same length and conforming to the background) 
+      would have position <i>p</i>-values such that the product is smaller
+      or equal to the value calculated for the sequence under test.</p>
+      <p>The position <i>p</i>-value is defined as the probability that a
+      random sequence (with the same length and conforming to the background)
+      would have a match to the motif under test with a score greater or equal
+      to the largest found in the sequence under test.</p>
+      <p>Hovering your mouse over a motif site in the motif location 
+      block diagram will show its position <i>p</i>-value and other information
+      about the site.</p>
+      <div style="float:right; bottom:0px;">[ 
+        <a href="javascript:help_popup()">close</a> ]</div>
+    </div>
+
+    <div class="pop_content" id="pop_download_pdf_motif_locations">
+      <p>Use this button to download the "Motif Locations" block diagrams
+	as a PDF image suitable for publication.
+      </p>
+      <p>
+	Only the block diagrams currently visible in the inner scrolling 
+	window (below) will be included in the image, and the numbers to
+	the left of each sequence name will not be included in the image.
+	You can change the size of the inner scrolling by moving the bottom
+	of the main document window up and down.  You can display more
+	diagrams by making your browser's font size smaller.
+      </p>
+      <div style="float:right; bottom:0px;">[ 
+        <a href="javascript:help_popup()">close</a> ]</div>
+    </div>
+
+    <div class="pop_content" id="pop_download_svg_motif_locations">
+      <p>Use this button to download the "Motif Locations" block diagrams
+	as a SVG image use in HTML documents.
+      </p>
+      <p>
+	Only the block diagrams currently visible in the inner scrolling 
+	window (below) will be included in the image, and the numbers to
+	the left of each sequence name will not be included in the image.
+	You can change the size of the inner scrolling by moving the bottom
+	of the main document window up and down.  You can display more
+	diagrams by making your browser's font size smaller.
+      </p>
+      <div style="float:right; bottom:0px;">[ 
+        <a href="javascript:help_popup()">close</a> ]</div>
+    </div>
+
+    <div class="pop_content" id="pop_offline">
+      <p>
+        This button will only function if your browser was
+	connected to the internet when you loaded this page.
+      </p>
+      <p>
+	To use this button, make sure your browser is connected to the internet
+	and then reload this page.  (You may need to do a "hard refresh" to clear the cache.
+	On Mac, hold down the Shift key and click the Reload button.
+	On Windows/Linux, hold down Ctrl and press F5.)
+      </p>
+      <div style="float:right; bottom:0px;">[ 
+        <a href="javascript:help_popup()">close</a> ]</div>
+    </div>
+
+    <div class="pop_content" id="pop_motif_location">
+      <p>This diagram shows the location of motif sites.</p>
+      <p>Each block shows the position and strength of a motif
+      site.  The height of a block gives an indication of the 
+      significance of the site as taller blocks are more significant. 
+      The height is calculated to be proportional to the negative 
+      logarithm of the <i>p</i>-value of the site, truncated at 
+      the height for a <i>p</i>-value of 1e-10.</p>
+      <p>For complementable alphabets (like DNA), sites on the 
+      positive strand are shown above the line,
+      sites on the negative strand are shown below.</p>
+      <p>Placing the cursor
+      over a motif site will reveal more information about the site
+      including its position <i>p</i>-value.  (See the help
+      for the <i>p</i>-value column for an explanation of position 
+      <i>p</i>-values.)</p>
+      <div style="float:right; bottom:0px;">[ 
+        <a href="javascript:help_popup()">close</a> ]</div>
+    </div>
+
+    <div class="pop_content" id="pop_seq_source">
+      <p>The name of the file(s) of sequences input to MEME.</p>
+      <div style="float:right; bottom:0px;">[ 
+        <a href="javascript:help_popup()">close</a> ]</div>
+    </div>
+    <div class="pop_content" id="pop_psp_source">
+      <p>The position specific priors file used by MEME to find the motifs.</p>
+      <div style="float:right; bottom:0px;">[ 
+        <a href="javascript:help_popup()">close</a> ]</div>
+    </div>
+    <div class="pop_content" id="pop_seq_alph">
+      <p>The alphabet used by the sequences.</p>
+      <div style="float:right; bottom:0px;">[ 
+        <a href="javascript:help_popup()">close</a> ]</div>
+    </div>
+    <div class="pop_content" id="pop_seq_count">
+      <p>The number of FASTA sequences provided in this input file.</p>
+      <div style="float:right; bottom:0px;">[ 
+        <a href="javascript:help_popup()">close</a> ]</div>
+    </div>
+    <div class="pop_content" id="pop_num_positions">
+      <p>The number of characters in the sequences provided in this FASTA input file.</p>
+      <div style="float:right; bottom:0px;">[ 
+        <a href="javascript:help_popup()">close</a> ]</div>
+    </div>
+
+    <div class="pop_content" id="pop_alph_name">
+      <p>The name of the alphabet symbol.</p>
+      <div style="float:right; bottom:0px;">[ 
+        <a href="javascript:help_popup()">close</a> ]</div>
+    </div>
+    <div class="pop_content" id="pop_alph_freq">
+      <p>The frequency of the alphabet symbol in the dataset.</p>
+      <div style="float:right; bottom:0px;">[ 
+        <a href="javascript:help_popup()">close</a> ]</div>
+    </div>
+    <div class="pop_content" id="pop_alph_bg">
+      <p>The frequency of the alphabet symbol as defined by the background model.</p>
+      <div style="float:right; bottom:0px;">[ 
+        <a href="javascript:help_popup()">close</a> ]</div>
+    </div>
+
+    <!-- templates -->
+    <div id="measure_match" class="match"></div>
+    <div class="template pop_block" id="tmpl_block_info">
+      <div>
+        <span class="tvar_logo_pad lflank" style="visibility:hidden;"></span>
+        <span class="tvar_logo"></span>
+      </div>
+      <div class="block_sequence_fragment">
+        <span class="tvar_lflank lflank"></span>
+        <span class="tvar_match match"></span>
+        <span class="tvar_rflank rflank"></span>
+      </div>
+      <table class="block_information">
+        <tr><th>Motif</th><td class="tvar_motif">1</td></tr>
+        <tr><th><i>p</i>-value</th><td class="tvar_pvalue">8.23e-7</td></tr>
+        <tr><th>Start</th><td class="tvar_start">23</td></tr>
+        <tr><th>End</th><td class="tvar_end">33</td></tr>
+      </table>
+    </div>
+
+    <div class="template pop_block" id="tmpl_scan_info">
+      <h5>Scanned Site</h5>
+      <div class="tvar_logo"></div>
+      <table class="block_information">
+        <tr><th>Motif</th><td class="tvar_motif">1</td></tr>
+        <tr><th><i>p</i>-value</th><td class="tvar_pvalue">8.23e-7</td></tr>
+        <tr><th>Start</th><td class="tvar_start">23</td></tr>
+        <tr><th>End</th><td class="tvar_end">33</td></tr>
+      </table>
+    </div>
+
+    <div class="template box expanded_motif" id="tmpl_motif_expanded">
+      <div style="position: relative; min-height: 20px">
+        <div class="param_box">
+          <span class="param"><span class="tvar_ordinal"></span>.</span>
+        </div>
+        <div class="sym_btn positioned tvar_less" tabindex="0" 
+          title="Show less information.">&#8613;</div>
+        <div class="sym_btn positioned tvar_submit" tabindex="0"
+          title="Submit the motif to another MEME Suite program or download it.">&#8674;</div>
+      </div>
+      <div>
+        <div class="param_box">
+          <span class="param"><i>E</i>-value:</span>
+          <span class="tvar_evalue"></span>
+          <div class="help" data-topic="pop_ev"></div>
+        </div>
+        <div class="param_box">
+          <span class="param">Site Count:</span>
+          <span class="tvar_site_count"></span>
+          <div class="help" data-topic="pop_sites"></div>
+        </div>
+        <div class="param_box">
+          <span class="param">Width:</span>
+          <span class="tvar_width"></span>
+          <div class="help" data-topic="pop_width"></div>
+        </div>
+      </div>
+      <div class="tabMain base">
+        <div class="tabCenter tvar_logo"></div>
+      </div>
+      <div class="tabArea base">
+        <span class="tvar_tab tab" tabindex="0">Standard</span><span 
+          class="tvar_tab_rc tab middle" tabindex="0">Reverse 
+          Complement</span>
+      </div>
+      <div style="padding: 10px 0">
+        <div class="param_box">
+          <span class="param">Log Likelihood Ratio:</span>
+          <span class="tvar_llr"></span>
+          <div class="help" data-topic="pop_llr"></div>
+        </div>
+        <div class="param_box">
+          <span class="param">Information Content:</span>
+          <span class="tvar_ic"></span>
+          <div class="help" data-topic="pop_ic"></div>
+        </div>
+        <div class="param_box">
+          <span class="param">Relative Entropy:</span>
+          <span class="tvar_re"></span>
+          <div class="help" data-topic="pop_re"></div>
+        </div>
+        <div class="param_box">
+          <span class="param">Bayes Threshold:</span>
+          <span class="tvar_bt"></span>
+          <div class="help" data-topic="pop_bt"></div>
+        </div>
+      </div>
+      <div class="tvar_sites"></div>
+    </div>
+
+    <div id="tab_submit_or_download_motif"></div>
+    <script> make_submit_or_download_motif_form("tab_submit_or_download_motif", site_url, "MEME"); </script>
+
+    <!-- Page starts here -->
+    <div id="top" class="pad1">
+      <div class="prog_logo big">
+        <img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAD4AAABGCAYAAACUsCfoAAAAAXNSR0IArs4c6QAAAAZiS0dEAP8A/wD/oL2nkwAAAAlwSFlzAAALEgAACxIB0t1+/AAAAAd0SU1FB9wLHAInL7an9JAAAA8eSURBVHja7ZpZbxv3ucZ/s3AZ7qQkypZELZS3WHKiRJbTFnHqOjZcGzCQBf0A7cUB8glOb89dz30vChRp7xK0aZo4TYq6dtKqSew6iuJWpmPJlrVFFCmKI+7LLJw5F81MFZyec5rTILJaP8AAnAty+Pzf933ebeAhHuIhHuIhHmJPo6TpaeGLfimTydhLS0sUCgWazSbVahXDMOh0Ong8HiKRCAMDAxw+fJhHH31UeFDJ/91/bHp62r558ya6rmOaJuvr6+TzeYrFIoZhAOD1epFlmWAwSDqdZnR0lCNHjjA+Ps7+/fuFPUU8k8nYV69epVKpEA6HuXPnDrOzs7RaLbxeL93d3fj9foLBIB6Ph0ajQaVSAUBRFNLpNI888ggHDhzg3Llzwp4g/vbbb9szMzPE43FyuRwffPAB2WyWnp4ehoaGiMVi2LZNvV6n3W7j8/mIRqN4vV4ajQa1Wo2trS0OHTqEaZo89dRTfO973xMeaOKvvfaaffv2bcLhMCsrK/z+979HVVWOHz/O0NAQxWIRVVVRVRW/348oihiGgSiKxGIxurq6CAQCBINB3n//fcbGxiiXyxw7dowXX3yx1Nvbm3igiBcKhY9u3rw5OTMzQzgc5vbt23zwwQfIsszExAS2bZPP55EkiVAoRCQSIRwOI8sy5XKZ7e1tWq0WnU6HTqfD4OAggUAAVVXpdDo0m01GRkb44Q9/KDxQxH/729/as7Oz+Hw+Pv30U37zm9/g9Xrp6emht7eXYDCI3+/H6/UiCALtdhvLsuh0OkiSRCAQQJZl6vU65XKZ1dVV+vv7SSQS5PN5vF4vhUKBgwcP8qMf/WjXyIs7b+7cuWMvLi4iCAL1ep133nkHXdcZHh4mlUoRDofp7+8nHo9jGAaCIBCPx+nr6yOdTtPX14fH40HTNGRZpqenh76+PrLZLMVikYGBARRFwTRN5ubm+PGPf2zvFnF5583c3BzlchlZlrl16xa1Wo2xsTGi0SiDg4OutUzTJBKJIIoiXq+XQCBAIpEgFAphmiaqqlIoFKjVaoyOjhKJRFhfXycajRKNRunp6WFhYYG33nqLQqHwUTKZPP5VE5ecD5cvX7bv37+Poijkcjl++ctfMjo6ytDQEMlkEo/HQ7lcpt1u4/F4kGUZQRDw+Xz09fVx4MABRkZGSKVSdHV10el0KJVK1Ot14vE4kiRRKpVQFIV4PI5t23z66ad0Op2+K1eu/MeuWVxVVUzTRNd17t27RzKZJJFIEI1GEUWRdruNaZqIoogkSYiiiCiK+P1+AoEA0WiUQ4cOCQCbm5vb5XI5Xi6XWVtbw7ZtZFnG7/e7D1YUhWAwSLVaJZvN2v39/cJXHuOLi4t2sVhEEAS2t7eZn59n//79JBIJwuEwlmXRbDbRdR1BEBAEAcuysCwL2/5LmIriX+Wit7c3EY/HSSQSeDweDMPA4/EQCoWwbRvbtgmFQoTDYUqlErlcbnfE7f79+64gbWxs0G63icViRCIRBEHANE0Mw0CSJLxer0vSUfVKpUKxWGRtbc12UmKr1cI0TQD3t4PBoHtwgUAAv99Ps9kkn8/vjrjlcjlkWabdbrO8vEx3dzfhcJhoNEq9XkfTNERRxOfz4fV6sW0bSZJcBS+VSqytrdFqtbh+/bq9sLBALpdje3sbXddd4jutLwh/8WzLslBVdXeI12o1RFFkc3PTLTFjsRixWAxVVbEsC1mWkSTJdVXnMgyDarWKrusUi0X8fj+WZVGtVimXyxiGgW3bblh4PB78fj/tdhvbthFF0a3tv3Liuq4jiiKFQgFZlolEInR3d6MoConEXytLp1Bx0Ol0sG0bXdfRdZ1arYYgCNi2jaZptFot1zOcQ3LSnxMGzsHvCnHH/RqNBtFoFEmSCIfDAAwNDWFZFu12m0ajgaZpWJbl/oDH4/ncoTii5xBz1N+2bTqdDrIs4/P53MxgWRaapu2exQOBgHsAnU6HdrvN5uYmgUCASCRCJBIhkUhgmibNZpNarUaj0XAt71jfET1RFN1YliTJfUa73SaZTLK1tUWtVkPTNKampnaHuFNGyrKM1+t141bTNGq1GrVazS1EIpEI8XjcLWJqtdrnYthNF58pv23beL1eJEly1VzXder1Oq1Wi2AwiK7ru0PcSSs73bBYLBIMBpEkCdM0qVQq6LpOq9UiHA673Vmn08E0TfdyRM85CNM08Xq9bkoMhULugRqGgd/v3z1Xl2X5c24aDodRVZV4PO7W406/raoqtVqNYDCIz+dDURQ3vp3LuXeEz4nlTqdDOBxG13U3TBRF2b0mJRAI0Gg0EAQBTdPw+/2Uy2VXoJzRkkPEifNWq0UgEHCLEsedLcty1X1nzIdCIRRFoVQqUSqVsCyLYDBIPB7fncotlUq5JaWu6xiGgWmabG1tuanINE0EQXAPwSlk6vU6zWaTdruNpmnud3eWsk6fnkwmMU2Tzc1NVFVFURSi0SjpdHp3iB89ehRRFOnt7XWHCNFolFwu58ar08AYhuEWNH6/H4/H8zlL71R4J5XJskwgECAWi5HP51lZWaHVajE8PEw8Hufw4cO7Q3zfvn0C4E5MNU2jq6uLarVKPp//nPA5hYgzcYlEIoRCIfcQHLd3SDvEPR4PHo+HfD5PPp9HEARGRkYIhUIMDQ0Ju0Ic4NixY3g8Hnp7e8lms8RiMcLhMNlsFk3TXHW3bZtgMOjmfScEvF6vW8s7qczxgGazSSAQ4M9//jOqqlKpVHj88cfx+XyMjY3t7ujp1KlTQrlcdicupVKJkZER1tbWuHfvHqqqEolEiMVitNtt6vW6q+iNRoNms4kkSfh8PtfC0WgURVHo7+9nc3OTjY0N3n33XQYGBkilUiSTSU6ePCnsKnGA559/nkqlwtGjR8nn8/j9fh5//HEsy+LWrVvMz8+j6zqhUAifz4dhGG7z0mq1UFUVXdeJRCIEg0F32loqlbh37x53796lq6sLRVGIRCJMTEzs2pT1c8Qfe+wxYWpqyv1j2WyWVCpFIpGgUqkwNzfHnTt33JTnDCUlSaK7u5v+/n66u7vxeDxun16r1SgUCly/fp3bt29z+vRpBgcHqdVqRKPRB2uh8LOf/cyemZlhYWGBYDBIJBIBoFgs0mw2CYfDxONxfD4fg4ODros7vXWhUKDT6bg5/v3332dlZYWhoSHS6TSnTp1i3759VKtVzpw5w1c9dvpfNymvvPKKff36dbLZLIqiuBVWs9mk0WhgWZbbn4fDYURRRNM0AoEAvb29+Hw+Go0Gly9fZmNjg4mJCcbGxti/f787mJyfn6darTI5OcmJEyeEB4J4sVj8wfT09L/Pzs6SzWbdpWEikXBJGoZBs9kkGo0iyzKmabrLhtXVVTKZDJubm5w9e5YjR44wMDDAd7/7XWF2dtZeXFzkyJEj7pZm//79pFIpenp6vhIP+D8f8NZbb9nr6+ssLy+ztbXl1t5er9fdhxeLRSRJoquri0qlQiaTYXt7m0gkwpkzZ5BlmbGxMV544QX3eR9//LE9Pz/PsWPHuHHjBouLi0iSxMDAAMePH2dqakrYVeIAKysr9u3bt1leXnZn65qmoeu6W9AYhkGj0aBYLGKaJocOHeLRRx8lkUgwOTnpjp4d5HI5++OPP6ZcLjM+Ps61a9dYWFig2Wzi9Xp5/vnnOX36tLCrxHfi1q1b9tLSkuv+9XrdbTEVRSEWi5FMJhkdHWV4eJiDBw/+j8/Y2tr6+WuvvfYdwzBIpVJIkoSqqszPz1Ov17lw4QJf+9rXziYSiau7TvxvoVQqpUul0n2n2/oibz+899579k9/+lPC4TCnTp3i61//Orlcjp/85CdomsbTTz/NiRMn/pvH/CMotrQfyF/GD8Xj8aX/7yEePnx4dnx8fPJ3v/sdiqIwODjI5OSkcOPGDfvNN9/kypUr5PN5MpmMPT4+/qWQ71Z835fZZSSTyeMrKyt2vV7n7t27vPrqq1y7ds1+8sknhT/+8Y/2pUuXuHnzJs1mk6WlJTudTn8p5EUeAAwPDwvPPfccBw4cYHV1lc+KJ3t0dPTVixcvcvDgQebn53n55ZeZmZn5h1fLalv/twfqTaRMJmP/4he/YH19nSNHjnDhwgVisRj37t3jnXfeYWFhgQMHDnD+/HmeeuopYc9b3MH4+LjwrW99C0EQuHXrFtPT09RqNfr7+zlx4gTpdJqNjQ3efPNN3njjDbtYLP5gV1X9y8bly5ft119/nUqlwsmTJzl9+jQej4ePPvqITz75hLW1NYLBIJOTk5w7d46+vr4vzEN+EImfO3dOuHr1qv3666/z3nvvoWkaZ8+e5YknnnBXU5qmcfPmTQzDYG1tzR4cHBT2vMUdTE9P25cuXaJQKDA5OcmFCxfQdZ3Z2VkWFhbY2NhAURRSqRTPPvssY2Njwp62uINvfvObwp/+9Cf7V7/6FTdu3KDT6XD+/HmmpqbcoaaqqszOzmIYxhfK9Q80cYCJiQlhbm7OFgSBubk5vF4vzzzzDBMTE+7CMRgMsrCwwEsvvcS1a9fsb3zjG8KedvWd+OSTT+y3336bubk5JicnOXnyJJZl8eGHH7K2tkahUKDRaLBv3z4uXrzI2bNnhT1tcQdHjx4VMpmM3el0WFxcJBQKMTU1xbFjx6hWqwC0221WVlb49a9/zY0bN+wnn3xS2BN5/O/J88899xzDw8NkMhnm5uaIx+M8/fTT9PT0YFkWg4ODrK6u8sorrzA/P2/veVffidXVVfvdd99lenqa8+fPMzo6iqZp/OEPf2BhYYFWq4Usy4yMjHDx4kX+luXlvUh8aGhImJmZsS3L4vr165imSSqVYt++fbTbbWq1GtVqlWq1yt27d7l//749Ojoq7HniAFNTU8LS0pJdLpe5e/cu6+vrRCIRhoeHqVarrK6uous66+vrZLNZSqVS+rP2eW8TB0in00I2m3XVHqCvr49YLEYikXBfRiqXy+Ryufs7Q1tkj6O/v1/49re/zTPPPIMgCMzPz7sraJ/Ph9/vd/d3pVIp/U9hcQdOnX7p0iU7k8kgiqK76lIUxX19dKerC/wTYXt7+8zm5uaV5eVlNjY2iMfj+P1+hoeH6enpmd35evg/FXEHm1uF7ZXltXgg6EcSPSR7u/+zO9H1ff6VsFWq/pyHeIiHeIh/FfwXjVDdIW9O2PAAAAAASUVORK5CYII=" alt="MEME Logo">
+        <h1>MEME</h1>
+        <h2>Multiple Em for Motif Elicitation</h2>
+      </div>
+      <p>
+        For further information on how to interpret these results please access
+        <a href="https://meme-suite.org/meme/doc/meme.html">https://meme-suite.org/meme/doc/meme.html</a>. <br />
+        To get a copy of the MEME software please access 
+        <a href="https://meme-suite.org">https://meme-suite.org</a>. 
+      </p>
+      <p id="citation"> <script>print_citation("citation", "MEME");</script></p>
+    </div>
+    <!-- navigation -->
+    <div class="pad2">
+      <a class="jump" href="#motifs_sec">Discovered Motifs</a>
+      &nbsp;&nbsp;|&nbsp;&nbsp;
+      <a class="jump" href="#sites_sec">Motif Locations</a>
+      &nbsp;&nbsp;|&nbsp;&nbsp;
+      <a class="jump" href="#inputs_sec">Inputs &amp; Settings</a>
+      &nbsp;&nbsp;|&nbsp;&nbsp;
+      <a class="jump" href="#info_sec">Program Information</a>
+      &nbsp;&nbsp;|&nbsp;&nbsp;
+      <a class="jump" href="meme.txt">Results in Text Format</a>&nbsp;<span id="results_txt_help"></span>
+      &nbsp;&nbsp;|&nbsp;&nbsp;
+      <a class="jump" href="meme.xml">Results in XML Format</a>&nbsp;<span id="results_xml_help"></span>
+      <script>
+        make_help_button($("results_txt_help"), "pop_results_txt");
+        make_help_button($("results_xml_help"), "pop_results_xml");
+      </script>
+    </div>
+    <!-- alert the user when their browser is not up to the task -->
+    <noscript><h1 style="color:red">Javascript is required to view these results!</h1></noscript>
+    <h1 id="html5_warning" style="color:red; display:none;">Your browser does not support canvas!</h1>
+    <script>
+      if (!window.HTMLCanvasElement) $("html5_warning").style.display = "block";
+    </script>
+    <h2 class="mainh pad2" id="motifs_sec">Discovered Motifs</h2>
+    <div id="motifs" class="box">
+      <p>Please wait... Loading...</p>
+      <p>If the page has fully loaded and this message does not disappear then an error may have occurred.</p>
+    </div>
+    <h2 class="mainh pad2" id="sites_sec">Motif Locations</h2>
+    <div id="blocks" class="box">
+      <p>Please wait... Loading...</p>
+      <p>If the page has fully loaded and this message does not disappear then an error may have occurred.</p>
+    </div>
+    <h2 class="mainh pad2" id="inputs_sec">Inputs &amp; Settings</h2>
+    <div class="box">
+      <h4>Sequences</h4>
+      <table id="seq_info" class="inputs">
+        <tr>
+          <th>Role <div class="help" data-topic="pop_seq_role"></div></th>
+          <th>Source <div class="help" data-topic="pop_seq_source"></div></th>
+          <th class="col_psp">PSP Source <div class="help" data-topic="pop_psp_source"></div></th>
+          <th>Alphabet <div class="help" data-topic="pop_seq_alph"></div></th>
+          <th>Sequence Count <div class="help" data-topic="pop_seq_count"></div></th>
+          <th>Total Size <div class="help" data-topic="pop_num_positions"></div></th>
+        </tr>
+        <tr>
+          <td>Primary Sequences</td>
+          <td id="ins_seq_source"></td>
+          <td id="ins_seq_psp" class="col_psp"></td>
+          <td id="ins_seq_alphabet"></td>
+          <td id="ins_seq_count"></td>
+          <td id="ins_num_positions"></td>
+        </tr>
+        <tr class="col_control">
+          <td class="col_control">Control Sequences</td>
+          <td id="ins_control_source" class="col_control"></td>
+          <td id="ins_control_psp" class="col_control col_psp"></td>
+          <td id="ins_control_alphabet" class="col_control"></td>
+          <td id="ins_control_count" class="col_control"></td>
+          <td id="ins_control_positions" class="col_control"></td>
+        </tr>
+      </table>
+      <script>
+      {
+        var db = data.sequence_db;
+        $("ins_seq_source").innerHTML = db.primary_source;
+        $("ins_seq_alphabet").innerHTML = current_alphabet.get_alphabet_name();
+        $("ins_seq_count").innerHTML = db.primary_count;
+        $("ins_num_positions").innerHTML = db.primary_positions;
+        $("ins_control_source").innerHTML = db.control_source;
+        $("ins_control_alphabet").innerHTML = current_alphabet.get_alphabet_name();
+        $("ins_control_count").innerHTML = db.control_count;
+        $("ins_control_positions").innerHTML = db.control_positions;
+        if (db.psp_source) {
+          $("ins_seq_psp").innerHTML = db.psp_source;
+        }
+        toggle_class($("seq_info"), "hide_psp", !(db.psp_source));
+        toggle_class($("seq_info"), "hide_control", (db.control_source == "--none--"));
+      }
+      </script>
+      <h4>Background Model</h4>
+      <span id="bg_source"></span>
+      <span id="bg_order"></span>
+      <span id="alpha_bg"></span>
+      <script>
+      {
+        $("bg_source").appendChild(make_background_source("Source", data.background.source, false));
+        $("bg_order").innerHTML = "&nbsp;&nbsp;&nbsp;&nbsp;<b>Order:</b> " + data.background.order +
+          (data.background.order>0 ? " (only order-0 shown)" : "");
+        $("alpha_bg").appendChild(make_alpha_bg_table(current_alphabet, data.sequence_db.freqs));
+      }
+      </script>
+      <h4>Other Settings</h4>
+      <table id="tbl_settings" class="inputs hide_advanced">
+        <tr>
+          <th>Motif Site Distribution</th>
+          <td id="opt_mod">
+            <span class="mod_zoops">ZOOPS: Zero or one site per sequence</span>
+            <span class="mod_oops">OOPS: Exactly one site per sequence</span>
+            <span class="mod_anr">ANR: Any number of sites per sequence</span>
+          </td>
+        </tr>
+        <tr>
+          <th>Objective Function</th>
+          <td id=opt_objfun></td>
+        </tr>
+        <tr>
+          <th>Starting Point Function</th>
+          <td id=opt_spfun></td>
+        </tr>
+        <tr>
+          <th>Site Strand Handling</th>
+          <td id="opt_strand">
+            <span class="strand_none">This alphabet only has one strand</span>
+            <span class="strand_given">Sites must be on the given strand</span>
+            <span class="strand_both">Sites may be on either strand</span>
+          </td>
+        </tr>
+        <tr>
+          <th>Maximum Number of Motifs</th>
+          <td id="opt_nmotifs"></td>
+        </tr>
+        <tr>
+          <th>Motif E-value Threshold</th>
+          <td id="opt_evt"></td>
+        </tr>
+        <tr>
+          <th>Minimum Motif Width</th>
+          <td id="opt_minw"></td>
+        </tr>
+        <tr>
+          <th>Maximum Motif Width</th>
+          <td id="opt_maxw"></td>
+        </tr>
+        <tr>
+          <th>Minimum Sites per Motif</th>
+          <td id="opt_minsites"></td>
+        </tr>
+        <tr>
+          <th>Maximum Sites per Motif</th>
+          <td id="opt_maxsites"></td>
+        </tr>
+        <tr class="advanced">
+          <th>Bias on Number of Sites</th>
+          <td id="opt_wnsites"></td>
+        </tr>
+        <tr class="advanced">
+          <th>Sequence Prior</th>
+          <td id="opt_prior">
+            <span class="prior_dirichlet">Simple Dirichlet</span>
+            <span class="prior_dmix">Dirichlet Mixture</span>
+            <span class="prior_mega">Mega-weight Dirichlet Mixture</span>
+            <span class="prior_megap">Mega-weight Dirichlet Mixture Plus</span>
+            <span class="prior_addone">Add One</span>
+          </td>
+        </tr>
+        <tr class="advanced">
+          <th>Sequence Prior Source</th>
+	  <td id="opt_prior_source"></td>
+        </tr>
+        <tr class="advanced">
+          <th>Sequence Prior Strength</th>
+          <td id="opt_b"></td>
+        </tr>
+        <tr class="advanced">
+          <th>EM Starting Point Source</th>
+          <td id="opt_substring">
+            <span class="substring_on">From substrings in input sequences</span>
+            <span class="substring_off">From strings on command line (-cons)</span>
+          </td>
+        </tr>
+        <tr class="advanced">
+          <th>EM Starting Point Map Type</th>
+          <td id="opt_spmap">
+            <span class="spmap_uni">Uniform</span>
+            <span class="spmap_pam">Point Accepted Mutation</span>
+          </td>
+        </tr>
+        <tr class="advanced">
+          <th>EM Starting Point Fuzz</th>
+          <td id="opt_spfuzz"></td>
+        </tr>
+        <tr class="advanced">
+          <th>EM Maximum Iterations</th>
+          <td id="opt_maxiter"></td>
+        </tr>
+        <tr class="advanced">
+          <th>EM Improvement Threshold</th>
+          <td id="opt_distance"></td>
+        </tr>
+        <tr class="advanced">
+          <th>Maximum Search Size</th>
+          <td id="opt_searchsize"></td>
+        </tr>
+        <tr class="advanced">
+          <th>Maximum Number of Sites for E-values</th>
+          <td id="opt_csites"></td>
+        </tr>
+        <tr class="advanced">
+          <th>Trim Gap Open Cost</th>
+          <td id="opt_wg"></td>
+        </tr>
+        <tr class="advanced">
+          <th>Trim Gap Extend Cost</th>
+          <td id="opt_ws"></td>
+        </tr>
+        <tr class="advanced">
+          <th>End Gap Treatment</th>
+          <td id="opt_noendgaps">
+            <span class="noendgaps_on">No cost</span>
+            <span class="noendgaps_off">Same cost as other gaps</span>
+          </td>
+        </tr>
+        <tr>
+          <td colspan="2" style="text-align: center">
+            <a href="javascript:toggle_class(document.getElementById('tbl_settings'), 'hide_advanced')">
+              <span class="show_more">Show Advanced Settings</span>
+              <span class="show_less">Hide Advanced Settings</span>
+            </a>
+          </td>
+        </tr>
+      </table>
       <script>
       {
         $("opt_mod").className = data.options.mod;
--- a/test-data/meme_output_test2.txt	Thu Aug 29 10:19:40 2024 +0000
+++ b/test-data/meme_output_test2.txt	Mon Jul 14 21:33:56 2025 +0000
@@ -1,40 +1,180 @@
 ********************************************************************************
-SUMMARY OF MOTIFS
+MOTIF GGSRTATAAAA MEME-1	width =  11  sites =  30  llr = 254  E-value = 5.1e-040
 ********************************************************************************
+--------------------------------------------------------------------------------
+	Motif GGSRTATAAAA MEME-1 Description
+--------------------------------------------------------------------------------
+Simplified        A  3313:9:a798
+pos.-specific     C  1:3::1:::1:
+probability       G  6756::::::2
+matrix            T  1:11a1a:3::
+
+         bits    2.2       *    
+                 2.0     * *    
+                 1.8     * *    
+                 1.5     * ** * 
+Relative         1.3     * ** * 
+Entropy          1.1     ****** 
+(12.2 bits)      0.9  *  *******
+                 0.7  *  *******
+                 0.4 ** ********
+                 0.2 ***********
+                 0.0 -----------
+
+Multilevel           GGGGTATAAAA
+consensus            AACA    T  
+sequence                        
+                                
+--------------------------------------------------------------------------------
+
+--------------------------------------------------------------------------------
+	Motif GGSRTATAAAA MEME-1 sites sorted by position p-value
+--------------------------------------------------------------------------------
+Sequence name             Start   P-value               Site  
+-------------             ----- ---------            -----------
+chr21_46046964_46047014_     13  4.51e-07 AAGGCCAGGA GGGGTATAAAA GCCTGAGAGC
+chr21_46031920_46031970_     16  2.22e-06 ATACCCAGGG AGGGTATAAAA CCTCAGCAGC
+chr21_32202076_32202126_     14  2.74e-06 CCACCAGCTT GAGGTATAAAA AGCCCTGTAC
+chr21_46057197_46057247_     37  4.86e-06 ACAGGCCCTG GGCATATAAAA GCC       
+chr21_45993530_45993580_      8  4.86e-06    CCAAGGA GGAGTATAAAA GCCCCACAAA
+chr21_45971413_45971463_     10  4.86e-06  CAGGCCCTG GGCATATAAAA GCCCCAGCAG
+chr21_31964683_31964733_     14  4.86e-06 GATTCACTGA GGCATATAAAA GGCCCTCTGC
+chr21_47517957_47518007_     33  6.48e-06 CCGGCGGGGC GGGGTATAAAG GGGGCGG   
+chr21_45978668_45978718_      5  6.48e-06       CAGA GGGGTATAAAG GTTCCGACCA
+chr21_32185595_32185645_     19  6.48e-06 CACCAGAGCT GGGATATATAA AGAAGGTTCT
+chr21_32410820_32410870_     22  1.38e-05 AATCACTGAG GATGTATAAAA GTCCCAGGGA
+chr21_31992870_31992920_     17  1.38e-05 CACTATTGAA GATGTATAAAA TTTCATTTGC
+chr21_19617074_19617124_     40  1.41e-05 CCTCGGGACG TGGGTATATAA           
+chr21_31914206_31914256_     16  1.61e-05 CCCACTACTT AGAGTATAAAA TCATTCTGAG
+chr21_46020421_46020471_      3  1.95e-05         GA GACATATAAAA GCCAACATCC
+chr21_32253899_32253949_     18  1.95e-05 CCCACCAGCA AGGATATATAA AAGCTCAGGA
+chr21_45705687_45705737_     38  2.16e-05 CGTGGTCGCG GGGGTATAACA GC        
+chr21_47575506_47575556_     31  3.04e-05 GCTGCCGGTG AGCGTATAAAG GCCCTGGCG 
+chr21_31744582_31744632_     13  3.04e-05 CAGGTCTAAG AGCATATATAA CTTGGAGTCC
+chr21_31768316_31768366_      1  3.67e-05          . AACGTATATAA ATGGTCCTGT
+chr21_26934381_26934431_     28  3.93e-05 AGTCACAAGT GAGTTATAAAA GGGTCGCACG
+chr21_31933633_31933683_      5  5.65e-05       TCAG AGTATATATAA ATGTTCCTGT
+chr21_31710037_31710087_     15  6.24e-05 CCCAGGTTTC TGAGTATATAA TCGCCGCACC
+chr21_36411748_36411798_     23  7.15e-05 AGTTTCAGTT GGCATCtaaaa attatataac
+chr21_46102103_46102153_     37  1.39e-04 TGCCTGGGTC CAGGTATAAAG GCT       
+chr21_46086869_46086919_     38  1.39e-04 TGCCTGGGCC CAGGTATAAAG GC        
+chr21_37838750_37838800_      3  4.81e-04         ga tggttttataa ggggcctcac
+chr21_31962741_31962791_     14  8.57e-04 TATAACTCAG GTTGGATAAAA TAATTTGTAC
+chr21_31973364_31973414_      8  1.47e-03    aaactta aaactctataa acttaaaact
+chr21_28217753_28217803_     27  2.64e-03 GGTGGGGGTG GGGGTTTCACT GGTCCACTAT
+--------------------------------------------------------------------------------
 
 --------------------------------------------------------------------------------
-	Combined block diagrams: non-overlapping sites with p-value < 0.0001
+	Motif GGSRTATAAAA MEME-1 block diagrams
 --------------------------------------------------------------------------------
-SEQUENCE NAME            COMBINED P-VALUE  MOTIF DIAGRAM
+SEQUENCE NAME            POSITION P-VALUE  MOTIF DIAGRAM
 -------------            ----------------  -------------
-chr21_19617074_19617124_         5.63e-04  39_[+1(1.41e-05)]
-chr21_26934381_26934431_         1.57e-03  27_[+1(3.93e-05)]_12
-chr21_28217753_28217803_         1.00e-01  50
-chr21_31710037_31710087_         2.49e-03  14_[+1(6.24e-05)]_25
-chr21_31744582_31744632_         1.22e-03  12_[+1(3.04e-05)]_27
-chr21_31768316_31768366_         1.47e-03  [+1(3.67e-05)]_39
-chr21_31914206_31914256_         6.45e-04  15_[+1(1.61e-05)]_24
-chr21_31933633_31933683_         2.26e-03  4_[+1(5.65e-05)]_35
-chr21_31962741_31962791_         3.37e-02  50
-chr21_31964683_31964733_         1.95e-04  13_[+1(4.86e-06)]_26
-chr21_31973364_31973414_         5.73e-02  50
-chr21_31992870_31992920_         5.52e-04  16_[+1(1.38e-05)]_23
-chr21_32185595_32185645_         2.59e-04  18_[+1(6.48e-06)]_21
-chr21_32202076_32202126_         1.10e-04  13_[+1(2.74e-06)]_26
-chr21_32253899_32253949_         7.78e-04  17_[+1(1.95e-05)]_22
-chr21_32410820_32410870_         5.52e-04  21_[+1(1.38e-05)]_18
-chr21_36411748_36411798_         2.85e-03  22_[+1(7.15e-05)]_17
-chr21_37838750_37838800_         1.90e-02  50
-chr21_45705687_45705737_         8.63e-04  37_[+1(2.16e-05)]_2
-chr21_45971413_45971463_         1.95e-04  9_[+1(4.86e-06)]_30
-chr21_45978668_45978718_         2.59e-04  4_[+1(6.48e-06)]_35
-chr21_45993530_45993580_         1.95e-04  7_[+1(4.86e-06)]_32
-chr21_46020421_46020471_         7.78e-04  2_[+1(1.95e-05)]_37
-chr21_46031920_46031970_         8.89e-05  15_[+1(2.22e-06)]_24
-chr21_46046964_46047014_         1.80e-05  12_[+1(4.51e-07)]_27
-chr21_46057197_46057247_         1.95e-04  36_[+1(4.86e-06)]_3
-chr21_46086869_46086919_         5.54e-03  50
-chr21_46102103_46102153_         5.54e-03  50
-chr21_47517957_47518007_         2.59e-04  32_[+1(6.48e-06)]_7
-chr21_47575506_47575556_         1.22e-03  30_[+1(3.04e-05)]_9
+chr21_46046964_46047014_          4.5e-07  12_[+1]_27
+chr21_46031920_46031970_          2.2e-06  15_[+1]_24
+chr21_32202076_32202126_          2.7e-06  13_[+1]_26
+chr21_46057197_46057247_          4.9e-06  36_[+1]_3
+chr21_45993530_45993580_          4.9e-06  7_[+1]_32
+chr21_45971413_45971463_          4.9e-06  9_[+1]_30
+chr21_31964683_31964733_          4.9e-06  13_[+1]_26
+chr21_47517957_47518007_          6.5e-06  32_[+1]_7
+chr21_45978668_45978718_          6.5e-06  4_[+1]_35
+chr21_32185595_32185645_          6.5e-06  18_[+1]_21
+chr21_32410820_32410870_          1.4e-05  21_[+1]_18
+chr21_31992870_31992920_          1.4e-05  16_[+1]_23
+chr21_19617074_19617124_          1.4e-05  39_[+1]
+chr21_31914206_31914256_          1.6e-05  15_[+1]_24
+chr21_46020421_46020471_          1.9e-05  2_[+1]_37
+chr21_32253899_32253949_          1.9e-05  17_[+1]_22
+chr21_45705687_45705737_          2.2e-05  37_[+1]_2
+chr21_47575506_47575556_            3e-05  30_[+1]_9
+chr21_31744582_31744632_            3e-05  12_[+1]_27
+chr21_31768316_31768366_          3.7e-05  [+1]_39
+chr21_26934381_26934431_          3.9e-05  27_[+1]_12
+chr21_31933633_31933683_          5.6e-05  4_[+1]_35
+chr21_31710037_31710087_          6.2e-05  14_[+1]_25
+chr21_36411748_36411798_          7.1e-05  22_[+1]_17
+chr21_46102103_46102153_          0.00014  36_[+1]_3
+chr21_46086869_46086919_          0.00014  37_[+1]_2
+chr21_37838750_37838800_          0.00048  2_[+1]_37
+chr21_31962741_31962791_          0.00086  13_[+1]_26
+chr21_31973364_31973414_           0.0015  7_[+1]_32
+chr21_28217753_28217803_           0.0026  26_[+1]_13
+--------------------------------------------------------------------------------
+
+--------------------------------------------------------------------------------
+	Motif GGSRTATAAAA MEME-1 in BLOCKS format
+--------------------------------------------------------------------------------
+BL   MOTIF GGSRTATAAAA width=11 seqs=30
+chr21_46046964_46047014_ (   13) GGGGTATAAAA  1 
+chr21_46031920_46031970_ (   16) AGGGTATAAAA  1 
+chr21_32202076_32202126_ (   14) GAGGTATAAAA  1 
+chr21_46057197_46057247_ (   37) GGCATATAAAA  1 
+chr21_45993530_45993580_ (    8) GGAGTATAAAA  1 
+chr21_45971413_45971463_ (   10) GGCATATAAAA  1 
+chr21_31964683_31964733_ (   14) GGCATATAAAA  1 
+chr21_47517957_47518007_ (   33) GGGGTATAAAG  1 
+chr21_45978668_45978718_ (    5) GGGGTATAAAG  1 
+chr21_32185595_32185645_ (   19) GGGATATATAA  1 
+chr21_32410820_32410870_ (   22) GATGTATAAAA  1 
+chr21_31992870_31992920_ (   17) GATGTATAAAA  1 
+chr21_19617074_19617124_ (   40) TGGGTATATAA  1 
+chr21_31914206_31914256_ (   16) AGAGTATAAAA  1 
+chr21_46020421_46020471_ (    3) GACATATAAAA  1 
+chr21_32253899_32253949_ (   18) AGGATATATAA  1 
+chr21_45705687_45705737_ (   38) GGGGTATAACA  1 
+chr21_47575506_47575556_ (   31) AGCGTATAAAG  1 
+chr21_31744582_31744632_ (   13) AGCATATATAA  1 
+chr21_31768316_31768366_ (    1) AACGTATATAA  1 
+chr21_26934381_26934431_ (   28) GAGTTATAAAA  1 
+chr21_31933633_31933683_ (    5) AGTATATATAA  1 
+chr21_31710037_31710087_ (   15) TGAGTATATAA  1 
+chr21_36411748_36411798_ (   23) GGCATCTAAAA  1 
+chr21_46102103_46102153_ (   37) CAGGTATAAAG  1 
+chr21_46086869_46086919_ (   38) CAGGTATAAAG  1 
+chr21_37838750_37838800_ (    3) TGGTTTTATAA  1 
+chr21_31962741_31962791_ (   14) GTTGGATAAAA  1 
+chr21_31973364_31973414_ (    8) AAACTCTATAA  1 
+chr21_28217753_28217803_ (   27) GGGGTTTCACT  1 
+//
+
+--------------------------------------------------------------------------------
+
+--------------------------------------------------------------------------------
+	Motif GGSRTATAAAA MEME-1 position-specific scoring matrix
+--------------------------------------------------------------------------------
+log-odds matrix: alength= 4 w= 11 n= 1200 bayes= 5.2854 E= 5.1e-040 
+   -14   -179    114   -112 
+     3  -1155    137   -270 
+  -114     20     86    -71 
+     3   -279    122   -170 
+ -1155  -1155   -295    215 
+   156   -179  -1155   -170 
+ -1155  -1155  -1155    220 
+   172   -279  -1155  -1155 
+   125  -1155  -1155     46 
+   167   -179  -1155  -1155 
+   144  -1155    -63   -270 
+--------------------------------------------------------------------------------
+
+--------------------------------------------------------------------------------
+	Motif GGSRTATAAAA MEME-1 position-specific probability matrix
+--------------------------------------------------------------------------------
+letter-probability matrix: alength= 4 w= 11 nsites= 30 E= 5.1e-040 
+ 0.266667  0.066667  0.566667  0.100000 
+ 0.300000  0.000000  0.666667  0.033333 
+ 0.133333  0.266667  0.466667  0.133333 
+ 0.300000  0.033333  0.600000  0.066667 
+ 0.000000  0.000000  0.033333  0.966667 
+ 0.866667  0.066667  0.000000  0.066667 
+ 0.000000  0.000000  0.000000  1.000000 
+ 0.966667  0.033333  0.000000  0.000000 
+ 0.700000  0.000000  0.000000  0.300000 
+ 0.933333  0.066667  0.000000  0.000000 
+ 0.800000  0.000000  0.166667  0.033333 
+--------------------------------------------------------------------------------
+
+--------------------------------------------------------------------------------
+	Motif GGSRTATAAAA MEME-1 regular expression
+--------------------------------------------------------------------------------
+[GA][GA][GC][GA]TATA[AT]AA
 --------------------------------------------------------------------------------
\ No newline at end of file
--- a/test-data/meme_output_test2.xml	Thu Aug 29 10:19:40 2024 +0000
+++ b/test-data/meme_output_test2.xml	Mon Jul 14 21:33:56 2025 +0000
@@ -1,3 +1,658 @@
+<alphabet_matrix>
+<alphabet_array>
+<value letter_id="A">-14</value>
+<value letter_id="C">-179</value>
+<value letter_id="G">114</value>
+<value letter_id="T">-112</value>
+</alphabet_array>
+<alphabet_array>
+<value letter_id="A">3</value>
+<value letter_id="C">-1155</value>
+<value letter_id="G">137</value>
+<value letter_id="T">-270</value>
+</alphabet_array>
+<alphabet_array>
+<value letter_id="A">-114</value>
+<value letter_id="C">20</value>
+<value letter_id="G">86</value>
+<value letter_id="T">-71</value>
+</alphabet_array>
+<alphabet_array>
+<value letter_id="A">3</value>
+<value letter_id="C">-279</value>
+<value letter_id="G">122</value>
+<value letter_id="T">-170</value>
+</alphabet_array>
+<alphabet_array>
+<value letter_id="A">-1155</value>
+<value letter_id="C">-1155</value>
+<value letter_id="G">-295</value>
+<value letter_id="T">215</value>
+</alphabet_array>
+<alphabet_array>
+<value letter_id="A">156</value>
+<value letter_id="C">-179</value>
+<value letter_id="G">-1155</value>
+<value letter_id="T">-170</value>
+</alphabet_array>
+<alphabet_array>
+<value letter_id="A">-1155</value>
+<value letter_id="C">-1155</value>
+<value letter_id="G">-1155</value>
+<value letter_id="T">220</value>
+</alphabet_array>
+<alphabet_array>
+<value letter_id="A">172</value>
+<value letter_id="C">-279</value>
+<value letter_id="G">-1155</value>
+<value letter_id="T">-1155</value>
+</alphabet_array>
+<alphabet_array>
+<value letter_id="A">125</value>
+<value letter_id="C">-1155</value>
+<value letter_id="G">-1155</value>
+<value letter_id="T">46</value>
+</alphabet_array>
+<alphabet_array>
+<value letter_id="A">167</value>
+<value letter_id="C">-179</value>
+<value letter_id="G">-1155</value>
+<value letter_id="T">-1155</value>
+</alphabet_array>
+<alphabet_array>
+<value letter_id="A">144</value>
+<value letter_id="C">-1155</value>
+<value letter_id="G">-63</value>
+<value letter_id="T">-270</value>
+</alphabet_array>
+</alphabet_matrix>
+</scores>
+<probabilities>
+<alphabet_matrix>
+<alphabet_array>
+<value letter_id="A">0.266667</value>
+<value letter_id="C">0.066667</value>
+<value letter_id="G">0.566667</value>
+<value letter_id="T">0.100000</value>
+</alphabet_array>
+<alphabet_array>
+<value letter_id="A">0.300000</value>
+<value letter_id="C">0.000000</value>
+<value letter_id="G">0.666667</value>
+<value letter_id="T">0.033333</value>
+</alphabet_array>
+<alphabet_array>
+<value letter_id="A">0.133333</value>
+<value letter_id="C">0.266667</value>
+<value letter_id="G">0.466667</value>
+<value letter_id="T">0.133333</value>
+</alphabet_array>
+<alphabet_array>
+<value letter_id="A">0.300000</value>
+<value letter_id="C">0.033333</value>
+<value letter_id="G">0.600000</value>
+<value letter_id="T">0.066667</value>
+</alphabet_array>
+<alphabet_array>
+<value letter_id="A">0.000000</value>
+<value letter_id="C">0.000000</value>
+<value letter_id="G">0.033333</value>
+<value letter_id="T">0.966667</value>
+</alphabet_array>
+<alphabet_array>
+<value letter_id="A">0.866667</value>
+<value letter_id="C">0.066667</value>
+<value letter_id="G">0.000000</value>
+<value letter_id="T">0.066667</value>
+</alphabet_array>
+<alphabet_array>
+<value letter_id="A">0.000000</value>
+<value letter_id="C">0.000000</value>
+<value letter_id="G">0.000000</value>
+<value letter_id="T">1.000000</value>
+</alphabet_array>
+<alphabet_array>
+<value letter_id="A">0.966667</value>
+<value letter_id="C">0.033333</value>
+<value letter_id="G">0.000000</value>
+<value letter_id="T">0.000000</value>
+</alphabet_array>
+<alphabet_array>
+<value letter_id="A">0.700000</value>
+<value letter_id="C">0.000000</value>
+<value letter_id="G">0.000000</value>
+<value letter_id="T">0.300000</value>
+</alphabet_array>
+<alphabet_array>
+<value letter_id="A">0.933333</value>
+<value letter_id="C">0.066667</value>
+<value letter_id="G">0.000000</value>
+<value letter_id="T">0.000000</value>
+</alphabet_array>
+<alphabet_array>
+<value letter_id="A">0.800000</value>
+<value letter_id="C">0.000000</value>
+<value letter_id="G">0.166667</value>
+<value letter_id="T">0.033333</value>
+</alphabet_array>
+</alphabet_matrix>
+</probabilities>
+<regular_expression>
+[GA][GA][GC][GA]TATA[AT]AA
+</regular_expression>
+<contributing_sites>
+<contributing_site sequence_id="sequence_24" position="12" strand="plus" pvalue="4.51e-07" >
+<left_flank>AAGGCCAGGA</left_flank>
+<site>
+<letter_ref letter_id="G"/>
+<letter_ref letter_id="G"/>
+<letter_ref letter_id="G"/>
+<letter_ref letter_id="G"/>
+<letter_ref letter_id="T"/>
+<letter_ref letter_id="A"/>
+<letter_ref letter_id="T"/>
+<letter_ref letter_id="A"/>
+<letter_ref letter_id="A"/>
+<letter_ref letter_id="A"/>
+<letter_ref letter_id="A"/>
+</site>
+<right_flank>GCCTGAGAGC</right_flank>
+</contributing_site>
+<contributing_site sequence_id="sequence_23" position="15" strand="plus" pvalue="2.22e-06" >
+<left_flank>ATACCCAGGG</left_flank>
+<site>
+<letter_ref letter_id="A"/>
+<letter_ref letter_id="G"/>
+<letter_ref letter_id="G"/>
+<letter_ref letter_id="G"/>
+<letter_ref letter_id="T"/>
+<letter_ref letter_id="A"/>
+<letter_ref letter_id="T"/>
+<letter_ref letter_id="A"/>
+<letter_ref letter_id="A"/>
+<letter_ref letter_id="A"/>
+<letter_ref letter_id="A"/>
+</site>
+<right_flank>CCTCAGCAGC</right_flank>
+</contributing_site>
+<contributing_site sequence_id="sequence_13" position="13" strand="plus" pvalue="2.74e-06" >
+<left_flank>CCACCAGCTT</left_flank>
+<site>
+<letter_ref letter_id="G"/>
+<letter_ref letter_id="A"/>
+<letter_ref letter_id="G"/>
+<letter_ref letter_id="G"/>
+<letter_ref letter_id="T"/>
+<letter_ref letter_id="A"/>
+<letter_ref letter_id="T"/>
+<letter_ref letter_id="A"/>
+<letter_ref letter_id="A"/>
+<letter_ref letter_id="A"/>
+<letter_ref letter_id="A"/>
+</site>
+<right_flank>AGCCCTGTAC</right_flank>
+</contributing_site>
+<contributing_site sequence_id="sequence_25" position="36" strand="plus" pvalue="4.86e-06" >
+<left_flank>ACAGGCCCTG</left_flank>
+<site>
+<letter_ref letter_id="G"/>
+<letter_ref letter_id="G"/>
+<letter_ref letter_id="C"/>
+<letter_ref letter_id="A"/>
+<letter_ref letter_id="T"/>
+<letter_ref letter_id="A"/>
+<letter_ref letter_id="T"/>
+<letter_ref letter_id="A"/>
+<letter_ref letter_id="A"/>
+<letter_ref letter_id="A"/>
+<letter_ref letter_id="A"/>
+</site>
+<right_flank>GCC</right_flank>
+</contributing_site>
+<contributing_site sequence_id="sequence_21" position="7" strand="plus" pvalue="4.86e-06" >
+<left_flank>CCAAGGA</left_flank>
+<site>
+<letter_ref letter_id="G"/>
+<letter_ref letter_id="G"/>
+<letter_ref letter_id="A"/>
+<letter_ref letter_id="G"/>
+<letter_ref letter_id="T"/>
+<letter_ref letter_id="A"/>
+<letter_ref letter_id="T"/>
+<letter_ref letter_id="A"/>
+<letter_ref letter_id="A"/>
+<letter_ref letter_id="A"/>
+<letter_ref letter_id="A"/>
+</site>
+<right_flank>GCCCCACAAA</right_flank>
+</contributing_site>
+<contributing_site sequence_id="sequence_19" position="9" strand="plus" pvalue="4.86e-06" >
+<left_flank>CAGGCCCTG</left_flank>
+<site>
+<letter_ref letter_id="G"/>
+<letter_ref letter_id="G"/>
+<letter_ref letter_id="C"/>
+<letter_ref letter_id="A"/>
+<letter_ref letter_id="T"/>
+<letter_ref letter_id="A"/>
+<letter_ref letter_id="T"/>
+<letter_ref letter_id="A"/>
+<letter_ref letter_id="A"/>
+<letter_ref letter_id="A"/>
+<letter_ref letter_id="A"/>
+</site>
+<right_flank>GCCCCAGCAG</right_flank>
+</contributing_site>
+<contributing_site sequence_id="sequence_9" position="13" strand="plus" pvalue="4.86e-06" >
+<left_flank>GATTCACTGA</left_flank>
+<site>
+<letter_ref letter_id="G"/>
+<letter_ref letter_id="G"/>
+<letter_ref letter_id="C"/>
+<letter_ref letter_id="A"/>
+<letter_ref letter_id="T"/>
+<letter_ref letter_id="A"/>
+<letter_ref letter_id="T"/>
+<letter_ref letter_id="A"/>
+<letter_ref letter_id="A"/>
+<letter_ref letter_id="A"/>
+<letter_ref letter_id="A"/>
+</site>
+<right_flank>GGCCCTCTGC</right_flank>
+</contributing_site>
+<contributing_site sequence_id="sequence_28" position="32" strand="plus" pvalue="6.48e-06" >
+<left_flank>CCGGCGGGGC</left_flank>
+<site>
+<letter_ref letter_id="G"/>
+<letter_ref letter_id="G"/>
+<letter_ref letter_id="G"/>
+<letter_ref letter_id="G"/>
+<letter_ref letter_id="T"/>
+<letter_ref letter_id="A"/>
+<letter_ref letter_id="T"/>
+<letter_ref letter_id="A"/>
+<letter_ref letter_id="A"/>
+<letter_ref letter_id="A"/>
+<letter_ref letter_id="G"/>
+</site>
+<right_flank>GGGGCGG</right_flank>
+</contributing_site>
+<contributing_site sequence_id="sequence_20" position="4" strand="plus" pvalue="6.48e-06" >
+<left_flank>CAGA</left_flank>
+<site>
+<letter_ref letter_id="G"/>
+<letter_ref letter_id="G"/>
+<letter_ref letter_id="G"/>
+<letter_ref letter_id="G"/>
+<letter_ref letter_id="T"/>
+<letter_ref letter_id="A"/>
+<letter_ref letter_id="T"/>
+<letter_ref letter_id="A"/>
+<letter_ref letter_id="A"/>
+<letter_ref letter_id="A"/>
+<letter_ref letter_id="G"/>
+</site>
+<right_flank>GTTCCGACCA</right_flank>
+</contributing_site>
+<contributing_site sequence_id="sequence_12" position="18" strand="plus" pvalue="6.48e-06" >
+<left_flank>CACCAGAGCT</left_flank>
+<site>
+<letter_ref letter_id="G"/>
+<letter_ref letter_id="G"/>
+<letter_ref letter_id="G"/>
+<letter_ref letter_id="A"/>
+<letter_ref letter_id="T"/>
+<letter_ref letter_id="A"/>
+<letter_ref letter_id="T"/>
+<letter_ref letter_id="A"/>
+<letter_ref letter_id="T"/>
+<letter_ref letter_id="A"/>
+<letter_ref letter_id="A"/>
+</site>
+<right_flank>AGAAGGTTCT</right_flank>
+</contributing_site>
+<contributing_site sequence_id="sequence_15" position="21" strand="plus" pvalue="1.38e-05" >
+<left_flank>AATCACTGAG</left_flank>
+<site>
+<letter_ref letter_id="G"/>
+<letter_ref letter_id="A"/>
+<letter_ref letter_id="T"/>
+<letter_ref letter_id="G"/>
+<letter_ref letter_id="T"/>
+<letter_ref letter_id="A"/>
+<letter_ref letter_id="T"/>
+<letter_ref letter_id="A"/>
+<letter_ref letter_id="A"/>
+<letter_ref letter_id="A"/>
+<letter_ref letter_id="A"/>
+</site>
+<right_flank>GTCCCAGGGA</right_flank>
+</contributing_site>
+<contributing_site sequence_id="sequence_11" position="16" strand="plus" pvalue="1.38e-05" >
+<left_flank>CACTATTGAA</left_flank>
+<site>
+<letter_ref letter_id="G"/>
+<letter_ref letter_id="A"/>
+<letter_ref letter_id="T"/>
+<letter_ref letter_id="G"/>
+<letter_ref letter_id="T"/>
+<letter_ref letter_id="A"/>
+<letter_ref letter_id="T"/>
+<letter_ref letter_id="A"/>
+<letter_ref letter_id="A"/>
+<letter_ref letter_id="A"/>
+<letter_ref letter_id="A"/>
+</site>
+<right_flank>TTTCATTTGC</right_flank>
+</contributing_site>
+<contributing_site sequence_id="sequence_0" position="39" strand="plus" pvalue="1.41e-05" >
+<left_flank>CCTCGGGACG</left_flank>
+<site>
+<letter_ref letter_id="T"/>
+<letter_ref letter_id="G"/>
+<letter_ref letter_id="G"/>
+<letter_ref letter_id="G"/>
+<letter_ref letter_id="T"/>
+<letter_ref letter_id="A"/>
+<letter_ref letter_id="T"/>
+<letter_ref letter_id="A"/>
+<letter_ref letter_id="T"/>
+<letter_ref letter_id="A"/>
+<letter_ref letter_id="A"/>
+</site>
+<right_flank></right_flank>
+</contributing_site>
+<contributing_site sequence_id="sequence_6" position="15" strand="plus" pvalue="1.61e-05" >
+<left_flank>CCCACTACTT</left_flank>
+<site>
+<letter_ref letter_id="A"/>
+<letter_ref letter_id="G"/>
+<letter_ref letter_id="A"/>
+<letter_ref letter_id="G"/>
+<letter_ref letter_id="T"/>
+<letter_ref letter_id="A"/>
+<letter_ref letter_id="T"/>
+<letter_ref letter_id="A"/>
+<letter_ref letter_id="A"/>
+<letter_ref letter_id="A"/>
+<letter_ref letter_id="A"/>
+</site>
+<right_flank>TCATTCTGAG</right_flank>
+</contributing_site>
+<contributing_site sequence_id="sequence_22" position="2" strand="plus" pvalue="1.95e-05" >
+<left_flank>GA</left_flank>
+<site>
+<letter_ref letter_id="G"/>
+<letter_ref letter_id="A"/>
+<letter_ref letter_id="C"/>
+<letter_ref letter_id="A"/>
+<letter_ref letter_id="T"/>
+<letter_ref letter_id="A"/>
+<letter_ref letter_id="T"/>
+<letter_ref letter_id="A"/>
+<letter_ref letter_id="A"/>
+<letter_ref letter_id="A"/>
+<letter_ref letter_id="A"/>
+</site>
+<right_flank>GCCAACATCC</right_flank>
+</contributing_site>
+<contributing_site sequence_id="sequence_14" position="17" strand="plus" pvalue="1.95e-05" >
+<left_flank>CCCACCAGCA</left_flank>
+<site>
+<letter_ref letter_id="A"/>
+<letter_ref letter_id="G"/>
+<letter_ref letter_id="G"/>
+<letter_ref letter_id="A"/>
+<letter_ref letter_id="T"/>
+<letter_ref letter_id="A"/>
+<letter_ref letter_id="T"/>
+<letter_ref letter_id="A"/>
+<letter_ref letter_id="T"/>
+<letter_ref letter_id="A"/>
+<letter_ref letter_id="A"/>
+</site>
+<right_flank>AAGCTCAGGA</right_flank>
+</contributing_site>
+<contributing_site sequence_id="sequence_18" position="37" strand="plus" pvalue="2.16e-05" >
+<left_flank>CGTGGTCGCG</left_flank>
+<site>
+<letter_ref letter_id="G"/>
+<letter_ref letter_id="G"/>
+<letter_ref letter_id="G"/>
+<letter_ref letter_id="G"/>
+<letter_ref letter_id="T"/>
+<letter_ref letter_id="A"/>
+<letter_ref letter_id="T"/>
+<letter_ref letter_id="A"/>
+<letter_ref letter_id="A"/>
+<letter_ref letter_id="C"/>
+<letter_ref letter_id="A"/>
+</site>
+<right_flank>GC</right_flank>
+</contributing_site>
+<contributing_site sequence_id="sequence_29" position="30" strand="plus" pvalue="3.04e-05" >
+<left_flank>GCTGCCGGTG</left_flank>
+<site>
+<letter_ref letter_id="A"/>
+<letter_ref letter_id="G"/>
+<letter_ref letter_id="C"/>
+<letter_ref letter_id="G"/>
+<letter_ref letter_id="T"/>
+<letter_ref letter_id="A"/>
+<letter_ref letter_id="T"/>
+<letter_ref letter_id="A"/>
+<letter_ref letter_id="A"/>
+<letter_ref letter_id="A"/>
+<letter_ref letter_id="G"/>
+</site>
+<right_flank>GCCCTGGCG</right_flank>
+</contributing_site>
+<contributing_site sequence_id="sequence_4" position="12" strand="plus" pvalue="3.04e-05" >
+<left_flank>CAGGTCTAAG</left_flank>
+<site>
+<letter_ref letter_id="A"/>
+<letter_ref letter_id="G"/>
+<letter_ref letter_id="C"/>
+<letter_ref letter_id="A"/>
+<letter_ref letter_id="T"/>
+<letter_ref letter_id="A"/>
+<letter_ref letter_id="T"/>
+<letter_ref letter_id="A"/>
+<letter_ref letter_id="T"/>
+<letter_ref letter_id="A"/>
+<letter_ref letter_id="A"/>
+</site>
+<right_flank>CTTGGAGTCC</right_flank>
+</contributing_site>
+<contributing_site sequence_id="sequence_5" position="0" strand="plus" pvalue="3.67e-05" >
+<left_flank></left_flank>
+<site>
+<letter_ref letter_id="A"/>
+<letter_ref letter_id="A"/>
+<letter_ref letter_id="C"/>
+<letter_ref letter_id="G"/>
+<letter_ref letter_id="T"/>
+<letter_ref letter_id="A"/>
+<letter_ref letter_id="T"/>
+<letter_ref letter_id="A"/>
+<letter_ref letter_id="T"/>
+<letter_ref letter_id="A"/>
+<letter_ref letter_id="A"/>
+</site>
+<right_flank>ATGGTCCTGT</right_flank>
+</contributing_site>
+<contributing_site sequence_id="sequence_1" position="27" strand="plus" pvalue="3.93e-05" >
+<left_flank>AGTCACAAGT</left_flank>
+<site>
+<letter_ref letter_id="G"/>
+<letter_ref letter_id="A"/>
+<letter_ref letter_id="G"/>
+<letter_ref letter_id="T"/>
+<letter_ref letter_id="T"/>
+<letter_ref letter_id="A"/>
+<letter_ref letter_id="T"/>
+<letter_ref letter_id="A"/>
+<letter_ref letter_id="A"/>
+<letter_ref letter_id="A"/>
+<letter_ref letter_id="A"/>
+</site>
+<right_flank>GGGTCGCACG</right_flank>
+</contributing_site>
+<contributing_site sequence_id="sequence_7" position="4" strand="plus" pvalue="5.65e-05" >
+<left_flank>TCAG</left_flank>
+<site>
+<letter_ref letter_id="A"/>
+<letter_ref letter_id="G"/>
+<letter_ref letter_id="T"/>
+<letter_ref letter_id="A"/>
+<letter_ref letter_id="T"/>
+<letter_ref letter_id="A"/>
+<letter_ref letter_id="T"/>
+<letter_ref letter_id="A"/>
+<letter_ref letter_id="T"/>
+<letter_ref letter_id="A"/>
+<letter_ref letter_id="A"/>
+</site>
+<right_flank>ATGTTCCTGT</right_flank>
+</contributing_site>
+<contributing_site sequence_id="sequence_3" position="14" strand="plus" pvalue="6.24e-05" >
+<left_flank>CCCAGGTTTC</left_flank>
+<site>
+<letter_ref letter_id="T"/>
+<letter_ref letter_id="G"/>
+<letter_ref letter_id="A"/>
+<letter_ref letter_id="G"/>
+<letter_ref letter_id="T"/>
+<letter_ref letter_id="A"/>
+<letter_ref letter_id="T"/>
+<letter_ref letter_id="A"/>
+<letter_ref letter_id="T"/>
+<letter_ref letter_id="A"/>
+<letter_ref letter_id="A"/>
+</site>
+<right_flank>TCGCCGCACC</right_flank>
+</contributing_site>
+<contributing_site sequence_id="sequence_16" position="22" strand="plus" pvalue="7.15e-05" >
+<left_flank>AGTTTCAGTT</left_flank>
+<site>
+<letter_ref letter_id="G"/>
+<letter_ref letter_id="G"/>
+<letter_ref letter_id="C"/>
+<letter_ref letter_id="A"/>
+<letter_ref letter_id="T"/>
+<letter_ref letter_id="C"/>
+<letter_ref letter_id="T"/>
+<letter_ref letter_id="A"/>
+<letter_ref letter_id="A"/>
+<letter_ref letter_id="A"/>
+<letter_ref letter_id="A"/>
+</site>
+<right_flank>attatataac</right_flank>
+</contributing_site>
+<contributing_site sequence_id="sequence_27" position="36" strand="plus" pvalue="1.39e-04" >
+<left_flank>TGCCTGGGTC</left_flank>
+<site>
+<letter_ref letter_id="C"/>
+<letter_ref letter_id="A"/>
+<letter_ref letter_id="G"/>
+<letter_ref letter_id="G"/>
+<letter_ref letter_id="T"/>
+<letter_ref letter_id="A"/>
+<letter_ref letter_id="T"/>
+<letter_ref letter_id="A"/>
+<letter_ref letter_id="A"/>
+<letter_ref letter_id="A"/>
+<letter_ref letter_id="G"/>
+</site>
+<right_flank>GCT</right_flank>
+</contributing_site>
+<contributing_site sequence_id="sequence_26" position="37" strand="plus" pvalue="1.39e-04" >
+<left_flank>TGCCTGGGCC</left_flank>
+<site>
+<letter_ref letter_id="C"/>
+<letter_ref letter_id="A"/>
+<letter_ref letter_id="G"/>
+<letter_ref letter_id="G"/>
+<letter_ref letter_id="T"/>
+<letter_ref letter_id="A"/>
+<letter_ref letter_id="T"/>
+<letter_ref letter_id="A"/>
+<letter_ref letter_id="A"/>
+<letter_ref letter_id="A"/>
+<letter_ref letter_id="G"/>
+</site>
+<right_flank>GC</right_flank>
+</contributing_site>
+<contributing_site sequence_id="sequence_17" position="2" strand="plus" pvalue="4.81e-04" >
+<left_flank>ga</left_flank>
+<site>
+<letter_ref letter_id="T"/>
+<letter_ref letter_id="G"/>
+<letter_ref letter_id="G"/>
+<letter_ref letter_id="T"/>
+<letter_ref letter_id="T"/>
+<letter_ref letter_id="T"/>
+<letter_ref letter_id="T"/>
+<letter_ref letter_id="A"/>
+<letter_ref letter_id="T"/>
+<letter_ref letter_id="A"/>
+<letter_ref letter_id="A"/>
+</site>
+<right_flank>ggggcctcac</right_flank>
+</contributing_site>
+<contributing_site sequence_id="sequence_8" position="13" strand="plus" pvalue="8.57e-04" >
+<left_flank>TATAACTCAG</left_flank>
+<site>
+<letter_ref letter_id="G"/>
+<letter_ref letter_id="T"/>
+<letter_ref letter_id="T"/>
+<letter_ref letter_id="G"/>
+<letter_ref letter_id="G"/>
+<letter_ref letter_id="A"/>
+<letter_ref letter_id="T"/>
+<letter_ref letter_id="A"/>
+<letter_ref letter_id="A"/>
+<letter_ref letter_id="A"/>
+<letter_ref letter_id="A"/>
+</site>
+<right_flank>TAATTTGTAC</right_flank>
+</contributing_site>
+<contributing_site sequence_id="sequence_10" position="7" strand="plus" pvalue="1.47e-03" >
+<left_flank>aaactta</left_flank>
+<site>
+<letter_ref letter_id="A"/>
+<letter_ref letter_id="A"/>
+<letter_ref letter_id="A"/>
+<letter_ref letter_id="C"/>
+<letter_ref letter_id="T"/>
+<letter_ref letter_id="C"/>
+<letter_ref letter_id="T"/>
+<letter_ref letter_id="A"/>
+<letter_ref letter_id="T"/>
+<letter_ref letter_id="A"/>
+<letter_ref letter_id="A"/>
+</site>
+<right_flank>acttaaaact</right_flank>
+</contributing_site>
+<contributing_site sequence_id="sequence_2" position="26" strand="plus" pvalue="2.64e-03" >
+<left_flank>GGTGGGGGTG</left_flank>
+<site>
+<letter_ref letter_id="G"/>
+<letter_ref letter_id="G"/>
+<letter_ref letter_id="G"/>
+<letter_ref letter_id="G"/>
+<letter_ref letter_id="T"/>
+<letter_ref letter_id="T"/>
+<letter_ref letter_id="T"/>
+<letter_ref letter_id="C"/>
+<letter_ref letter_id="A"/>
+<letter_ref letter_id="C"/>
+<letter_ref letter_id="T"/>
+</site>
+<right_flank>GGTCCACTAT</right_flank>
+</contributing_site>
+</contributing_sites>
+</motif>
 </motifs>
 <scanned_sites_summary p_thresh="0.0001">
 <scanned_sites sequence_id="sequence_0" pvalue="5.63e-04" num_sites="1"><scanned_site motif_id="motif_1" strand="plus" position="39" pvalue="1.41e-05"/>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test-data/streme_input_neg2.fasta	Mon Jul 14 21:33:56 2025 +0000
@@ -0,0 +1,66 @@
+>chr21_19617074_19617124_+
+AAAAATTATTACTAGGGAGGGGGCCGGAAAAACCTCGGGACGTGGGTATATAA
+>chr21_26934381_26934431_+
+GCGCCTGGTCGGTTATGAGTCACAAGTGAGTTTTCCmATAAAAGGGTCGCACGTT
+>chr21_28217753_28217803_-
+CAAAGGGGAGGAGTGmGGGTGGGGGTGGGGGTTTCACTGGTCCACTATAAA
+>chr21_31710037_31710087_-
+AACACCCAGGTTTCTGAGTATATAATCGCCGCACCAAAGAATTTAATTTT
+>chr21_31744582_31744632_-
+CCCAGGTCTAAGAGCATATATAmACTTGGAGTCCAGACTATGACATTCAAA
+>chr21_31768316_31768366_+
+AACGTATATAAATGGTCCTGTCCAGATGTGGCATGCAmAACTCAGAATCTT
+>chr21_31914206_31914256_-
+TGACACCCACTACTTAGAGTATAAAmATCATTCTGAGAAGTTAGAGACACC
+>chr21_31933633_31933683_-
+TCAGAGTATATATAAATGTTCCTGTCCAGTCACAAAGTCACCAAACTGACCT
+>chr21_31962741_31962791_-
+ACATATAACTCAGGTTGGATAAAATAATTTGTATCAGmCAAATCAGGAGAGTCAA
+>chr21_31964683_31964733_+
+TCTGATTCACTGAGGCATATAAAAGGCCCTCTGCGGAGAmAGTGTCCATAC
+>chr21_31973364_31973414_+
+aaacttaaaactctataaacttaaaactCTAGAATCCTGCTATAC
+>chr21_31992870_31992920_+
+CTCATACACTATTGAAGATGTATAAAATTTCATTTGmGATGGTGACATT
+>chr21_32185595_32185645_-
+TCACCACCCACCAmAGCTGGGATATATAAAGAAGGTTCTGAGACTAGGAA
+>chr21_32202076_32202126_-
+TGCCCACCAGCTATmGTGAGGTATAAAAAGCCCTGTACGGGAAGAGACCTTCAT
+>chr21_32253899_32253949_-
+AGCCCCACCCACCAGCAAGGATATATAAAAGCTCAGGAGTCTGGAGTGAC
+>chr21_32410820_32410870_-
+TCTACCCCACTAATCACTGAGGATGTATAAAAGTCCCAGGGAAGCTGGTG
+>chr21_36411748_36411798_-
+ATAGTTCTGTATAAmGAGTTTCAGTTGGCATCtaaaaattatataactttattt
+>chr21_37838750_37838800_-
+gatggttttataaggggcctcaccctcggctcagccctcattcttctcct
+>chr21_45705687_45705737_+
+CCGGGGCGGAGCGGCCTTTGCTCTTTGCGTGGTCGCGGGGGTATAACAGC
+>chr21_45971413_45971463_-
+CAGGCCCTGGGCATATAAAAGCCCCAGCAGmCCAACAGGctcacacacaca
+>chr21_45978668_45978718_-
+CAGAGGGGTATAAAGGTTCCGACCACTCAGAGGCCTGGCACGAtcactca
+>chr21_45993530_45993580_+
+CCAAGGAGGAGTATAAAAGCCCCACAAACCCGAGCACCTCACTCTCGC
+>chr21_46020421_46020471_+
+GAGACATATAAAAGCCAACATCCCTGAGCACCTAAACGGactcactc
+>chr21_46031920_46031970_+
+GGAAAATACCCAGGGAGGGTATAAATCAGCAGCCAGGGCACACAAAC
+>chr21_46046964_46047014_+
+ACAAGGCCAGGAGGGGTATAAAACTGAGAGCCCCAAGAACctcacaca
+>chr21_46057197_46057247_+
+ATTGCTGAGTCTCCTGCTGGGAAAACACAGGCCCTGGGCATATAAAAGCC
+>chr21_46086869_46086919_-
+GACGTGTGCTTCTGTGCTGTGGGGATGCCTGGGCCCAGGTATAAAGGC
+>chr21_46102103_46102153_-
+AGGTGTGCTTCTGTGCTGTGGGGATGCCTGGGTCCAGGTATAAAGGCT
+>chr21_47517957_47518007_+
+CCTGGCGGCGGGGCGGGTGGCCGGCGGGGCGGGGTATAAAGGGGGCGG
+>chr21_47517957_47518007_+
+CCTGGCGGCGGGGCGGGTCGCCGGCGGGGCGGGGTATAAAGGGGGCGG
+>chr21_47517957_47518007_+
+CCTGGCGGCGGGGCGGGTCAGGCCGGCGGCGGGGTATAAAGGGGGCGG
+>chr21_47575506_47575556_-
+TGAGAAGCCGGTGGGGAGGTGCTGCGTGAGCGTATAAAGGCCCTGGCG
+>chr21_47575506_47575556_-
+TGAGAAGCCGGTGGGAGmGTGCTGCCGGTGAGCGTATAAAGGCCCTGGCG
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test-data/streme_input_pos.fasta	Mon Jul 14 21:33:56 2025 +0000
@@ -0,0 +1,66 @@
+>chr21_19617074_19617124_+
+AAAAATTATTACTAGGGAGGGGGCCGGAACCTCGGGACGTGGGTATATAA
+>chr21_26934381_26934431_+
+GCGCCTGGTCGGTTATGAGTCACAAGTGAGTTATAAAAGGGTCGCACGTT
+>chr21_28217753_28217803_-
+CAAAGGGGAGGAGTGGGGTGGGGGTGGGGGTTTCACTGGTCCTATAAA
+>chr21_31710037_31710087_-
+AACACCCAGGTTTCTGAGTATATAATCGCCGCACCAAAGAATTTAATTTT
+>chr21_31744582_31744632_-
+CCCAGGTCTAAGAGCATATATAACTTGGAGTCCAGACTATGACATTCAAA
+>chr21_31768316_31768366_+
+AACGTATATAAATGGTCCTGTCCAGATGTG
+>chr21_31914206_31914256_-
+TGACACCCACTACTTAGAGTATAAAATCATTCTGAGAAGTTAGAGACACC
+>chr21_31933633_31933683_-
+TCAGAGTATATATAAATGTTCCTGTCCAGTCACAGTCACCAATGACCT
+>chr21_31962741_31962791_-
+ACATATAACTCAGGTTGGATAAAATAATTTGTACAAATCAGGAGAGTCAA
+>chr21_31964683_31964733_+
+TCTGATTCACTGAGGCATATAAAAGGCCCTCTGCGGAGAAGTTAC
+>chr21_31973364_31973414_+
+aaacttaaaactctataaacttaaaactCTAGAATCTGATCCTGCTATAC
+>chr21_31992870_31992920_+
+CTCATACACTATTGAAGATGTATAAAATTTCATTTGCAGATGGTGACATT
+>chr21_32185595_32185645_-
+TCACCACCCACCAGAGCTGGGATATATAAAGAAGGTTCTAGGAA
+>chr21_32202076_32202126_-
+TGCCCACCAGCTTGAGGTATAAAAAGCCCTGTACGGGAAGAGACCTTCAT
+>chr21_32253899_32253949_-
+AGCCCCACCCACCAGCAAGGATATATAAAAGCTCAGGAGTCTGGAGTGAC
+>chr21_32410820_32410870_-
+TCTACCCCACTAATCACTGAGGATGTATAAAAGTCCCAGGGAAGCTGGTG
+>chr21_36411748_36411798_-
+ATAGTTCTGTATAGTTTCAGTTGGCATCtaaaaattatataactttattt
+>chr21_37838750_37838800_-
+gatggttttataaggggcctcaccctcggctcagccctcattcttctcct
+>chr21_45705687_45705737_+
+CCGGGGCGGAGCGGCCTTTGCTCTTTGCGTGGTCGGGGTATAACAGC
+>chr21_45971413_45971463_-
+CAGGCCCTGGGCATATAAAAGCCCCAGCAGCCAACAGGctcacacacaca
+>chr21_45978668_45978718_-
+CAGAGGGGTATAAAGGTTCCGACCACTCCTGGCACGAtcactca
+>chr21_45993530_45993580_+
+CCAAGGAGGAGTATAAAAGCCCCACAAACCCGAGCACCTCACTCACTCGC
+>chr21_46020421_46020471_+
+GAGACATATAAAAGCCAACATCCCTGAGCACCTAACACACGGactcactc
+>chr21_46031920_46031970_+
+GGAAAATACCCAGGGAGGGTATAAAACCTCAGCAGCCAGGGCACACAAAC
+>chr21_46046964_46047014_+
+ACAAGGCCAGGAGGGGTATAAAAGCCTGAGAGCCCCAAGAACctcacaca
+>chr21_46057197_46057247_+
+ATTGCTGAGTCTCCTGCTGGGAAAACACAGGCCCTGGGCATATAAAAGCC
+>chr21_46086869_46086919_-
+GACAGGTGTGCTTCTGTGCTGTGGGGATGCCTGGGCCCAGGTATAAAGGC
+>chr21_46102103_46102153_-
+AGGTGTGTGCTTCTGTGCTGTGGGGATGCCTGGGTCCAGGTATAAAGGCT
+>chr21_47517957_47518007_+
+CCTGGCGGCGGGGCGGGTCAGGCCGGCGGGGCGGGGTATAAAGGGGGCGG
+>chr21_47517957_47518007_+
+CCTGGCGGCGGGGCGGGTCAGGCGGGGCGGGGTATAAAGGGGGCGG
+>chr21_47517957_47518007_+
+CCTGGCGGCGGGGCGGGTCAGGCCGGCGGGGTATAAAGGGGGCGG
+>chr21_47575506_47575556_-
+TGAGAAGCCGGTGGGGAGGTGCTGCCGGTGAGCGTATAAAGGCCCTGGCG
+>chr21_47575506_47575556_-
+TGAGAAGCCGGTGGGGAGGTGCTGCCGGTGAGCGTATAAAGGCCCTGGCG
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test-data/streme_input_pos2.fasta	Mon Jul 14 21:33:56 2025 +0000
@@ -0,0 +1,66 @@
+>chr21_19617074_19617124_+
+AAAAATTATTACTAGGGAGGGGGCmGGAACCTCGGGACGTGGGTmATATAA
+>chr21_26934381_26934431_+
+GCGCCTGGTCGGTTATGAGTCACAAGTGAGTTATAAAAGGGTCGCACGTT
+>chr21_28217753_28217803_-
+CAAAGGGGAGGAGTGGGGTGGGGGTGGGGGTTTCACTGGTmCACTATAAA
+>chr21_31710037_31710087_-
+AACACCCAGGTTTCTGAGTATATAATCGCCGCACCAAAGAATTTAATTTTTT
+>chr21_31744582_31744632_-
+CCmAGGTCTAAGAGCATATATTAACTTGGAGTCCAGACTATGACATTCAAA
+>chr21_31768316_31768366_+
+AACGTATATAAATGGTCCTGTCCAGATGTGGCATGCAAACTmAGAATCTT
+>chr21_31914206_31914256_-
+TGACACCCACTACTTAGAGTATAAAATCATTCTGAGAAGTTAGAGA
+>chr21_31933633_31933683_-
+TCAGAGTATATATAAATGTTCCTGTCCAGTCACAGTCACCAAACTGACCT
+>chr21_31962741_31962791_-
+ACATATAACTCAGGTTGGATAAAATAATTTGTACAAATCAGG
+>chr21_31964683_31964733_+
+TCTGATTCACTGAGGCATATAAAAGGCCCTCTGCGGAGAAGTGTCCATAC
+>chr21_31973364_31973414_+
+aaacttaaaactctataaacttaaaactCTAGAATCTGATCCTGCTATAC
+>chr21_31992870_31992920_+
+CTCATACACTATTGAAGATGTATAAAATTTCATTTGCAGATGGTGACATT
+>chr21_32185595_32185645_-
+TCACCACCCACCAGAGCTGGGATATATAAAGAAGGTTCTGAGACTAGGAA
+>chr21_32202076_32202126_-
+TGCCCACCAGCTTGAGGTATAAAAAGCCCTGTACGGGAAGAGACCTTCAT
+>chr21_32253899_32253949_-
+AGCCCCACCCACCAGCAAGGATATATAAAAGCTCAGGAGTCTGGAGTGAC
+>chr21_32410820_32410870_-
+TCTACCCCACTAATCACTGAGGATGTATAAAAGTCCCAGGGAAGCTGGTG
+>chr21_36411748_36411798_-
+ATAGTTCTGTATAGTTTCAGTTGGCATCtaaaaattatataactttattt
+>chr21_37838750_37838800_-
+gatggttttataaggggcctcaccctcggctcagccctcattcttctcct
+>chr21_45705687_45705737_+
+CCGGGGCGGAGCGGCCTTTGCTCTTTGCGTGGTCGCGGGmGGTATAACAGC
+>chr21_45971413_45971463_-
+CAGGCCCTGGGCATATAAAAGCCCCAGCAGCCAACAGGctcacacacaca
+>chr21_45978668_45978718_-
+CAGAGGGGTATAAAGGTTCCGACCACTCAGAGGCCTGGCACGAtcactca
+>chr21_45993530_45993580_+
+CCAAGGAGGAGTATAAAAGCCCCACAAACCCGAGCACCmTCACTCACTCGC
+>chr21_46020421_46020471_+
+GAGACATATAAAAGCCAACATCCCTGAGCACCTAACACACGGactcactc
+>chr21_46031920_46031970_+
+GGAAAATACCCAGGGAGGGTATAAAACCTCAGCAGCCAGGGCACACAAAC
+>chr21_46046964_46047014_+
+ACAAGGCCAGGAGGGGTATAAAAGCCTGAGAGCCCCAAGAACctcacaca
+>chr21_46057197_46057247_+
+ATTGCTGAGTCTCCTGCTGGGAAAACACAGGCCCTGGGCAT
+>chr21_46086869_46086919_-
+GACAGGTGTGCTTCTGTGCTGTGGGGATGCCTGGGCCCAGGTATAAAGGC
+>chr21_46102103_46102153_-
+AGGTGTGTGCTTCTGTGCTGTGGGGATGCCTCCAGGTATAAAGGCT
+>chr21_47517957_47518007_+
+CCTGGCGGCGGGGCGGGTCAGGCCGGCGGGGCGGGGTATAAAGGGGGmGG
+>chr21_47517957_47518007_+
+CCTGGCGGCGmGGGCGGGTCAGGCCGGCGGGmGCGGGGTATAAAGGGGGCGG
+>chr21_47517957_47518007_+
+CCTGGCGGCGGGmGCGGGTCAGGCCGGCGGGGCGGGGTATAAAGGGGmGCGG
+>chr21_47575506_47575556_-
+TGAGAAGCCGGTGGGGAGGTGmTGCCGGTGAGCmGTATAAAGGCCCTGGCG
+>chr21_47575506_47575556_-
+TGAGAAGCmGGTGGGGAGGTGCTGCCGGTGAGCGTATAAAGmGCCCTGGCG
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test-data/streme_output_test1.html	Mon Jul 14 21:33:56 2025 +0000
@@ -0,0 +1,39 @@
+        "train_negatives": {
+          "from": "shuffled",
+          "count": 33,
+          "positions": 1597
+        },
+        "test_positives": {
+          "count": 0,
+          "positions": 0
+        },
+        "test_negatives": {
+          "count": 0,
+          "positions": 0
+        },
+        "sequence_db": {
+          "freqs": [0.245, 0.255, 0.255, 0.245]
+        },
+        "motifs": [
+          {
+            "db": 0,
+            "id": "1-CTTTTATAYRCCY",
+            "alt": "STREME-1",
+            "width": 13,
+            "initial_width": 8,
+            "seed": "CTTTTATATGCCT",
+            "score_threshold": 10.1927,
+            "npassing": 18,
+            "train_pos_count": 18,
+            "train_neg_count": 0,
+            "train_log_pvalue": -6.81978,
+            "train_pvalue": "1.5e-007",
+            "train_dtc": -1.0,
+            "train_bernoulli": -1,
+            "test_pos_count": 0,
+            "test_neg_count": 0,
+            "test_log_pvalue": 0,
+            "test_pvalue": "1.0e+000",
+            "test_log_evalue": 0.69897,
+            "test_evalue": "5.0e+000",
+            "test_dtc": -1.0,
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test-data/streme_output_test1.txt	Mon Jul 14 21:33:56 2025 +0000
@@ -0,0 +1,93 @@
+********************************************************************************
+STREME - Sensitive, Thorough, Rapid, Enriched Motif Elicitation
+********************************************************************************
+MEME version 5.5.8 (Release date: Thu May 15 15:01:46 2025 -0700)
+
+For further information on how to interpret these results please access https://meme-suite.org/meme.
+To get a copy of the MEME Suite software please access https://meme-suite.org.
+
+********************************************************************************
+
+
+********************************************************************************
+REFERENCE
+********************************************************************************
+If you use this program in your research, please cite:
+
+Timothy L. Bailey,
+"STREME: accurate and versatile sequence motif discovery",
+Bioinformatics, Mar. 24, 2021.
+********************************************************************************
+
+
+ALPHABET= ACGT
+
+strands: + -
+
+Background letter frequencies
+A 0.244 C 0.256 G 0.256 T 0.244 
+
+MOTIF 1-CTTTTATAYRCCY STREME-1
+letter-probability matrix: alength= 4 w= 13 nsites= 18 S= 1.5e-007
+ 0.072963 0.851476 0.002598 0.072963
+ 0.072963 0.145128 0.002598 0.779311
+ 0.002486 0.002598 0.073075 0.921841
+ 0.002486 0.002598 0.002598 0.992318
+ 0.002486 0.002598 0.002598 0.992318
+ 0.992318 0.002598 0.002598 0.002486
+ 0.002486 0.002598 0.073075 0.921841
+ 0.992318 0.002598 0.002598 0.002486
+ 0.002486 0.497514 0.002598 0.497402
+ 0.284394 0.143552 0.499090 0.072963
+ 0.002486 0.710522 0.002598 0.284394
+ 0.002486 0.779422 0.073075 0.145017
+ 0.072963 0.428613 0.073075 0.425349
+
+MOTIF 2-CCCCACCRSC STREME-2
+letter-probability matrix: alength= 4 w= 10 nsites= 12 S= 7.2e-005
+ 0.139001 0.787776 0.070814 0.002409
+ 0.070705 0.924368 0.002517 0.002409
+ 0.002409 0.924368 0.070814 0.002409
+ 0.002409 0.992664 0.002517 0.002409
+ 0.716267 0.002517 0.210510 0.070705
+ 0.002409 0.856072 0.070814 0.070705
+ 0.208825 0.786248 0.002517 0.002409
+ 0.343890 0.030359 0.555046 0.070705
+ 0.070705 0.376471 0.550414 0.002409
+ 0.208825 0.786248 0.002517 0.002409
+
+MOTIF 3-RCAGAAKCA STREME-3
+letter-probability matrix: alength= 4 w= 9 nsites= 10 S= 4.4e-004
+ 0.595835 0.003626 0.397069 0.003470
+ 0.003470 0.694352 0.298708 0.003470
+ 0.792557 0.003626 0.101987 0.101831
+ 0.003470 0.101987 0.891074 0.003470
+ 0.694196 0.003626 0.298708 0.003470
+ 0.694196 0.298708 0.003626 0.003470
+ 0.003470 0.101987 0.300909 0.593635
+ 0.101831 0.792713 0.003626 0.101831
+ 0.989279 0.003626 0.003626 0.003470
+
+MOTIF 4-RAGTTATAAA STREME-4
+letter-probability matrix: alength= 4 w= 10 nsites= 8 S= 2.4e-003
+ 0.333562 0.113112 0.440386 0.112939
+ 0.988110 0.004021 0.004021 0.003848
+ 0.003848 0.004021 0.879191 0.112939
+ 0.003848 0.004021 0.222204 0.769927
+ 0.112939 0.004021 0.004021 0.879018
+ 0.769927 0.004021 0.113112 0.112939
+ 0.003848 0.004021 0.113112 0.879018
+ 0.988110 0.004021 0.004021 0.003848
+ 0.549304 0.113112 0.113112 0.224471
+ 0.769927 0.004021 0.113112 0.112939
+
+MOTIF 5-AACCTCGG STREME-5
+letter-probability matrix: alength= 4 w= 8 nsites= 7 S= 5.5e-003
+ 0.973700 0.008894 0.008894 0.008511
+ 0.732403 0.250191 0.008894 0.008511
+ 0.008511 0.974083 0.008894 0.008511
+ 0.008511 0.974083 0.008894 0.008511
+ 0.008511 0.008894 0.008894 0.973700
+ 0.008511 0.732786 0.250191 0.008511
+ 0.249809 0.008894 0.732786 0.008511
+ 0.008511 0.008894 0.974083 0.008511
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test-data/streme_output_test1.xml	Mon Jul 14 21:33:56 2025 +0000
@@ -0,0 +1,26 @@
+      <letter id="A" symbol="A" complement="T" name="Adenine" colour="CC0000"/>
+      <letter id="C" symbol="C" complement="G" name="Cytosine" colour="0000CC"/>
+      <letter id="G" symbol="G" complement="C" name="Guanine" colour="FFB300"/>
+      <letter id="T" symbol="T" aliases="U" complement="A" name="Thymine" colour="008000"/>
+      <letter id="N" symbol="N" aliases="X." equals="ACGT" name="Any base"/>
+      <letter id="V" symbol="V" equals="ACG" name="Not T"/>
+      <letter id="H" symbol="H" equals="ACT" name="Not G"/>
+      <letter id="D" symbol="D" equals="AGT" name="Not C"/>
+      <letter id="B" symbol="B" equals="CGT" name="Not A"/>
+      <letter id="M" symbol="M" equals="AC" name="Amino"/>
+      <letter id="R" symbol="R" equals="AG" name="Purine"/>
+      <letter id="W" symbol="W" equals="AT" name="Weak"/>
+      <letter id="S" symbol="S" equals="CG" name="Strong"/>
+      <letter id="Y" symbol="Y" equals="CT" name="Pyrimidine"/>
+      <letter id="K" symbol="K" equals="GT" name="Keto"/>
+    </alphabet>
+    <strands>both</strands>
+    <sequence_db A="0.245" C="0.255" G="0.255" T="0.245"/>
+    <background_frequencies source="--negatives--" order="2">
+      <alphabet_array>
+        <value letter_id="A">0.244</value>
+        <value letter_id="C">0.256</value>
+        <value letter_id="G">0.256</value>
+        <value letter_id="T">0.244</value>
+      </alphabet_array>
+    </background_frequencies>
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test-data/streme_output_test2.html	Mon Jul 14 21:33:56 2025 +0000
@@ -0,0 +1,43 @@
+        "train_negatives": {
+          "from": "shuffled",
+          "count": 33,
+          "positions": 1597
+        },
+        "test_positives": {
+          "count": 0,
+          "positions": 0
+        },
+        "test_negatives": {
+          "count": 0,
+          "positions": 0
+        },
+        "sequence_db": {
+          "freqs": [
+            0.218, 0.24, 0.24, 0.218, 0.0266, 0.0125, 0, 0.00313, 0, 0,
+            0.0266, 0, 0, 0, 0.0125, 0.00313
+          ]
+        },
+        "motifs": [
+          {
+            "db": 0,
+            "id": "1-GTATAAAAGC",
+            "alt": "STREME-1",
+            "width": 10,
+            "initial_width": 5,
+            "seed": "GTATAAAGGC",
+            "score_threshold": 9.73039,
+            "npassing": 28,
+            "train_pos_count": 28,
+            "train_neg_count": 0,
+            "train_log_pvalue": -13.1578,
+            "train_pvalue": "7.0e-014",
+            "train_dtc": -1.0,
+            "train_bernoulli": -1,
+            "test_pos_count": 0,
+            "test_neg_count": 0,
+            "test_log_pvalue": 0,
+            "test_pvalue": "1.0e+000",
+            "test_log_evalue": 0.477121,
+            "test_evalue": "3.0e+000",
+            "test_dtc": -1.0,
+            "test_bernoulli": -1,
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test-data/streme_output_test2.txt	Mon Jul 14 21:33:56 2025 +0000
@@ -0,0 +1,78 @@
+********************************************************************************
+STREME - Sensitive, Thorough, Rapid, Enriched Motif Elicitation
+********************************************************************************
+MEME version 5.5.8 (Release date: Thu May 15 15:01:46 2025 -0700)
+
+For further information on how to interpret these results please access https://meme-suite.org/meme.
+To get a copy of the MEME Suite software please access https://meme-suite.org.
+
+********************************************************************************
+
+
+********************************************************************************
+REFERENCE
+********************************************************************************
+If you use this program in your research, please cite:
+
+Timothy L. Bailey,
+"STREME: accurate and versatile sequence motif discovery",
+Bioinformatics, Mar. 24, 2021.
+********************************************************************************
+
+
+********************************************************************************
+ALPHABET "DNA with covalent modifications" DNA-LIKE
+********************************************************************************
+A "Adenine" 8510A8 ~ T "Thymine" A89610
+C "Cytosine" A50026 ~ G "Guanine" 313695
+a "N6-methyladenine" 8510A8 ~ t "Thymine_lowercase" 756BB1
+c "5-Carboxylcytosine" FEE090 ~ 4 "Guanine:5-Carboxylcytosine" E0F3F8
+f "5-Formylcytosine" FDAE61 ~ 3 "Guanine:5-Formylcytosine" ABD9E9
+g "modified_g" 00897B ~ 5 "cytosine_lowercase" 53698A
+h "5-Hydroxymethylcytosine" F46D43 ~ 2 "Guanine:5-Hydroxymethylcytosine" 74ADD1
+m "5-Methylcytosine" D73027 ~ 1 "Guanine:5-Methylcytosine" 4575B4
+? = ACGTacfghmt12345
+********************************************************************************
+
+strands: + -
+
+Background letter frequencies
+A 0.218 C 0.24 G 0.24 T 0.218 a 0.0266 c 0.0125 f 1.96e-05 g 0.00315 h 1.96e-05 m 1.96e-05 t 0.0266 1 1.96e-05 2 1.96e-05 3 1.96e-05 4 0.0125 5 0.00315 
+
+MOTIF 1-GTATAAAAGC STREME-1
+letter-probability matrix: alength= 16 w= 10 nsites= 28 S= 7.0e-014
+ 0.344606 0.001172 0.618858 0.034950 0.000130 0.000061 0.000000 0.000015 0.000000 0.000000 0.000130 0.000000 0.000000 0.000000 0.000061 0.000015
+ 0.001065 0.001172 0.001172 0.996177 0.000130 0.000061 0.000000 0.000015 0.000000 0.000000 0.000130 0.000000 0.000000 0.000000 0.000061 0.000015
+ 0.996177 0.001172 0.001172 0.001065 0.000130 0.000061 0.000000 0.000015 0.000000 0.000000 0.000130 0.000000 0.000000 0.000000 0.000061 0.000015
+ 0.001065 0.001172 0.001172 0.996177 0.000130 0.000061 0.000000 0.000015 0.000000 0.000000 0.000130 0.000000 0.000000 0.000000 0.000061 0.000015
+ 0.996177 0.001172 0.001172 0.001065 0.000130 0.000061 0.000000 0.000015 0.000000 0.000000 0.000130 0.000000 0.000000 0.000000 0.000061 0.000015
+ 0.928407 0.001172 0.035057 0.034950 0.000130 0.000061 0.000000 0.000015 0.000000 0.000000 0.000130 0.000000 0.000000 0.000000 0.000061 0.000015
+ 0.860638 0.136711 0.001172 0.001065 0.000130 0.000061 0.000000 0.000015 0.000000 0.000000 0.000130 0.000000 0.000000 0.000000 0.000061 0.000015
+ 0.548672 0.001172 0.313139 0.136603 0.000130 0.000061 0.000000 0.000015 0.000000 0.000000 0.000130 0.000000 0.000000 0.000000 0.000061 0.000015
+ 0.068834 0.068941 0.725207 0.136603 0.000130 0.000061 0.000000 0.000015 0.000000 0.000000 0.000130 0.000000 0.000000 0.000000 0.000061 0.000015
+ 0.068834 0.485705 0.308443 0.136603 0.000130 0.000061 0.000000 0.000015 0.000000 0.000000 0.000130 0.000000 0.000000 0.000000 0.000061 0.000015
+
+MOTIF 2-CCCACCAGA STREME-2
+letter-probability matrix: alength= 16 w= 9 nsites= 20 S= 2.2e-007
+ 0.001482 0.947685 0.048775 0.001482 0.000181 0.000085 0.000000 0.000021 0.000000 0.000000 0.000181 0.000000 0.000000 0.000000 0.000085 0.000021
+ 0.143970 0.805197 0.048775 0.001482 0.000181 0.000085 0.000000 0.000021 0.000000 0.000000 0.000181 0.000000 0.000000 0.000000 0.000085 0.000021
+ 0.095771 0.711962 0.143064 0.048626 0.000181 0.000085 0.000000 0.000021 0.000000 0.000000 0.000181 0.000000 0.000000 0.000000 0.000085 0.000021
+ 0.947536 0.001631 0.048775 0.001482 0.000181 0.000085 0.000000 0.000021 0.000000 0.000000 0.000181 0.000000 0.000000 0.000000 0.000085 0.000021
+ 0.095771 0.710908 0.191263 0.001482 0.000181 0.000085 0.000000 0.000021 0.000000 0.000000 0.000181 0.000000 0.000000 0.000000 0.000085 0.000021
+ 0.001482 0.900540 0.001631 0.095771 0.000181 0.000085 0.000000 0.000021 0.000000 0.000000 0.000181 0.000000 0.000000 0.000000 0.000085 0.000021
+ 0.663614 0.095920 0.096974 0.142915 0.000181 0.000085 0.000000 0.000021 0.000000 0.000000 0.000181 0.000000 0.000000 0.000000 0.000085 0.000021
+ 0.095771 0.332697 0.569474 0.001482 0.000181 0.000085 0.000000 0.000021 0.000000 0.000000 0.000181 0.000000 0.000000 0.000000 0.000085 0.000021
+ 0.473982 0.239462 0.143064 0.142915 0.000181 0.000085 0.000000 0.000021 0.000000 0.000000 0.000181 0.000000 0.000000 0.000000 0.000085 0.000021
+
+MOTIF 3-4a4t4a4a4T STREME-3
+letter-probability matrix: alength= 16 w= 10 nsites= 7 S= 5.5e-003
+ 0.004400 0.004842 0.004842 0.004400 0.140510 0.000253 0.000000 0.000064 0.000000 0.000000 0.000537 0.000000 0.000000 0.000000 0.840087 0.000064
+ 0.004400 0.004842 0.004842 0.004400 0.700399 0.000253 0.000000 0.000064 0.000000 0.000000 0.280482 0.000000 0.000000 0.000000 0.000253 0.000064
+ 0.004400 0.004842 0.004842 0.004400 0.000537 0.000253 0.000000 0.000064 0.000000 0.000000 0.000537 0.000000 0.000000 0.000000 0.980059 0.000064
+ 0.004400 0.004842 0.004842 0.004400 0.000537 0.000253 0.000000 0.000064 0.000000 0.000000 0.840371 0.000000 0.000000 0.000000 0.140226 0.000064
+ 0.004400 0.004842 0.004842 0.004400 0.000537 0.000253 0.000000 0.000064 0.000000 0.000000 0.280482 0.000000 0.000000 0.000000 0.700115 0.000064
+ 0.004400 0.004842 0.004842 0.004400 0.560427 0.000253 0.000000 0.000064 0.000000 0.000000 0.420454 0.000000 0.000000 0.000000 0.000253 0.000064
+ 0.004400 0.004842 0.004842 0.144372 0.000537 0.000253 0.000000 0.000064 0.000000 0.000000 0.280482 0.000000 0.000000 0.000000 0.560142 0.000064
+ 0.004400 0.144814 0.144814 0.004400 0.420454 0.000253 0.000000 0.000064 0.000000 0.000000 0.280482 0.000000 0.000000 0.000000 0.000253 0.000064
+ 0.004400 0.144814 0.144814 0.144372 0.140510 0.000253 0.000000 0.000064 0.000000 0.000000 0.140510 0.000000 0.000000 0.000000 0.280198 0.000064
+ 0.004400 0.144814 0.004842 0.284344 0.280482 0.000253 0.000000 0.000064 0.000000 0.000000 0.000537 0.000000 0.000000 0.000000 0.280198 0.000064
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test-data/streme_output_test2.xml	Mon Jul 14 21:33:56 2025 +0000
@@ -0,0 +1,39 @@
+    <alphabet name="DNA with covalent modifications" like="dna">
+      <letter id="A" symbol="A" complement="T" name="Adenine" colour="8510A8"/>
+      <letter id="C" symbol="C" complement="G" name="Cytosine" colour="A50026"/>
+      <letter id="G" symbol="G" complement="C" name="Guanine" colour="313695"/>
+      <letter id="T" symbol="T" complement="A" name="Thymine" colour="A89610"/>
+      <letter id="a" symbol="a" complement="t" name="N6-methyladenine" colour="8510A8"/>
+      <letter id="c" symbol="c" complement="4" name="5-Carboxylcytosine" colour="FEE090"/>
+      <letter id="f" symbol="f" complement="3" name="5-Formylcytosine" colour="FDAE61"/>
+      <letter id="g" symbol="g" complement="5" name="modified_g" colour="00897B"/>
+      <letter id="h" symbol="h" complement="2" name="5-Hydroxymethylcytosine" colour="F46D43"/>
+      <letter id="m" symbol="m" complement="1" name="5-Methylcytosine" colour="D73027"/>
+      <letter id="t" symbol="t" complement="a" name="Thymine_lowercase" colour="756BB1"/>
+      <letter id="n1" symbol="1" complement="m" name="Guanine:5-Methylcytosine" colour="4575B4"/>
+      <letter id="n2" symbol="2" complement="h" name="Guanine:5-Hydroxymethylcytosine" colour="74ADD1"/>
+      <letter id="n3" symbol="3" complement="f" name="Guanine:5-Formylcytosine" colour="ABD9E9"/>
+      <letter id="n4" symbol="4" complement="c" name="Guanine:5-Carboxylcytosine" colour="E0F3F8"/>
+      <letter id="n5" symbol="5" complement="g" name="cytosine_lowercase" colour="53698A"/>
+      <letter id="x3F" symbol="?" equals="ACGTacfghmt12345"/>
+    </alphabet>
+    <strands>both</strands>
+    <sequence_db A="0.218" C="0.24" G="0.24" T="0.218" a="0.0266" c="0.0125" f="0" g="0.00313" h="0" m="0" t="0.0266" n1="0" n2="0" n3="0" n4="0.0125" n5="0.00313"/>
+    <background_frequencies source="--negatives--" order="0">
+      <alphabet_array>
+        <value letter_id="A">0.218</value>
+        <value letter_id="C">0.24</value>
+        <value letter_id="G">0.24</value>
+        <value letter_id="T">0.218</value>
+        <value letter_id="a">0.0266</value>
+        <value letter_id="c">0.0125</value>
+        <value letter_id="f">1.96e-05</value>
+        <value letter_id="g">0.00315</value>
+        <value letter_id="h">1.96e-05</value>
+        <value letter_id="m">1.96e-05</value>
+        <value letter_id="t">0.0266</value>
+        <value letter_id="n1">1.96e-05</value>
+        <value letter_id="n2">1.96e-05</value>
+        <value letter_id="n3">1.96e-05</value>
+        <value letter_id="n4">0.0125</value>
+        <value letter_id="n5">0.00315</value>
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test-data/streme_output_test3.html	Mon Jul 14 21:33:56 2025 +0000
@@ -0,0 +1,38 @@
+            "max_sites": 2,
+            "site_hist": [0, 6, 1],
+            "len": 5,
+            "nsites": 7,
+            "evalue": "0",
+            "pwm": [
+              [
+                0.00775938, 0.00626088, 8.41549e-07, 8.41549e-07, 8.41549e-07,
+                0.979973, 8.41549e-07, 8.41549e-07, 8.41549e-07, 8.41549e-07,
+                0.000219631, 8.41549e-07, 8.41549e-07, 8.41549e-07,
+                8.41549e-07, 8.41549e-07, 0.00577435, 8.41549e-07,
+                8.41549e-07, 8.41549e-07
+              ], [
+                0.00775938, 0.588717, 8.41549e-07, 8.41549e-07, 8.41549e-07,
+                0.397517, 8.41549e-07, 8.41549e-07, 8.41549e-07, 8.41549e-07,
+                0.000219631, 8.41549e-07, 8.41549e-07, 8.41549e-07,
+                8.41549e-07, 8.41549e-07, 0.00577435, 8.41549e-07,
+                8.41549e-07, 8.41549e-07
+              ], [
+                0.00775938, 0.00626088, 8.41549e-07, 8.41549e-07, 8.41549e-07,
+                0.00777606, 8.41549e-07, 8.41549e-07, 8.41549e-07,
+                8.41549e-07, 0.972417, 8.41549e-07, 8.41549e-07, 8.41549e-07,
+                8.41549e-07, 8.41549e-07, 0.00577435, 8.41549e-07,
+                8.41549e-07, 8.41549e-07
+              ], [
+                0.00775938, 0.00626088, 8.41549e-07, 8.41549e-07, 8.41549e-07,
+                0.979973, 8.41549e-07, 8.41549e-07, 8.41549e-07, 8.41549e-07,
+                0.000219631, 8.41549e-07, 8.41549e-07, 8.41549e-07,
+                8.41549e-07, 8.41549e-07, 0.00577435, 8.41549e-07,
+                8.41549e-07, 8.41549e-07
+              ], [
+                0.00775938, 0.00626088, 8.41549e-07, 8.41549e-07, 8.41549e-07,
+                0.787258, 8.41549e-07, 8.41549e-07, 8.41549e-07, 8.41549e-07,
+                0.000219631, 8.41549e-07, 8.41549e-07, 8.41549e-07,
+                8.41549e-07, 8.41549e-07, 0.19849, 8.41549e-07, 8.41549e-07,
+                8.41549e-07
+              ]
+            ]
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test-data/streme_output_test3.txt	Mon Jul 14 21:33:56 2025 +0000
@@ -0,0 +1,79 @@
+********************************************************************************
+STREME - Sensitive, Thorough, Rapid, Enriched Motif Elicitation
+********************************************************************************
+MEME version 5.5.8 (Release date: Thu May 15 15:01:46 2025 -0700)
+
+For further information on how to interpret these results please access https://meme-suite.org/meme.
+To get a copy of the MEME Suite software please access https://meme-suite.org.
+
+********************************************************************************
+
+
+********************************************************************************
+REFERENCE
+********************************************************************************
+If you use this program in your research, please cite:
+
+Timothy L. Bailey,
+"STREME: accurate and versatile sequence motif discovery",
+Bioinformatics, Mar. 24, 2021.
+********************************************************************************
+
+
+ALPHABET= ACDEFGHIKLMNPQRSTVWY
+
+strands: +
+
+Background letter frequencies
+A 0.279 C 0.225 D 3.03e-05 E 3.03e-05 F 3.03e-05 G 0.28 H 3.03e-05 I 3.03e-05 K 3.03e-05 L 3.03e-05 M 0.0079 N 3.03e-05 P 3.03e-05 Q 3.03e-05 R 3.03e-05 S 3.03e-05 T 0.208 V 3.03e-05 W 3.03e-05 Y 3.03e-05 
+
+MOTIF 1-GCMGG STREME-1
+letter-probability matrix: alength= 20 w= 5 nsites= 7 S= 5.5e-003
+ 0.007759 0.006261 0.000001 0.000001 0.000001 0.979973 0.000001 0.000001 0.000001 0.000001 0.000220 0.000001 0.000001 0.000001 0.000001 0.000001 0.005774 0.000001 0.000001 0.000001
+ 0.007759 0.588717 0.000001 0.000001 0.000001 0.397517 0.000001 0.000001 0.000001 0.000001 0.000220 0.000001 0.000001 0.000001 0.000001 0.000001 0.005774 0.000001 0.000001 0.000001
+ 0.007759 0.006261 0.000001 0.000001 0.000001 0.007776 0.000001 0.000001 0.000001 0.000001 0.972417 0.000001 0.000001 0.000001 0.000001 0.000001 0.005774 0.000001 0.000001 0.000001
+ 0.007759 0.006261 0.000001 0.000001 0.000001 0.979973 0.000001 0.000001 0.000001 0.000001 0.000220 0.000001 0.000001 0.000001 0.000001 0.000001 0.005774 0.000001 0.000001 0.000001
+ 0.007759 0.006261 0.000001 0.000001 0.000001 0.787258 0.000001 0.000001 0.000001 0.000001 0.000220 0.000001 0.000001 0.000001 0.000001 0.000001 0.198490 0.000001 0.000001 0.000001
+
+MOTIF 2-GGTMA STREME-2
+letter-probability matrix: alength= 20 w= 5 nsites= 6 S= 5.2e-002
+ 0.166242 0.005192 0.000001 0.000001 0.000001 0.823585 0.000001 0.000001 0.000001 0.000001 0.000182 0.000001 0.000001 0.000001 0.000001 0.000001 0.004788 0.000001 0.000001 0.000001
+ 0.006434 0.164999 0.000001 0.000001 0.000001 0.823585 0.000001 0.000001 0.000001 0.000001 0.000182 0.000001 0.000001 0.000001 0.000001 0.000001 0.004788 0.000001 0.000001 0.000001
+ 0.006434 0.005192 0.000001 0.000001 0.000001 0.006448 0.000001 0.000001 0.000001 0.000001 0.000182 0.000001 0.000001 0.000001 0.000001 0.000001 0.981733 0.000001 0.000001 0.000001
+ 0.006434 0.277760 0.000001 0.000001 0.000001 0.166256 0.000001 0.000001 0.000001 0.000001 0.479605 0.000001 0.000001 0.000001 0.000001 0.000001 0.069935 0.000001 0.000001 0.000001
+ 0.823572 0.164999 0.000001 0.000001 0.000001 0.006448 0.000001 0.000001 0.000001 0.000001 0.000182 0.000001 0.000001 0.000001 0.000001 0.000001 0.004788 0.000001 0.000001 0.000001
+
+MOTIF 3-GTATAAAATCA STREME-3
+letter-probability matrix: alength= 20 w= 11 nsites= 8 S= 9.3e-002
+ 0.008845 0.007137 0.000001 0.000001 0.000001 0.977170 0.000001 0.000001 0.000001 0.000001 0.000250 0.000001 0.000001 0.000001 0.000001 0.000001 0.006583 0.000001 0.000001 0.000001
+ 0.008845 0.007137 0.000001 0.000001 0.000001 0.008864 0.000001 0.000001 0.000001 0.000001 0.000250 0.000001 0.000001 0.000001 0.000001 0.000001 0.974888 0.000001 0.000001 0.000001
+ 0.977151 0.007137 0.000001 0.000001 0.000001 0.008864 0.000001 0.000001 0.000001 0.000001 0.000250 0.000001 0.000001 0.000001 0.000001 0.000001 0.006583 0.000001 0.000001 0.000001
+ 0.008845 0.007137 0.000001 0.000001 0.000001 0.008864 0.000001 0.000001 0.000001 0.000001 0.000250 0.000001 0.000001 0.000001 0.000001 0.000001 0.974888 0.000001 0.000001 0.000001
+ 0.977151 0.007137 0.000001 0.000001 0.000001 0.008864 0.000001 0.000001 0.000001 0.000001 0.000250 0.000001 0.000001 0.000001 0.000001 0.000001 0.006583 0.000001 0.000001 0.000001
+ 0.757464 0.007137 0.000001 0.000001 0.000001 0.228552 0.000001 0.000001 0.000001 0.000001 0.000250 0.000001 0.000001 0.000001 0.000001 0.000001 0.006583 0.000001 0.000001 0.000001
+ 0.757464 0.007137 0.000001 0.000001 0.000001 0.008864 0.000001 0.000001 0.000001 0.000001 0.000250 0.000001 0.000001 0.000001 0.000001 0.000001 0.226270 0.000001 0.000001 0.000001
+ 0.757464 0.007137 0.000001 0.000001 0.000001 0.008864 0.000001 0.000001 0.000001 0.000001 0.000250 0.000001 0.000001 0.000001 0.000001 0.000001 0.226270 0.000001 0.000001 0.000001
+ 0.008845 0.226824 0.000001 0.000001 0.000001 0.228552 0.000001 0.000001 0.000001 0.000001 0.000250 0.000001 0.000001 0.000001 0.000001 0.000001 0.535514 0.000001 0.000001 0.000001
+ 0.008845 0.885886 0.000001 0.000001 0.000001 0.008864 0.000001 0.000001 0.000001 0.000001 0.000250 0.000001 0.000001 0.000001 0.000001 0.000001 0.096140 0.000001 0.000001 0.000001
+ 0.448220 0.226824 0.000001 0.000001 0.000001 0.008864 0.000001 0.000001 0.000001 0.000001 0.000250 0.000001 0.000001 0.000001 0.000001 0.000001 0.315827 0.000001 0.000001 0.000001
+
+MOTIF 4-GAGGTG STREME-4
+letter-probability matrix: alength= 20 w= 6 nsites= 5 S= 9.8e-002
+ 0.007829 0.200766 0.000001 0.000001 0.000001 0.785344 0.000001 0.000001 0.000001 0.000001 0.000222 0.000001 0.000001 0.000001 0.000001 0.000001 0.005826 0.000001 0.000001 0.000001
+ 0.979776 0.006317 0.000001 0.000001 0.000001 0.007846 0.000001 0.000001 0.000001 0.000001 0.000222 0.000001 0.000001 0.000001 0.000001 0.000001 0.005826 0.000001 0.000001 0.000001
+ 0.202278 0.041933 0.000001 0.000001 0.000001 0.670460 0.000001 0.000001 0.000001 0.000001 0.000222 0.000001 0.000001 0.000001 0.000001 0.000001 0.085095 0.000001 0.000001 0.000001
+ 0.007829 0.200766 0.000001 0.000001 0.000001 0.785344 0.000001 0.000001 0.000001 0.000001 0.000222 0.000001 0.000001 0.000001 0.000001 0.000001 0.005826 0.000001 0.000001 0.000001
+ 0.007829 0.006317 0.000001 0.000001 0.000001 0.007846 0.000001 0.000001 0.000001 0.000001 0.000222 0.000001 0.000001 0.000001 0.000001 0.000001 0.977773 0.000001 0.000001 0.000001
+ 0.087098 0.006317 0.000001 0.000001 0.000001 0.900525 0.000001 0.000001 0.000001 0.000001 0.000222 0.000001 0.000001 0.000001 0.000001 0.000001 0.005826 0.000001 0.000001 0.000001
+
+MOTIF 5-TCACACACA STREME-5
+letter-probability matrix: alength= 20 w= 9 nsites= 5 S= 9.8e-002
+ 0.007502 0.192368 0.000001 0.000001 0.000001 0.007518 0.000001 0.000001 0.000001 0.000001 0.000212 0.000001 0.000001 0.000001 0.000001 0.000001 0.792388 0.000001 0.000001 0.000001
+ 0.193817 0.716905 0.000001 0.000001 0.000001 0.083471 0.000001 0.000001 0.000001 0.000001 0.000212 0.000001 0.000001 0.000001 0.000001 0.000001 0.005583 0.000001 0.000001 0.000001
+ 0.794307 0.006053 0.000001 0.000001 0.000001 0.007518 0.000001 0.000001 0.000001 0.000001 0.000212 0.000001 0.000001 0.000001 0.000001 0.000001 0.191898 0.000001 0.000001 0.000001
+ 0.007502 0.903220 0.000001 0.000001 0.000001 0.007518 0.000001 0.000001 0.000001 0.000001 0.000212 0.000001 0.000001 0.000001 0.000001 0.000001 0.081536 0.000001 0.000001 0.000001
+ 0.794307 0.006053 0.000001 0.000001 0.000001 0.007518 0.000001 0.000001 0.000001 0.000001 0.000212 0.000001 0.000001 0.000001 0.000001 0.000001 0.191898 0.000001 0.000001 0.000001
+ 0.007502 0.792858 0.000001 0.000001 0.000001 0.193833 0.000001 0.000001 0.000001 0.000001 0.000212 0.000001 0.000001 0.000001 0.000001 0.000001 0.005583 0.000001 0.000001 0.000001
+ 0.718354 0.082006 0.000001 0.000001 0.000001 0.007518 0.000001 0.000001 0.000001 0.000001 0.000212 0.000001 0.000001 0.000001 0.000001 0.000001 0.191898 0.000001 0.000001 0.000001
+ 0.007502 0.979173 0.000001 0.000001 0.000001 0.007518 0.000001 0.000001 0.000001 0.000001 0.000212 0.000001 0.000001 0.000001 0.000001 0.000001 0.005583 0.000001 0.000001 0.000001
+ 0.532038 0.006053 0.000001 0.000001 0.000001 0.193833 0.000001 0.000001 0.000001 0.000001 0.000212 0.000001 0.000001 0.000001 0.000001 0.000001 0.267851 0.000001 0.000001 0.000001
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test-data/streme_output_test3.xml	Mon Jul 14 21:33:56 2025 +0000
@@ -0,0 +1,73 @@
+      <letter id="A" symbol="A" name="Alanine" colour="0000CC"/>
+      <letter id="C" symbol="C" name="Cysteine" colour="0000CC"/>
+      <letter id="D" symbol="D" name="Aspartic acid" colour="FF00FF"/>
+      <letter id="E" symbol="E" name="Glutamic acid" colour="FF00FF"/>
+      <letter id="F" symbol="F" name="Phenylalanine" colour="0000CC"/>
+      <letter id="G" symbol="G" name="Glycine" colour="FFB300"/>
+      <letter id="H" symbol="H" name="Histidine" colour="FFCCCC"/>
+      <letter id="I" symbol="I" name="Isoleucine" colour="0000CC"/>
+      <letter id="K" symbol="K" name="Lysine" colour="CC0000"/>
+      <letter id="L" symbol="L" name="Leucine" colour="0000CC"/>
+      <letter id="M" symbol="M" name="Methionine" colour="0000CC"/>
+      <letter id="N" symbol="N" name="Asparagine" colour="008000"/>
+      <letter id="P" symbol="P" name="Proline" colour="FFFF00"/>
+      <letter id="Q" symbol="Q" name="Glutamine" colour="008000"/>
+      <letter id="R" symbol="R" name="Arginine" colour="CC0000"/>
+      <letter id="S" symbol="S" name="Serine" colour="008000"/>
+      <letter id="T" symbol="T" name="Threonine" colour="008000"/>
+      <letter id="V" symbol="V" name="Valine" colour="0000CC"/>
+      <letter id="W" symbol="W" name="Tryptophan" colour="0000CC"/>
+      <letter id="Y" symbol="Y" name="Tyrosine" colour="33E6CC"/>
+      <letter id="X" symbol="X" aliases="*." equals="ACDEFGHIKLMNPQRSTVWY" name="Any amino acid"/>
+      <letter id="B" symbol="B" equals="DN" name="Asparagine or Aspartic acid"/>
+      <letter id="Z" symbol="Z" equals="EQ" name="Glutamine or Glutamic acid"/>
+      <letter id="J" symbol="J" equals="IL" name="Leucine or Isoleucine"/>
+    </alphabet>
+    <strands>none</strands>
+    <sequence_db A="0.275" C="0.224" D="0" E="0" F="0" G="0.283" H="0" I="0" K="0" L="0" M="0.00977" N="0" P="0" Q="0" R="0" S="0" T="0.209" V="0" W="0" Y="0"/>
+    <background_frequencies source="--negatives--" order="0">
+      <alphabet_array>
+        <value letter_id="A">0.279</value>
+        <value letter_id="C">0.225</value>
+        <value letter_id="D">3.03e-05</value>
+        <value letter_id="E">3.03e-05</value>
+        <value letter_id="F">3.03e-05</value>
+        <value letter_id="G">0.28</value>
+        <value letter_id="H">3.03e-05</value>
+        <value letter_id="I">3.03e-05</value>
+        <value letter_id="K">3.03e-05</value>
+        <value letter_id="L">3.03e-05</value>
+        <value letter_id="M">0.0079</value>
+        <value letter_id="N">3.03e-05</value>
+        <value letter_id="P">3.03e-05</value>
+        <value letter_id="Q">3.03e-05</value>
+        <value letter_id="R">3.03e-05</value>
+        <value letter_id="S">3.03e-05</value>
+        <value letter_id="T">0.208</value>
+        <value letter_id="V">3.03e-05</value>
+        <value letter_id="W">3.03e-05</value>
+        <value letter_id="Y">3.03e-05</value>
+      </alphabet_array>
+    </background_frequencies>
+    <stop nmotifs="5"/>
+    <objfun>Differential Enrichment</objfun>
+    <test>Fisher Exact Test</test>
+    <minw>5</minw>
+    <maxw>20</maxw>
+    <kmer>1</kmer>
+    <hofract>0.1</hofract>
+    <neval>25</neval>
+    <nref>4</nref>
+    <niter>20</niter>
+    <patience>3</patience>
+    <seed>0</seed>
+    <notrim>no</notrim>
+    <useer>no</useer>
+    <minscore>0</minscore>
+    <ignore_depth>5</ignore_depth>
+    <nsubsets>1</nsubsets>
+    <min_pal_ratio>0.85</min_pal_ratio>
+    <max_pal_ed>5</max_pal_ed>
+    <cand>no</cand>
+    <experimental>no</experimental>
+    <totallength>0</totallength>
\ No newline at end of file