| 0 | 1 <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> | 
|  | 2 <html> | 
|  | 3 <head> | 
|  | 4 <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> | 
|  | 5 <title>DREME</title> | 
|  | 6 <style type="text/css"> | 
|  | 7 | 
|  | 8     /* START INCLUDED FILE "meme.css" */ | 
|  | 9         /* The following is the content of meme.css */ | 
|  | 10         body { background-color:white; font-size: 12px; font-family: Verdana, Arial, Helvetica, sans-serif;} | 
|  | 11 | 
|  | 12         div.help { | 
|  | 13           display: inline-block; | 
|  | 14           margin: 0px; | 
|  | 15           padding: 0px; | 
|  | 16           width: 12px; | 
|  | 17           height: 13px; | 
|  | 18           cursor: pointer; | 
|  | 19           background-image: url("help.gif"); | 
|  | 20           background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAwAAAANAQMAAACn5x0BAAAAAXNSR0IArs4c6QAAAAZQTFRFAAAAnp6eqp814gAAAAF0Uk5TAEDm2GYAAAABYktHRACIBR1IAAAACXBIWXMAAAsTAAALEwEAmpwYAAAAB3RJTUUH2gMJBQgGYqhNZQAAACZJREFUCNdj+P+BoUGAoV+AYeYEEGoWYGgTYGgRAAm2gRGQ8f8DAOnhC2lYnqs6AAAAAElFTkSuQmCC"); | 
|  | 21         } | 
|  | 22 | 
|  | 23         div.help2 { | 
|  | 24           color: #999; | 
|  | 25           display: inline-block; | 
|  | 26           width: 12px; | 
|  | 27           height: 12px; | 
|  | 28           border: 1px solid #999; | 
|  | 29           font-size: 13px; | 
|  | 30           line-height:12px; | 
|  | 31           font-family: Helvetica, sans-serif; | 
|  | 32           font-weight: bold; | 
|  | 33           font-style: normal; | 
|  | 34           cursor: pointer; | 
|  | 35         } | 
|  | 36         div.help2:hover { | 
|  | 37           color: #000; | 
|  | 38           border-color: #000; | 
|  | 39         } | 
|  | 40 | 
|  | 41         p.spaced { line-height: 1.8em;} | 
|  | 42 | 
|  | 43         span.citation { font-family: "Book Antiqua", "Palatino Linotype", serif; color: #004a4d;} | 
|  | 44 | 
|  | 45         p.pad { padding-left: 30px; padding-top: 5px; padding-bottom: 10px;} | 
|  | 46 | 
|  | 47         td.jump { font-size: 13px; color: #ffffff; background-color: #00666a; | 
|  | 48           font-family: Georgia, "Times New Roman", Times, serif;} | 
|  | 49 | 
|  | 50         a.jump { margin: 15px 0 0; font-style: normal; font-variant: small-caps; | 
|  | 51           font-weight: bolder; font-family: Georgia, "Times New Roman", Times, serif;} | 
|  | 52 | 
|  | 53         h2.mainh {font-size: 1.5em; font-style: normal; margin: 15px 0 0; | 
|  | 54           font-variant: small-caps; font-family: Georgia, "Times New Roman", Times, serif;} | 
|  | 55 | 
|  | 56         h2.line {border-bottom: 1px solid #CCCCCC; font-size: 1.5em; font-style: normal; | 
|  | 57           margin: 15px 0 0; padding-bottom: 3px; font-variant: small-caps; | 
|  | 58           font-family: Georgia, "Times New Roman", Times, serif;} | 
|  | 59 | 
|  | 60         h4 {border-bottom: 1px solid #CCCCCC; font-size: 1.2em; font-style: normal; | 
|  | 61           margin: 10px 0 0; padding-bottom: 3px; font-family: Georgia, "Times New Roman", Times, serif;} | 
|  | 62 | 
|  | 63         h5 {margin: 0px} | 
|  | 64 | 
|  | 65         a.help { font-size: 9px; font-style: normal; text-transform: uppercase; | 
|  | 66           font-family: Georgia, "Times New Roman", Times, serif;} | 
|  | 67 | 
|  | 68         div.pad { padding-left: 30px; padding-top: 5px; padding-bottom: 10px;} | 
|  | 69 | 
|  | 70         div.pad1 { margin: 10px 5px;} | 
|  | 71 | 
|  | 72         div.pad2 { margin: 25px 5px 5px;} | 
|  | 73         h2.pad2 { padding: 25px 5px 5px;} | 
|  | 74 | 
|  | 75         div.pad3 { padding: 5px 0px 10px 30px;} | 
|  | 76 | 
|  | 77         div.box { border: 2px solid #CCCCCC; padding:10px;} | 
|  | 78 | 
|  | 79         div.bar { border-left: 7px solid #00666a; padding:5px; margin-top:25px; } | 
|  | 80 | 
|  | 81         div.subsection {margin:25px 0px;} | 
|  | 82 | 
|  | 83         img {border:0px none;} | 
|  | 84 | 
|  | 85         th.majorth {text-align:left;} | 
|  | 86         th.minorth {font-weight:normal; text-align:left; width:8em; padding: 3px 0px;} | 
|  | 87         th.actionth {font-weight:normal; text-align:left;} | 
|  | 88 | 
|  | 89         .strand_name {text-align:left;} | 
|  | 90         .strand_side {padding:0px 10px;} | 
|  | 91         .strand_start {padding:0px 10px;} | 
|  | 92         .strand_pvalue {text-align:center; padding:0px 10px;} | 
|  | 93         .strand_lflank {text-align:right; padding-right:5px; font-weight:bold; font-size:large; font-family: 'Courier New', Courier, monospace; color:gray;} | 
|  | 94         .strand_seq {text-align:center; font-weight:bold; font-size:large; font-family: 'Courier New', Courier, monospace;} | 
|  | 95         .strand_rflank {text-align:left; padding-left:5px; font-weight:bold; font-size:large; font-family: 'Courier New', Courier, monospace; color:gray;} | 
|  | 96 | 
|  | 97         .block_td {height:25px;} | 
|  | 98         .block_container {position:relative; width:99%; height:25px; padding:0px; margin:0px;} | 
|  | 99         .block_motif {position:absolute; z-index:3; height:12px; top:0px; text-align:center; vertical-align:middle; background-color:cyan;} | 
|  | 100         .block_rule {position:absolute; z-index:2; width:100%; height:1px; top:12px; left:0px; background-color:gray;} | 
|  | 101         .block_plus_sym {position:absolute; z-index:4; width:12px; height:12px; top:0px; left:0px; color:gray;} | 
|  | 102         .block_minus_sym {position:absolute; z-index:4; width:12px; height:12px; top:13px; left:0px; color:gray;} | 
|  | 103 | 
|  | 104         .tic_major {position:absolute; border-left:2px solid blue; height:0.5em; top:0em;} | 
|  | 105         .tic_minor {position:absolute; border-left:1px solid blue; height:0.2em; top:0em;} | 
|  | 106         .tic_label {position:absolute; top:0.5em;  height: 1em; text-align:center; vertical-align:middle} | 
|  | 107 | 
|  | 108         .explain h5 {font-size:1em; margin-left: 1em;} | 
|  | 109 | 
|  | 110         div.doc {margin-left: 2em; margin-bottom: 3em;} | 
|  | 111 | 
|  | 112         div.tabArea { | 
|  | 113           font-size: 80%; | 
|  | 114           font-weight: bold; | 
|  | 115         } | 
|  | 116 | 
|  | 117         a.tab { | 
|  | 118           background-color: #ddddff; | 
|  | 119           border: 1px solid #000000; | 
|  | 120           padding: 2px 1em 2px 1em; | 
|  | 121           text-decoration: none; | 
|  | 122         } | 
|  | 123         div.tabArea.base a.tab { | 
|  | 124           border-top-width: 0px; | 
|  | 125         } | 
|  | 126         div.tabArea.top a.tab { | 
|  | 127           border-bottom-width: 0px; | 
|  | 128         } | 
|  | 129 | 
|  | 130         a.tab, a.tab:visited { | 
|  | 131           color: #808080; | 
|  | 132         } | 
|  | 133 | 
|  | 134         a.tab:hover { | 
|  | 135           background-color: #d0d0d0; | 
|  | 136           color: #606060; | 
|  | 137         } | 
|  | 138         a.tab.activeTab, a.tab.activeTab:hover, a.tab.activeTab:visited { | 
|  | 139           background-color: #f0f0f0; | 
|  | 140           color: #000000; | 
|  | 141         } | 
|  | 142         div.tabMain { | 
|  | 143           border: 1px solid #000000; | 
|  | 144           background-color: #ffffff; | 
|  | 145           padding: 5px; | 
|  | 146           margin-right: 5px; | 
|  | 147         } | 
|  | 148         th.trainingset { | 
|  | 149           border-bottom: thin dashed black; | 
|  | 150           font-weight:normal; | 
|  | 151           padding:0px 10px; | 
|  | 152         } | 
|  | 153         .dnaseq { | 
|  | 154           font-weight: bold; | 
|  | 155           font-size: large; | 
|  | 156           font-family: 'Courier New', Courier, monospace; | 
|  | 157         } | 
|  | 158         .dna_A { | 
|  | 159           color: rgb(204,0,0); | 
|  | 160         } | 
|  | 161         .dna_C { | 
|  | 162           color: rgb(0,0,204); | 
|  | 163         } | 
|  | 164         .dna_G { | 
|  | 165           color: rgb(255,179,0); | 
|  | 166         } | 
|  | 167         .dna_T { | 
|  | 168           color: rgb(0,128,0); | 
|  | 169         } | 
|  | 170     /* END INCLUDED FILE "meme.css" */ | 
|  | 171 | 
|  | 172 | 
|  | 173 | 
|  | 174     /* START INCLUDED FILE "dreme-to-html.css" */ | 
|  | 175       table.dreme_motifs tr th, table.dreme_motifs tr td { | 
|  | 176         padding: 0px 10px; | 
|  | 177       } | 
|  | 178 | 
|  | 179       div.popup_wrapper { | 
|  | 180         position:fixed; | 
|  | 181         z-index:2; | 
|  | 182         width:100%; | 
|  | 183         height:0; | 
|  | 184         top:50%; | 
|  | 185         left:0; | 
|  | 186       } | 
|  | 187 | 
|  | 188       div.popup { | 
|  | 189         width: 400px; | 
|  | 190         z-index:2; | 
|  | 191         margin-left: auto; | 
|  | 192         margin-right: auto; | 
|  | 193         padding: 5px; | 
|  | 194         background: #FFF; | 
|  | 195         border-style: double; | 
|  | 196         border-width: 5px; | 
|  | 197         border-color: #00666a; | 
|  | 198         position:relative; | 
|  | 199       } | 
|  | 200 | 
|  | 201       div.grey_background { | 
|  | 202         position:fixed; | 
|  | 203         z-index: 1; | 
|  | 204         background-color: #000; | 
|  | 205         -ms-filter: "progid:DXImageTransform.Microsoft.Alpha(Opacity=50)"; | 
|  | 206         filter: alpha(opacity=50); | 
|  | 207         opacity: 0.5; | 
|  | 208         left: 0; | 
|  | 209         top: 0; | 
|  | 210         width: 100%; | 
|  | 211         height: 100%; | 
|  | 212 | 
|  | 213       } | 
|  | 214       td.symaction { | 
|  | 215         text-align: center; | 
|  | 216       } | 
|  | 217       *.symaction { | 
|  | 218         font-size: 20px; | 
|  | 219       } | 
|  | 220 | 
|  | 221       div.close { | 
|  | 222         cursor: pointer; | 
|  | 223         border: 1px solid black; | 
|  | 224         width:15px; | 
|  | 225         height:15px; | 
|  | 226         line-height:15px; /* this causes vertical centering */ | 
|  | 227         text-align:center; | 
|  | 228         background-color:#FFF; | 
|  | 229         color:#000; | 
|  | 230         font-size:15px; | 
|  | 231         font-family:monospace; | 
|  | 232       } | 
|  | 233 | 
|  | 234       div.close:hover { | 
|  | 235         color:#FFF; | 
|  | 236         background-color:#000; | 
|  | 237       } | 
|  | 238 | 
|  | 239       div.navnum { | 
|  | 240         width:100%; | 
|  | 241         height:20px; | 
|  | 242         line-height:20px; | 
|  | 243         text-align:center; | 
|  | 244         font-size:medium; | 
|  | 245       } | 
|  | 246 | 
|  | 247       a.navarrow { | 
|  | 248         font-size: 30px; | 
|  | 249         text-decoration:none; | 
|  | 250       } | 
|  | 251 | 
|  | 252       a.inactive { | 
|  | 253         color:#CCC; | 
|  | 254       } | 
|  | 255 | 
|  | 256       div.actionbutton { | 
|  | 257         cursor: pointer; | 
|  | 258         font-size: 18px; | 
|  | 259         line-height:20px; | 
|  | 260         padding: 5px; | 
|  | 261         margin: 10px 0; | 
|  | 262         border: 1px solid black; | 
|  | 263       } | 
|  | 264 | 
|  | 265       div.actionbutton:hover { | 
|  | 266         color:#FFF; | 
|  | 267         background-color:#000; | 
|  | 268       } | 
|  | 269 | 
|  | 270       div.pop_content { | 
|  | 271         position:absolute; | 
|  | 272         z-index:1; | 
|  | 273         width:300px; | 
|  | 274         padding: 5px; | 
|  | 275         background: #E4ECEC; | 
|  | 276         font-size: 12px; | 
|  | 277         font-family: Arial; | 
|  | 278         border-style: double; | 
|  | 279         border-width: 3px; | 
|  | 280         border-color: #AA2244; | 
|  | 281         display:none; | 
|  | 282       } | 
|  | 283       span.sort_dir { | 
|  | 284         text-decoration: none; | 
|  | 285       } | 
|  | 286 | 
|  | 287       div.section_title { | 
|  | 288         font-weight: bold; | 
|  | 289         cursor: pointer; | 
|  | 290       } | 
|  | 291 | 
|  | 292       div.section_title.inactive { | 
|  | 293         color: #000; | 
|  | 294       } | 
|  | 295 | 
|  | 296       div.section_title.inactive:hover { | 
|  | 297         color: #000; | 
|  | 298         text-decoration:underline; | 
|  | 299       } | 
|  | 300 | 
|  | 301       div.section_title label { | 
|  | 302         cursor: pointer; | 
|  | 303       } | 
|  | 304 | 
|  | 305       span.ellipsis { | 
|  | 306         display: inline-block; | 
|  | 307         border: 1px solid black; | 
|  | 308         padding: 0 2px; | 
|  | 309         margin: 0 2px; | 
|  | 310       } | 
|  | 311 | 
|  | 312       div.section_title.inactive:hover span.ellipsis { | 
|  | 313         color: #FFF; | 
|  | 314         background-color: #000; | 
|  | 315       } | 
|  | 316 | 
|  | 317       div.section_title.inactive span.toggle { | 
|  | 318         color: #000; | 
|  | 319       } | 
|  | 320 | 
|  | 321       div.section_data { | 
|  | 322         margin-left: 20px; | 
|  | 323       } | 
|  | 324       tr.rule td, tr.rule th { | 
|  | 325         border-bottom: 1px solid #CCC; | 
|  | 326       } | 
|  | 327 | 
|  | 328       h1.compact, h2.compact, h3.compact, h4.compact, h5.compact, h6.compact { | 
|  | 329         margin:0; | 
|  | 330         padding:0; | 
|  | 331       } | 
|  | 332 | 
|  | 333       ul.programs { | 
|  | 334         margin-top: 0; | 
|  | 335         padding-top: 0; | 
|  | 336         margin-bottom: 0; | 
|  | 337         padding-bottom: 0; | 
|  | 338         margin-left: 0; | 
|  | 339         padding-left: 0; | 
|  | 340         list-style: none; | 
|  | 341         border-bottom: 1px solid black; | 
|  | 342       } | 
|  | 343 | 
|  | 344       ul.programs li { | 
|  | 345         border: 1px solid black; | 
|  | 346         border-bottom-width: 0; | 
|  | 347         background-color: #EFE; | 
|  | 348         cursor: default; | 
|  | 349       } | 
|  | 350 | 
|  | 351       ul.programs li.active { | 
|  | 352         background-color: #CFC; | 
|  | 353       } | 
|  | 354 | 
|  | 355       ul.programs li.selected { | 
|  | 356         background-color: #262; | 
|  | 357         color: #FFF; | 
|  | 358       } | 
|  | 359 | 
|  | 360       div.programs_scroll { | 
|  | 361         width: 100%; | 
|  | 362         height: 90px; | 
|  | 363         overflow-y: auto; | 
|  | 364         overflow-x: hidden; | 
|  | 365         margin: 0 auto; | 
|  | 366       } | 
|  | 367     /* END INCLUDED FILE "dreme-to-html.css" */ | 
|  | 368 | 
|  | 369   </style> | 
|  | 370 <script type="text/javascript"> | 
|  | 371       var pos_count = 3; | 
|  | 372       var neg_count = 3; | 
|  | 373       var motif_seqs = []; | 
|  | 374 | 
|  | 375 | 
|  | 376     /* START INCLUDED FILE "delay_draw.js" */ | 
|  | 377       // | 
|  | 378       // Functions to measure the position of page elements relative to the size of the page | 
|  | 379       // | 
|  | 380 | 
|  | 381       // gets the offset of the top of the page due to scrolling | 
|  | 382       // from: http://www.howtocreate.co.uk/tutorials/javascript/browserwindow | 
|  | 383       function get_scroll_xy() { | 
|  | 384         var scrOfX = 0, scrOfY = 0; | 
|  | 385         if( typeof( window.pageYOffset ) == 'number' ) { | 
|  | 386           //Netscape compliant | 
|  | 387           scrOfY = window.pageYOffset; | 
|  | 388           scrOfX = window.pageXOffset; | 
|  | 389         } else if( document.body && ( document.body.scrollLeft || document.body.scrollTop ) ) { | 
|  | 390           //DOM compliant | 
|  | 391           scrOfY = document.body.scrollTop; | 
|  | 392           scrOfX = document.body.scrollLeft; | 
|  | 393         } else if( document.documentElement && ( document.documentElement.scrollLeft || document.documentElement.scrollTop ) ) { | 
|  | 394           //IE6 standards compliant mode | 
|  | 395           scrOfY = document.documentElement.scrollTop; | 
|  | 396           scrOfX = document.documentElement.scrollLeft; | 
|  | 397         } | 
|  | 398         return [ scrOfX, scrOfY ]; | 
|  | 399       } | 
|  | 400 | 
|  | 401       // gets the width and height of the visible page | 
|  | 402       // from: http://www.howtocreate.co.uk/tutorials/javascript/browserwindow | 
|  | 403       function get_page_size() { | 
|  | 404         var myWidth = 0, myHeight = 0; | 
|  | 405         if( typeof( window.innerWidth ) == 'number' ) { | 
|  | 406           //Non-IE | 
|  | 407           myWidth = window.innerWidth; | 
|  | 408           myHeight = window.innerHeight; | 
|  | 409         } else if( document.documentElement && ( document.documentElement.clientWidth || document.documentElement.clientHeight ) ) { | 
|  | 410           //IE 6+ in 'standards compliant mode' | 
|  | 411           myWidth = document.documentElement.clientWidth; | 
|  | 412           myHeight = document.documentElement.clientHeight; | 
|  | 413         } else if( document.body && ( document.body.clientWidth || document.body.clientHeight ) ) { | 
|  | 414           //IE 4 compatible | 
|  | 415           myWidth = document.body.clientWidth; | 
|  | 416           myHeight = document.body.clientHeight; | 
|  | 417         } | 
|  | 418         return [myWidth, myHeight]; | 
|  | 419       } | 
|  | 420 | 
|  | 421       // gets the x and y offset of an element | 
|  | 422       // from http://www.quirksmode.org/js/findpos.html | 
|  | 423       function get_elem_xy(elem) { | 
|  | 424         var myX = myY = 0; | 
|  | 425         if (elem.offsetParent) { | 
|  | 426           do { | 
|  | 427             myX += elem.offsetLeft; | 
|  | 428             myY += elem.offsetTop; | 
|  | 429           } while (elem = elem.offsetParent); | 
|  | 430         } | 
|  | 431         return [myX, myY]; | 
|  | 432       } | 
|  | 433 | 
|  | 434       // | 
|  | 435       // Functions to delay a drawing task until it is required or it would not lag the display to do so | 
|  | 436       // | 
|  | 437 | 
|  | 438       // a list of items still to be drawn | 
|  | 439       var drawable_list = []; | 
|  | 440       // the delay between drawing objects that are not currently visible | 
|  | 441       var draw_delay = 1; | 
|  | 442       // the delay after a user interaction | 
|  | 443       var user_delay = 300; | 
|  | 444       // the delay after a user has stopped scrolling and is viewing the stuff drawn on the current page | 
|  | 445       var stop_delay = 2000; | 
|  | 446       // the timer handle; allows resetting of the timer after user interactions | 
|  | 447       var draw_timer = null; | 
|  | 448 | 
|  | 449       // | 
|  | 450       // Drawable | 
|  | 451       // | 
|  | 452       // elem - a page element which defines the position on the page that drawing is to be done | 
|  | 453       // task - an object with the method run which takes care of painting the object | 
|  | 454       // | 
|  | 455       function Drawable(elem, task) { | 
|  | 456         this.elem = elem; | 
|  | 457         this.task = task; | 
|  | 458         this.is_visible = Drawable_is_visible; | 
|  | 459       } | 
|  | 460 | 
|  | 461       // | 
|  | 462       // Drawable_is_visible | 
|  | 463       // | 
|  | 464       // Determines if the drawable object is in the visible part of the page. | 
|  | 465       // | 
|  | 466       // page_top - the distance to the top of the page for the visible region | 
|  | 467       // page_height - the height of the visible region | 
|  | 468       function Drawable_is_visible(page_top, page_height) { | 
|  | 469         var elem_top = get_elem_xy(this.elem)[1]; | 
|  | 470         var elem_height = this.elem.height; | 
|  | 471         if (typeof (elem_height) != 'number') elem_height = 1; | 
|  | 472         return ((elem_top + elem_height) >= page_top && elem_top <= (page_top + page_height)); | 
|  | 473       } | 
|  | 474 | 
|  | 475       // | 
|  | 476       // draw_on_screen | 
|  | 477       // | 
|  | 478       // Checks each drawable object and draws those on screen. | 
|  | 479       // | 
|  | 480       function draw_on_screen() { | 
|  | 481         var found = false; | 
|  | 482         var page_top = get_scroll_xy()[1]; | 
|  | 483         var page_height = get_page_size()[1]; | 
|  | 484         for (var i = 0; i < drawable_list.length; i++) { | 
|  | 485           var drawable = drawable_list[i]; | 
|  | 486           if (drawable.is_visible(page_top, page_height)) { | 
|  | 487             drawable.task.run(); | 
|  | 488             drawable_list.splice(i--, 1); | 
|  | 489             found = true; | 
|  | 490           } | 
|  | 491         } | 
|  | 492         return found; | 
|  | 493       } | 
|  | 494 | 
|  | 495       // | 
|  | 496       // process_draw_tasks | 
|  | 497       // | 
|  | 498       // Called on a delay to process the next avaliable | 
|  | 499       // draw task. | 
|  | 500       // | 
|  | 501       function process_draw_tasks() { | 
|  | 502         var delay = draw_delay; | 
|  | 503         draw_timer = null; | 
|  | 504         if (drawable_list.length == 0) return; //no more tasks | 
|  | 505         if (draw_on_screen()) { | 
|  | 506           delay = stop_delay; //give the user a chance to scroll | 
|  | 507         } else { | 
|  | 508           //get next task | 
|  | 509           var drawable = drawable_list.shift(); | 
|  | 510           drawable.task.run(); | 
|  | 511         } | 
|  | 512         //allow UI updates between tasks | 
|  | 513         draw_timer = window.setTimeout("process_draw_tasks()", draw_delay); | 
|  | 514       } | 
|  | 515 | 
|  | 516       // | 
|  | 517       // delayed_process_draw_tasks | 
|  | 518       // | 
|  | 519       // Call process_draw_tasks after a short delay. | 
|  | 520       // The delay serves to group multiple redundant events. | 
|  | 521       // Should be set as event handler for onscroll and onresize. | 
|  | 522       // | 
|  | 523       function delayed_process_draw_tasks() { | 
|  | 524         //reset the timer | 
|  | 525         if (drawable_list.length > 0) { | 
|  | 526           if (draw_timer != null) clearTimeout(draw_timer); | 
|  | 527           draw_timer = window.setTimeout("process_draw_tasks()", user_delay); | 
|  | 528         } | 
|  | 529       } | 
|  | 530 | 
|  | 531       // | 
|  | 532       // add_draw_task | 
|  | 533       // | 
|  | 534       // Add a drawing task to be called immediately if it is | 
|  | 535       // visible, or to be called on a delay to reduce stuttering | 
|  | 536       // effect on the web browser. | 
|  | 537       function add_draw_task(elem, task) { | 
|  | 538         var page_top = get_scroll_xy()[1]; | 
|  | 539         var page_height = get_page_size()[1]; | 
|  | 540         drawable = new Drawable(elem, task); | 
|  | 541         if (drawable.is_visible(page_top, page_height)) { | 
|  | 542           task.run(); | 
|  | 543         } else { | 
|  | 544           drawable_list.push(drawable); | 
|  | 545           //reset timer | 
|  | 546           if (draw_timer != null) clearTimeout(draw_timer); | 
|  | 547           draw_timer = window.setTimeout("process_draw_tasks()", user_delay); | 
|  | 548         } | 
|  | 549       } | 
|  | 550 | 
|  | 551     /* END INCLUDED FILE "delay_draw.js" */ | 
|  | 552 | 
|  | 553 | 
|  | 554 | 
|  | 555     /* START INCLUDED FILE "motif_logo.js" */ | 
|  | 556     //====================================================================== | 
|  | 557     // start Alphabet object | 
|  | 558     //====================================================================== | 
|  | 559     function Alphabet(alphabet, bg) { | 
|  | 560       //variable prototype | 
|  | 561       this.freqs = new Array(); | 
|  | 562       this.alphabet = new Array(); | 
|  | 563       this.letter_count = 0; | 
|  | 564       //method prototype | 
|  | 565       this.get_ic = Alphabet_get_ic; | 
|  | 566       this.get_size = Alphabet_get_size; | 
|  | 567       this.get_index = Alphabet_get_index; | 
|  | 568       this.get_letter = Alphabet_get_letter; | 
|  | 569       this.get_colour = Alphabet_get_colour; | 
|  | 570       this.get_bg_freq = Alphabet_get_bg_freq; | 
|  | 571       this.is_nucleotide = Alphabet_is_nucleotide; | 
|  | 572       this.is_ambig = Alphabet_is_ambig; | 
|  | 573       this.toString = Alphabet_to_string; | 
|  | 574       //construct | 
|  | 575       var is_letter = /^\w$/; | 
|  | 576       var is_prob = /^((1(\.0+)?)|(0(\.\d+)?))$/; | 
|  | 577       for (var pos = 0; pos < alphabet.length; pos++) { | 
|  | 578         var letter = alphabet.charAt(pos); | 
|  | 579         if (is_letter.test(letter)) { | 
|  | 580           this.alphabet[this.letter_count] = letter.toUpperCase(); | 
|  | 581           this.freqs[this.letter_count] = -1; | 
|  | 582           this.letter_count++; | 
|  | 583         } | 
|  | 584       } | 
|  | 585       if (!(bg === undefined)) { | 
|  | 586         var parts = bg.split(/\s+/); | 
|  | 587         for (var i = 0, pos = 0; (i + 1) < parts.length; i += 2) { | 
|  | 588           var letter = parts[i]; | 
|  | 589           var freq = parts[i+1]; | 
|  | 590           if (is_letter.test(letter) && is_prob.test(freq)) { | 
|  | 591             letter = letter.toUpperCase();          //find the letter it matches | 
|  | 592             for (;pos < this.letter_count; pos++) { | 
|  | 593               if (this.alphabet[pos] == letter) break; | 
|  | 594             } | 
|  | 595             if (pos >= this.letter_count) throw "NOT_IN_ALPHABET"; | 
|  | 596             this.freqs[pos] = (+freq); | 
|  | 597           } | 
|  | 598         } | 
|  | 599       } else { | 
|  | 600         //assume uniform background | 
|  | 601         var freq = 1.0 / this.letter_count; | 
|  | 602         for (var pos = 0; pos < this.letter_count; pos++) { | 
|  | 603           this.freqs[pos] = freq; | 
|  | 604         } | 
|  | 605       } | 
|  | 606     } | 
|  | 607 | 
|  | 608 | 
|  | 609     function Alphabet_get_ic() { | 
|  | 610       if (this.is_nucleotide()) { | 
|  | 611         return 2; | 
|  | 612       } else { | 
|  | 613         return Math.log(20) / Math.LN2; | 
|  | 614       } | 
|  | 615     } | 
|  | 616 | 
|  | 617     function Alphabet_get_size() { | 
|  | 618       return this.letter_count; | 
|  | 619     } | 
|  | 620 | 
|  | 621     function Alphabet_get_letter(alph_index) { | 
|  | 622       if (alph_index < 0 || alph_index >= this.letter_count) { | 
|  | 623         throw "BAD_ALPHABET_INDEX"; | 
|  | 624       } | 
|  | 625       return this.alphabet[alph_index]; | 
|  | 626     } | 
|  | 627 | 
|  | 628     function Alphabet_get_bg_freq(alph_index) { | 
|  | 629       if (alph_index < 0 || alph_index >= this.letter_count) { | 
|  | 630         throw "BAD_ALPHABET_INDEX"; | 
|  | 631       } | 
|  | 632       if (this.freqs[alph_index] == -1) throw "BG_FREQ_NOT_SET"; | 
|  | 633       return this.freqs[alph_index]; | 
|  | 634     } | 
|  | 635 | 
|  | 636     function Alphabet_get_colour(alph_index) { | 
|  | 637       var red = "rgb(204,0,0)"; | 
|  | 638       var blue = "rgb(0,0,204)"; | 
|  | 639       var orange = "rgb(255,179,0)"; | 
|  | 640       var green = "rgb(0,128,0)"; | 
|  | 641       var yellow = "rgb(255,255,0)"; | 
|  | 642       var purple = "rgb(204,0,204)"; | 
|  | 643       var magenta = "rgb(255,0,255)"; | 
|  | 644       var pink = "rgb(255,204,204)"; | 
|  | 645       var turquoise = "rgb(51,230,204)"; | 
|  | 646       if (alph_index < 0 || alph_index >= this.letter_count) { | 
|  | 647         throw "BAD_ALPHABET_INDEX"; | 
|  | 648       } | 
|  | 649       if (this.is_nucleotide()) { | 
|  | 650         switch (this.alphabet[alph_index]) { | 
|  | 651           case "A": | 
|  | 652             return red; | 
|  | 653           case "C": | 
|  | 654             return blue; | 
|  | 655           case "G": | 
|  | 656             return orange; | 
|  | 657           case "T": | 
|  | 658             return green; | 
|  | 659         } | 
|  | 660       } else { | 
|  | 661         switch (this.alphabet[alph_index]) { | 
|  | 662           case "A": | 
|  | 663           case "C": | 
|  | 664           case "F": | 
|  | 665           case "I": | 
|  | 666           case "L": | 
|  | 667           case "V": | 
|  | 668           case "W": | 
|  | 669           case "M": | 
|  | 670             return blue; | 
|  | 671           case "N": | 
|  | 672           case "Q": | 
|  | 673           case "S": | 
|  | 674           case "T": | 
|  | 675             return green; | 
|  | 676           case "D": | 
|  | 677           case "E": | 
|  | 678             return magenta; | 
|  | 679           case "K": | 
|  | 680           case "R": | 
|  | 681             return red; | 
|  | 682           case "H": | 
|  | 683             return pink; | 
|  | 684           case "G": | 
|  | 685             return orange; | 
|  | 686           case "P": | 
|  | 687             return yellow; | 
|  | 688           case "Y": | 
|  | 689             return turquoise; | 
|  | 690         } | 
|  | 691       } | 
|  | 692       return "black"; | 
|  | 693     } | 
|  | 694 | 
|  | 695     function Alphabet_is_ambig(alph_index) { | 
|  | 696       if (alph_index < 0 || alph_index >= this.letter_count) { | 
|  | 697         throw "BAD_ALPHABET_INDEX"; | 
|  | 698       } | 
|  | 699       if (this.is_nucleotide()) { | 
|  | 700         return ("ACGT".indexOf(this.alphabet[alph_index]) == -1); | 
|  | 701       } else { | 
|  | 702         return ("ACDEFGHIKLMNPQRSTVWY".indexOf(this.alphabet[alph_index]) == -1); | 
|  | 703       } | 
|  | 704     } | 
|  | 705 | 
|  | 706     function Alphabet_get_index(letter) { | 
|  | 707       for (i = 0; i < this.letter_count; i++) { | 
|  | 708         if (this.alphabet[i] == letter.toUpperCase()) return i; | 
|  | 709       } | 
|  | 710       throw "UNKNOWN_LETTER"; | 
|  | 711     } | 
|  | 712 | 
|  | 713     function Alphabet_is_nucleotide() { | 
|  | 714       //TODO basic method, make better | 
|  | 715       if (this.letter_count < 20) return true; | 
|  | 716       return false; | 
|  | 717     } | 
|  | 718 | 
|  | 719     function Alphabet_to_string() { | 
|  | 720       return (this.is_nucleotide() ? "Nucleotide" : "Protein") + " Alphabet " + (this.alphabet.join("")); | 
|  | 721     } | 
|  | 722 | 
|  | 723     //====================================================================== | 
|  | 724     // end Alphabet object | 
|  | 725     //====================================================================== | 
|  | 726 | 
|  | 727     //====================================================================== | 
|  | 728     // start Symbol object | 
|  | 729     //====================================================================== | 
|  | 730     function Symbol(alph_index, scale, alphabet) { | 
|  | 731       //variable prototype | 
|  | 732       this.symbol = alphabet.get_letter(alph_index); | 
|  | 733       this.scale = scale; | 
|  | 734       this.colour = alphabet.get_colour(alph_index); | 
|  | 735       //function prototype | 
|  | 736       this.get_symbol = Symbol_get_symbol; | 
|  | 737       this.get_scale = Symbol_get_scale; | 
|  | 738       this.get_colour = Symbol_get_colour; | 
|  | 739       this.toString = Symbol_to_string; | 
|  | 740     } | 
|  | 741 | 
|  | 742     function Symbol_get_symbol() { | 
|  | 743       return this.symbol; | 
|  | 744     } | 
|  | 745 | 
|  | 746     function Symbol_get_scale() { | 
|  | 747       return this.scale; | 
|  | 748     } | 
|  | 749 | 
|  | 750     function Symbol_get_colour() { | 
|  | 751       return this.colour; | 
|  | 752     } | 
|  | 753 | 
|  | 754     function Symbol_to_string() { | 
|  | 755       return this.symbol + " " + (Math.round(this.scale*1000)/10) + "%"; | 
|  | 756     } | 
|  | 757 | 
|  | 758     function compare_symbol(sym1, sym2) { | 
|  | 759       if (sym1.get_scale() < sym2.get_scale()) { | 
|  | 760         return -1; | 
|  | 761       } else if (sym1.get_scale() > sym2.get_scale()) { | 
|  | 762         return 1; | 
|  | 763       } else { | 
|  | 764         return 0; | 
|  | 765       } | 
|  | 766     } | 
|  | 767     //====================================================================== | 
|  | 768     // end Symbol object | 
|  | 769     //====================================================================== | 
|  | 770 | 
|  | 771     //====================================================================== | 
|  | 772     // start Pspm object | 
|  | 773     //====================================================================== | 
|  | 774     function Pspm(pspm, name, ltrim, rtrim, nsites, evalue) { | 
|  | 775       if (ltrim === undefined) ltrim = 0; | 
|  | 776       if (rtrim === undefined) rtrim = 0; | 
|  | 777       if (nsites === undefined) nsites = 0; | 
|  | 778       if (evalue === undefined) evalue = 0; | 
|  | 779       //variable prototype | 
|  | 780       this.alph_length = 0; | 
|  | 781       this.motif_length = 0; | 
|  | 782       this.pspm = null; | 
|  | 783       this.name = (typeof name == "string" ? name : ""); | 
|  | 784       this.nsites = nsites; | 
|  | 785       this.evalue = evalue; | 
|  | 786       this.ltrim = ltrim; | 
|  | 787       this.rtrim = rtrim; | 
|  | 788       //function prototype | 
|  | 789       this.copy = Pspm_copy; | 
|  | 790       this.reverse_complement = Pspm_reverse_complement; | 
|  | 791       this.get_stack = Pspm_get_stack; | 
|  | 792       this.get_stack_ic = Pspm_get_stack_ic; | 
|  | 793       this.get_motif_length = Pspm_get_motif_length; | 
|  | 794       this.get_alph_length = Pspm_get_alph_length; | 
|  | 795       this.get_left_trim = Pspm_get_left_trim; | 
|  | 796       this.get_right_trim = Pspm_get_right_trim; | 
|  | 797       this.as_pspm = Pspm_as_pspm; | 
|  | 798       this.as_pssm = Pspm_as_pssm; | 
|  | 799       this.toString = Pspm_to_string; | 
|  | 800       //construct | 
|  | 801       if (typeof pspm == "string") { | 
|  | 802         var pspm_header = /letter-probability matrix:\s+alength=\s+(\d+)\s+w=\s+(\d+)(\s+nsites=\s+(\S+))?(\s+E=\s+(\S+))?\s*/; | 
|  | 803         var lines = pspm.split(/\n/); | 
|  | 804         var read_pspm = false; | 
|  | 805         var line_num = 0; | 
|  | 806         var col_num = 0; | 
|  | 807         this.pspm = new Array(); | 
|  | 808         for (line_index in lines) { | 
|  | 809           //exclude inherited properties and undefined properties | 
|  | 810           if (!lines.hasOwnProperty(line_index) || lines[line_index] === undefined) continue; | 
|  | 811 | 
|  | 812           var line = trim(lines[line_index]); | 
|  | 813           if (line == '') { | 
|  | 814             continue; | 
|  | 815           } | 
|  | 816           if (!read_pspm) { | 
|  | 817             var header_match = pspm_header.exec(line); | 
|  | 818             if (header_match != null) { | 
|  | 819               read_pspm = true; | 
|  | 820               this.alph_length = (+header_match[1]); | 
|  | 821               this.motif_length = (+header_match[2]); | 
|  | 822               if (header_match[4]) this.nsites = parseFloat(header_match[4]);//not always an integer | 
|  | 823               if (header_match[6]) this.evalue = parseFloat(header_match[6]); | 
|  | 824               this.pspm = new Array(this.motif_length); | 
|  | 825             } | 
|  | 826             continue; | 
|  | 827           } | 
|  | 828           if (line_num >= this.motif_length) { | 
|  | 829             throw "TOO_MANY_ROWS"; | 
|  | 830           } | 
|  | 831           this.pspm[line_num] = new Array(this.alph_length); | 
|  | 832           col_num = 0; | 
|  | 833           var parts = line.split(/\s+/); | 
|  | 834           for (part_index in parts) { | 
|  | 835             //exclude inherited properties and undefined properties | 
|  | 836             if (!parts.hasOwnProperty(part_index) || parts[part_index] === undefined) continue; | 
|  | 837 | 
|  | 838             var prob = parts[part_index]; | 
|  | 839             if (col_num >= this.alph_length) { | 
|  | 840               throw "TOO_MANY_COLS"; | 
|  | 841             } | 
|  | 842             this.pspm[line_num][col_num] = (+prob); | 
|  | 843             //check the probability is within bounds | 
|  | 844             if (this.pspm[line_num][col_num] > 1 || this.pspm[line_num][col_num] < 0) { | 
|  | 845               throw "NUM_NOT_PROB"; | 
|  | 846             } | 
|  | 847             col_num++; | 
|  | 848           } | 
|  | 849           if (col_num != this.alph_length) { | 
|  | 850             throw "TOO_FEW_COLS"; | 
|  | 851           } | 
|  | 852         line_num++; | 
|  | 853         } | 
|  | 854         if (line_num != this.motif_length) { | 
|  | 855           throw "TOO_FEW_ROWS"; | 
|  | 856         } | 
|  | 857       } else { | 
|  | 858         // assume pspm is a nested array | 
|  | 859         this.motif_length = pspm.length; | 
|  | 860         this.alpha_length = (pspm.length > 0 ? pspm[0].length : 0); | 
|  | 861         this.pspm = new Array(this.motif_length); | 
|  | 862         // copy pspm and check | 
|  | 863         for (var row = 0; row < this.motif_length; row++) { | 
|  | 864           if (this.alpha_length != pspm[row].length) throw "COLUMN_MISMATCH"; | 
|  | 865           this.pspm[row] = new Array(this.alpha_length); | 
|  | 866           var row_sum = 0; | 
|  | 867           for (var col = 0; col < this.alpha_length; col++) { | 
|  | 868             row_sum += this.pspm[row][col]; | 
|  | 869             this.pspm[row][col] = 0 + pspm[row][col]; | 
|  | 870           } | 
|  | 871           var delta = 0.1 | 
|  | 872           if ((row_sum > 1 && (row_sum - 1) > delta) || | 
|  | 873               (row_sum < 1 && (1 - row_sum) > delta)) { | 
|  | 874             throw "INVALID_SUM"; | 
|  | 875           } | 
|  | 876         } | 
|  | 877       } | 
|  | 878     } | 
|  | 879 | 
|  | 880     function Clone() {} | 
|  | 881 | 
|  | 882     function Pspm_copy() { | 
|  | 883       Clone.prototype = this; | 
|  | 884       var clone = new Clone(); | 
|  | 885       //so far only a shallow copy, need to copy everything | 
|  | 886       clone.alph_length = (0+this.alph_length); | 
|  | 887       clone.motif_length = (0+this.motif_length); | 
|  | 888       clone.name = (""+this.name); | 
|  | 889       clone.nsites = (0+this.nsites); | 
|  | 890       clone.evalue = (0+this.evalue); | 
|  | 891       clone.ltrim = (0+this.ltrim); | 
|  | 892       clone.rtrim = (0+this.rtrim); | 
|  | 893       clone.pspm = new Array(this.motif_length); | 
|  | 894       for (row = 0; row < this.motif_length; row++) { | 
|  | 895         clone.pspm[row] = new Array(this.alph_length); | 
|  | 896         for (col = 0; col < this.alph_length; col++) { | 
|  | 897           clone.pspm[row][col] = (0+this.pspm[row][col]); | 
|  | 898         } | 
|  | 899       } | 
|  | 900       return clone; | 
|  | 901     } | 
|  | 902 | 
|  | 903     function Pspm_reverse_complement(alphabet) { | 
|  | 904       if (this.alph_length != alphabet.get_size()) { | 
|  | 905         throw "ALPHABET_MISMATCH"; | 
|  | 906       } | 
|  | 907       if (!alphabet.is_nucleotide()) { | 
|  | 908         throw "NO_PROTEIN_RC"; | 
|  | 909       } | 
|  | 910       //reverse | 
|  | 911       var x = 0; | 
|  | 912       var y = this.motif_length-1; | 
|  | 913       while (x < y) { | 
|  | 914         var temp = this.pspm[x]; | 
|  | 915         this.pspm[x] = this.pspm[y]; | 
|  | 916         this.pspm[y] = temp; | 
|  | 917         x++; | 
|  | 918         y--; | 
|  | 919       } | 
|  | 920       //complement | 
|  | 921       var a_index = alphabet.get_index("A"); | 
|  | 922       var c_index = alphabet.get_index("C"); | 
|  | 923       var g_index = alphabet.get_index("G"); | 
|  | 924       var t_index = alphabet.get_index("T"); | 
|  | 925       for (i = 0; i < this.motif_length; i++) { | 
|  | 926         var row = this.pspm[i]; | 
|  | 927         //swap A and T | 
|  | 928         var temp = row[a_index]; | 
|  | 929         row[a_index] = row[t_index]; | 
|  | 930         row[t_index] = temp; | 
|  | 931         //swap C and G | 
|  | 932         temp = row[c_index]; | 
|  | 933         row[c_index] = row[g_index]; | 
|  | 934         row[g_index] = temp; | 
|  | 935       } | 
|  | 936       //swap triming | 
|  | 937       var temp_trim = this.ltrim; | 
|  | 938       this.ltrim = this.rtrim; | 
|  | 939       this.rtrim = temp_trim; | 
|  | 940       //note that ambigs are ignored because they don't effect motifs | 
|  | 941       return this; //allow function chaining... | 
|  | 942     } | 
|  | 943 | 
|  | 944     function Pspm_get_stack(position, alphabet) { | 
|  | 945       if (this.alph_length != alphabet.get_size()) { | 
|  | 946         throw "ALPHABET_MISMATCH"; | 
|  | 947       } | 
|  | 948       var row = this.pspm[position]; | 
|  | 949       var stack_ic = this.get_stack_ic(position, alphabet); | 
|  | 950       var alphabet_ic = alphabet.get_ic(); | 
|  | 951       var stack = new Array(); | 
|  | 952       for (i = 0; i < this.alph_length; i++) { | 
|  | 953         if (alphabet.is_ambig(i)) continue; | 
|  | 954         var sym = new Symbol(i, row[i]*stack_ic/alphabet_ic, alphabet); | 
|  | 955         if (sym.get_scale() <= 0) continue; | 
|  | 956         stack.push(sym); | 
|  | 957       } | 
|  | 958       stack.sort(compare_symbol); | 
|  | 959       return stack; | 
|  | 960     } | 
|  | 961 | 
|  | 962     function Pspm_get_stack_ic(position, alphabet) { | 
|  | 963       if (this.alph_length != alphabet.get_size()) { | 
|  | 964         throw "ALPHABET_MISMATCH"; | 
|  | 965       } | 
|  | 966       var row = this.pspm[position]; | 
|  | 967       var H = 0; | 
|  | 968       for (var i = 0; i < this.alph_length; i++) { | 
|  | 969         if (alphabet.is_ambig(i)) continue; | 
|  | 970         if (row[i] == 0) continue; | 
|  | 971         H -= (row[i] * (Math.log(row[i]) / Math.LN2)); | 
|  | 972       } | 
|  | 973       return alphabet.get_ic() - H; | 
|  | 974     } | 
|  | 975 | 
|  | 976     function Pspm_get_error(alphabet) { | 
|  | 977       var asize; | 
|  | 978       if (this.nsites == 0) return 0; | 
|  | 979       if (alphabet.is_nucleotide()) { | 
|  | 980         asize = 4; | 
|  | 981       } else { | 
|  | 982         asize = 20; | 
|  | 983       } | 
|  | 984       return (asize-1) / (2 * Math.log(2)*this.nsites); | 
|  | 985     } | 
|  | 986 | 
|  | 987     function Pspm_get_motif_length() { | 
|  | 988       return this.motif_length; | 
|  | 989     } | 
|  | 990 | 
|  | 991     function Pspm_get_alph_length() { | 
|  | 992       return this.alph_length; | 
|  | 993     } | 
|  | 994 | 
|  | 995     function Pspm_get_left_trim() { | 
|  | 996       return this.ltrim; | 
|  | 997     } | 
|  | 998 | 
|  | 999     function Pspm_get_right_trim() { | 
|  | 1000       return this.rtrim; | 
|  | 1001     } | 
|  | 1002 | 
|  | 1003     function Pspm_as_pspm() { | 
|  | 1004       var out = "letter-probability matrix: alength= " + this.alph_length + | 
|  | 1005           " w= " + this.motif_length + " nsites= " + this.nsites + | 
|  | 1006           " E= " + this.evalue.toExponential() + "\n"; | 
|  | 1007       for (var row = 0; row < this.motif_length; row++) { | 
|  | 1008         for (var col = 0; col < this.alph_length; col++) { | 
|  | 1009           if (col != 0) out += " "; | 
|  | 1010           out += this.pspm[row][col].toFixed(6); | 
|  | 1011         } | 
|  | 1012         out += "\n"; | 
|  | 1013       } | 
|  | 1014       return out; | 
|  | 1015     } | 
|  | 1016 | 
|  | 1017     function Pspm_as_pssm(alphabet, pseudo) { | 
|  | 1018       if (typeof pseudo != "number") pseudo = 0.1; | 
|  | 1019       var out = "log-odds matrix: alength= " + this.alph_length + | 
|  | 1020           " w= " + this.motif_length + | 
|  | 1021           " E= " + this.evalue.toExponential() + "\n"; | 
|  | 1022       var log2 = Math.log(2); | 
|  | 1023       var total = this.nsites + pseudo; | 
|  | 1024       for (var row = 0; row < this.motif_length; row++) { | 
|  | 1025         for (var col = 0; col < this.alph_length; col++) { | 
|  | 1026           if (col != 0) out += " "; | 
|  | 1027           var p = this.pspm[row][col]; | 
|  | 1028           // to avoid log of zero we add a pseudo count | 
|  | 1029           var bg = alphabet.get_bg_freq(col); | 
|  | 1030           var p2 = (p * this.nsites + bg * pseudo) / total; | 
|  | 1031           // now calculate the score | 
|  | 1032           var score = -10000; | 
|  | 1033           if (p2 > 0) { | 
|  | 1034             score = Math.round((Math.log(p2 / bg) / log2) * 100) | 
|  | 1035           } | 
|  | 1036           out += score; | 
|  | 1037         } | 
|  | 1038         out += "\n"; | 
|  | 1039       } | 
|  | 1040       return out; | 
|  | 1041     } | 
|  | 1042 | 
|  | 1043     function Pspm_to_string() { | 
|  | 1044       var str = ""; | 
|  | 1045       for (row_index in this.pspm) { | 
|  | 1046         //exclude inherited properties and undefined properties | 
|  | 1047         if (!this.pspm.hasOwnProperty(row_index) || this.pspm[row_index] === undefined) continue; | 
|  | 1048 | 
|  | 1049         var row = this.pspm[row_index]; | 
|  | 1050         str += row.join("\t") + "\n"; | 
|  | 1051       } | 
|  | 1052       return str; | 
|  | 1053     } | 
|  | 1054     //====================================================================== | 
|  | 1055     // end Pspm object | 
|  | 1056     //====================================================================== | 
|  | 1057 | 
|  | 1058     //====================================================================== | 
|  | 1059     // start Logo object | 
|  | 1060     //====================================================================== | 
|  | 1061     function Logo(alphabet, fine_text) { | 
|  | 1062       this.alphabet = alphabet; | 
|  | 1063       this.fine_text = fine_text; | 
|  | 1064       this.pspm_list = []; | 
|  | 1065       this.pspm_column = []; | 
|  | 1066       this.rows = 0; | 
|  | 1067       this.columns = 0; | 
|  | 1068 | 
|  | 1069       //functions | 
|  | 1070       this.add_pspm = Logo_add_pspm; | 
|  | 1071       this.get_columns = Logo_get_columns; | 
|  | 1072       this.get_rows = Logo_get_rows; | 
|  | 1073       this.get_pspm = Logo_get_pspm; | 
|  | 1074       this.get_offset = Logo_get_offset; | 
|  | 1075     } | 
|  | 1076 | 
|  | 1077     function Logo_add_pspm(pspm, column) { | 
|  | 1078       if (column === undefined) column = 0; | 
|  | 1079       else if (column < 0) throw "COLUMN_OUT_OF_BOUNDS"; | 
|  | 1080       this.pspm_list[this.rows] = pspm; | 
|  | 1081       this.pspm_column[this.rows] = column; | 
|  | 1082       this.rows++; | 
|  | 1083       var col = column + pspm.get_motif_length(); | 
|  | 1084       if (col > this.columns) this.columns = col; | 
|  | 1085     } | 
|  | 1086 | 
|  | 1087     function Logo_get_columns() { | 
|  | 1088       return this.columns; | 
|  | 1089     } | 
|  | 1090 | 
|  | 1091     function Logo_get_rows() { | 
|  | 1092       return this.rows; | 
|  | 1093     } | 
|  | 1094 | 
|  | 1095     function Logo_get_pspm(row_index) { | 
|  | 1096       if (row_index < 0 || row_index >= this.rows) throw "INDEX_OUT_OF_BOUNDS"; | 
|  | 1097       return this.pspm_list[row_index]; | 
|  | 1098     } | 
|  | 1099 | 
|  | 1100     function Logo_get_offset(row_index) { | 
|  | 1101       if (row_index < 0 || row_index >= this.rows) throw "INDEX_OUT_OF_BOUNDS"; | 
|  | 1102       return this.pspm_column[row_index]; | 
|  | 1103     } | 
|  | 1104 | 
|  | 1105     //====================================================================== | 
|  | 1106     // end Logo object | 
|  | 1107     //====================================================================== | 
|  | 1108 | 
|  | 1109     //====================================================================== | 
|  | 1110     // start RasterizedAlphabet | 
|  | 1111     //====================================================================== | 
|  | 1112 | 
|  | 1113     // Rasterize Alphabet | 
|  | 1114     // 1) Measure width of text at default font for all symbols in alphabet | 
|  | 1115     // 2) sort in width ascending | 
|  | 1116     // 3) Drop the top and bottom 10% (designed to ignore outliers like 'W' and 'I') | 
|  | 1117     // 4) Calculate the average as the maximum scaling factor (designed to stop I becoming a rectangular blob). | 
|  | 1118     // 5) Assume scale of zero would result in width of zero, interpolate scale required to make perfect width font | 
|  | 1119     // 6) Draw text onto temp canvas at calculated scale | 
|  | 1120     // 7) Find bounds of drawn text | 
|  | 1121     // 8) Paint on to another canvas at the desired height (but only scaling width to fit if larger). | 
|  | 1122     function RasterizedAlphabet(alphabet, font, target_width) { | 
|  | 1123       //variable prototypes | 
|  | 1124       this.lookup = []; //a map of letter to index | 
|  | 1125       this.rasters = []; //a list of rasters | 
|  | 1126       this.dimensions = []; //a list of dimensions | 
|  | 1127 | 
|  | 1128       //function prototypes | 
|  | 1129       this.draw = RasterizedAlphabet_draw; | 
|  | 1130 | 
|  | 1131       //construct | 
|  | 1132       var default_size = 60; // size of square to assume as the default width | 
|  | 1133       var safety_pad = 20; // pixels to pad around so we don't miss the edges | 
|  | 1134       // create a canvas to do our rasterizing on | 
|  | 1135       var canvas = document.createElement("canvas"); | 
|  | 1136       // assume the default font would fit in a canvas of 100 by 100 | 
|  | 1137       canvas.width = default_size + 2 * safety_pad; | 
|  | 1138       canvas.height = default_size + 2 * safety_pad; | 
|  | 1139       // check for canvas support before attempting anything | 
|  | 1140       if (!canvas.getContext) throw "NO_CANVAS_SUPPORT"; | 
|  | 1141       var ctx = canvas.getContext('2d'); | 
|  | 1142       // check for html5 text drawing support | 
|  | 1143       if (!supports_text(ctx)) throw "NO_CANVAS_TEXT_SUPPORT"; | 
|  | 1144       // calculate the middle | 
|  | 1145       var middle = Math.round(canvas.width / 2); | 
|  | 1146       // calculate the baseline | 
|  | 1147       var baseline = Math.round(canvas.height - safety_pad); | 
|  | 1148       // list of widths | 
|  | 1149       var widths = []; | 
|  | 1150       var count = 0; | 
|  | 1151       var letters = []; | 
|  | 1152       //now measure each letter in the alphabet | 
|  | 1153       for (var i = 0; i < alphabet.get_size(); ++i) { | 
|  | 1154         if (alphabet.is_ambig(i)) continue; //skip ambigs as they're never rendered | 
|  | 1155         var letter = alphabet.get_letter(i); | 
|  | 1156         letters.push(letter); | 
|  | 1157         var pos = count++; | 
|  | 1158         this.lookup[letter] = pos; | 
|  | 1159         //clear the canvas | 
|  | 1160         canvas.width = canvas.width; | 
|  | 1161         // get the context and prepare to draw our width test | 
|  | 1162         var ctx = canvas.getContext('2d'); | 
|  | 1163         ctx.font = font; | 
|  | 1164         ctx.fillStyle = alphabet.get_colour(i); | 
|  | 1165         ctx.textAlign = "center"; | 
|  | 1166         ctx.translate(middle, baseline); | 
|  | 1167         // draw the test text | 
|  | 1168         ctx.fillText(letter, 0, 0); | 
|  | 1169         //measure | 
|  | 1170         var size = RasterizedAlphabet_measure(ctx, canvas.width, canvas.height); | 
|  | 1171         if (size.width == 0) throw "INVISIBLE_LETTER"; //maybe the fill was white on white? | 
|  | 1172         widths.push(size.width); | 
|  | 1173         this.dimensions[pos] = size; | 
|  | 1174       } | 
|  | 1175       //sort the widths | 
|  | 1176       widths.sort(function(a,b) {return a - b;}); | 
|  | 1177       //drop 10% of the items off each end | 
|  | 1178       var tenpercent = Math.floor(widths.length / 10); | 
|  | 1179       for (var i = 0; i < tenpercent; ++i) { | 
|  | 1180         widths.pop(); | 
|  | 1181         widths.shift(); | 
|  | 1182       } | 
|  | 1183       //calculate average width | 
|  | 1184       var avg_width = 0; | 
|  | 1185       for (var i = 0; i < widths.length; ++i) avg_width += widths[i]; | 
|  | 1186       avg_width /= widths.length; | 
|  | 1187       // calculate scales | 
|  | 1188       for (var i = 0; i < this.dimensions.length; ++i) { | 
|  | 1189         var size = this.dimensions[i]; | 
|  | 1190         // calculate scale | 
|  | 1191         var scale = target_width / Math.max(avg_width, size.width); | 
|  | 1192         // estimate scaled height | 
|  | 1193         var target_height = size.height * scale; | 
|  | 1194         // create an approprately sized canvas | 
|  | 1195         var raster = document.createElement("canvas"); | 
|  | 1196         raster.width = target_width; // if it goes over the edge too bad... | 
|  | 1197         raster.height = target_height + safety_pad * 2; | 
|  | 1198         // calculate the middle | 
|  | 1199         middle = Math.round(raster.width / 2); | 
|  | 1200         // calculate the baseline | 
|  | 1201         baseline = Math.round(raster.height - safety_pad); | 
|  | 1202         // get the context and prepare to draw the rasterized text | 
|  | 1203         ctx = raster.getContext('2d'); | 
|  | 1204         ctx.font = font; | 
|  | 1205         ctx.fillStyle = alphabet.get_colour(i); | 
|  | 1206         ctx.textAlign = "center"; | 
|  | 1207         ctx.translate(middle, baseline); | 
|  | 1208         ctx.save(); | 
|  | 1209         ctx.scale(scale, scale); | 
|  | 1210         // draw the rasterized text | 
|  | 1211         ctx.fillText(letters[i], 0, 0); | 
|  | 1212         ctx.restore(); | 
|  | 1213         this.rasters[i] = raster; | 
|  | 1214         this.dimensions[i] = RasterizedAlphabet_measure(ctx, raster.width, raster.height); | 
|  | 1215       } | 
|  | 1216     } | 
|  | 1217 | 
|  | 1218     function RasterizedAlphabet_measure(ctx, cwidth, cheight) { | 
|  | 1219       var data = ctx.getImageData(0, 0, cwidth, cheight).data; | 
|  | 1220       var r = 0, c = 0;// r: row, c: column | 
|  | 1221       var top_line = -1, bottom_line = -1, left_line = -1, right_line = -1; | 
|  | 1222       var txt_width = 0, txt_height = 0; | 
|  | 1223       // Find the top-most line with a non-white pixel | 
|  | 1224       for (r = 0; r < cheight; r++) { | 
|  | 1225         for (c = 0; c < cwidth; c++) { | 
|  | 1226           if (data[r * cwidth * 4 + c * 4 + 3]) { | 
|  | 1227             top_line = r; | 
|  | 1228             break; | 
|  | 1229           } | 
|  | 1230         } | 
|  | 1231         if (top_line != -1) break; | 
|  | 1232       } | 
|  | 1233 | 
|  | 1234       //find the last line with a non-white pixel | 
|  | 1235       if (top_line != -1) { | 
|  | 1236         for (r = cheight-1; r >= top_line; r--) { | 
|  | 1237           for(c = 0; c < cwidth; c++) { | 
|  | 1238             if(data[r * cwidth * 4 + c * 4 + 3]) { | 
|  | 1239               bottom_line = r; | 
|  | 1240               break; | 
|  | 1241             } | 
|  | 1242           } | 
|  | 1243           if (bottom_line != -1) break; | 
|  | 1244         } | 
|  | 1245         txt_height = bottom_line - top_line + 1; | 
|  | 1246       } | 
|  | 1247 | 
|  | 1248       // Find the left-most line with a non-white pixel | 
|  | 1249       for (c = 0; c < cwidth; c++) { | 
|  | 1250         for (r = 0; r < cheight; r++) { | 
|  | 1251           if (data[r * cwidth * 4 + c * 4 + 3]) { | 
|  | 1252             left_line = c; | 
|  | 1253             break; | 
|  | 1254           } | 
|  | 1255         } | 
|  | 1256         if (left_line != -1) break; | 
|  | 1257       } | 
|  | 1258 | 
|  | 1259       //find the right most line with a non-white pixel | 
|  | 1260       if (left_line != -1) { | 
|  | 1261         for (c = cwidth-1; c >= left_line; c--) { | 
|  | 1262           for(r = 0; r < cheight; r++) { | 
|  | 1263             if(data[r * cwidth * 4 + c * 4 + 3]) { | 
|  | 1264               right_line = c; | 
|  | 1265               break; | 
|  | 1266             } | 
|  | 1267           } | 
|  | 1268           if (right_line != -1) break; | 
|  | 1269         } | 
|  | 1270         txt_width = right_line - left_line + 1; | 
|  | 1271       } | 
|  | 1272 | 
|  | 1273       //return the bounds | 
|  | 1274       return {bound_top: top_line, bound_bottom: bottom_line, bound_left: left_line, bound_right: right_line, width: txt_width, height: txt_height}; | 
|  | 1275     } | 
|  | 1276 | 
|  | 1277     function RasterizedAlphabet_draw(ctx, letter, dx, dy, dWidth, dHeight) { | 
|  | 1278       var index = this.lookup[letter]; | 
|  | 1279       var raster = this.rasters[index]; | 
|  | 1280       var size = this.dimensions[index]; | 
|  | 1281       ctx.drawImage(raster, 0, size.bound_top -1, raster.width, size.height+1, dx, dy, dWidth, dHeight); | 
|  | 1282     } | 
|  | 1283 | 
|  | 1284     //====================================================================== | 
|  | 1285     // end RasterizedAlphabet | 
|  | 1286     //====================================================================== | 
|  | 1287 | 
|  | 1288     //====================================================================== | 
|  | 1289     // start LogoMetrics object | 
|  | 1290     //====================================================================== | 
|  | 1291 | 
|  | 1292     function LogoMetrics(ctx, canvas_width, canvas_height, logo_columns, logo_rows, allow_space_for_names) { | 
|  | 1293       if (allow_space_for_names === undefined) allow_space_for_names = false; | 
|  | 1294       //variable prototypes | 
|  | 1295       this.canvas_width = canvas_width; | 
|  | 1296       this.canvas_height = canvas_height; | 
|  | 1297       this.scale_x = 1; | 
|  | 1298       this.scale_y = 1; | 
|  | 1299       this.pad_top = 5; | 
|  | 1300       this.pad_left = 10; | 
|  | 1301       this.pad_right = 5; | 
|  | 1302       this.pad_bottom = 0; | 
|  | 1303       this.pad_middle = 20; | 
|  | 1304       this.name_height = 14; | 
|  | 1305       this.name_font = "bold " + this.name_height + "px Times, sans-serif"; | 
|  | 1306       this.name_spacer = 0; | 
|  | 1307       this.y_label = "bits" | 
|  | 1308       this.y_label_height = 12; | 
|  | 1309       this.y_label_font = "bold " + this.y_label_height + "px Helvetica, sans-serif"; | 
|  | 1310       this.y_label_spacer = 3; | 
|  | 1311       this.y_num_height = 12; | 
|  | 1312       this.y_num_width = 0; | 
|  | 1313       this.y_num_font = "bold " + this.y_num_height + "px Helvetica, sans-serif"; | 
|  | 1314       this.y_tic_width = 5; | 
|  | 1315       this.stack_pad_left = 0; | 
|  | 1316       this.stack_font = "bold 25px Helvetica, sans-serif"; | 
|  | 1317       this.stack_height = 90; | 
|  | 1318       this.stack_width = 26; | 
|  | 1319       this.stacks_pad_right = 5; | 
|  | 1320       this.x_num_above = 2; | 
|  | 1321       this.x_num_height = 12; | 
|  | 1322       this.x_num_width = 0; | 
|  | 1323       this.x_num_font = "bold " + this.x_num_height + "px Helvetica, sans-serif"; | 
|  | 1324       this.fine_txt_height = 6; | 
|  | 1325       this.fine_txt_above = 2; | 
|  | 1326       this.fine_txt_font = "normal " + this.fine_txt_height + "px Helvetica, sans-serif"; | 
|  | 1327       this.letter_metrics = new Array(); | 
|  | 1328       this.summed_width = 0; | 
|  | 1329       this.summed_height = 0; | 
|  | 1330       //function prototypes | 
|  | 1331       //none | 
|  | 1332       //calculate the width of the y axis numbers | 
|  | 1333       ctx.font = this.y_num_font; | 
|  | 1334       for (var i = 0; i <= 2; i++) { | 
|  | 1335         this.y_num_width = Math.max(this.y_num_width, ctx.measureText("" + i).width); | 
|  | 1336       } | 
|  | 1337       //calculate the width of the x axis numbers (but they are rotated so it becomes height) | 
|  | 1338       ctx.font = this.x_num_font; | 
|  | 1339       for (var i = 1; i <= logo_columns; i++) { | 
|  | 1340         this.x_num_width = Math.max(this.x_num_width, ctx.measureText("" + i).width); | 
|  | 1341       } | 
|  | 1342 | 
|  | 1343       //calculate how much vertical space we want to draw this | 
|  | 1344       //first we add the padding at the top and bottom since that's always there | 
|  | 1345       this.summed_height += this.pad_top + this.pad_bottom; | 
|  | 1346       //all except the last row have the same amount of space allocated to them | 
|  | 1347       if (logo_rows > 1) { | 
|  | 1348         var row_height = this.stack_height + this.pad_middle; | 
|  | 1349         if (allow_space_for_names) { | 
|  | 1350           row_height += this.name_height; | 
|  | 1351           //the label is allowed to overlap into the spacer | 
|  | 1352           row_height += Math.max(this.y_num_height/2, this.name_spacer); | 
|  | 1353           //the label is allowed to overlap the space used by the other label | 
|  | 1354           row_height += Math.max(this.y_num_height/2, this.x_num_height + this.x_num_above); | 
|  | 1355         } else { | 
|  | 1356           row_height += this.y_num_height/2; | 
|  | 1357           //the label is allowed to overlap the space used by the other label | 
|  | 1358           row_height += Math.max(this.y_num_height/2, this.x_num_height + this.x_num_above); | 
|  | 1359         } | 
|  | 1360         this.summed_height += row_height * (logo_rows - 1); | 
|  | 1361       } | 
|  | 1362       //the last row has the name and fine text below it but no padding | 
|  | 1363       this.summed_height += this.stack_height + this.y_num_height/2; | 
|  | 1364       if (allow_space_for_names) { | 
|  | 1365         this.summed_height += this.fine_txt_height + this.fine_txt_above + this.name_height; | 
|  | 1366         this.summed_height += Math.max(this.y_num_height/2, this.x_num_height + this.x_num_above + this.name_spacer); | 
|  | 1367       } else { | 
|  | 1368         this.summed_height += Math.max(this.y_num_height/2, this.x_num_height + this.x_num_above + this.fine_txt_height + this.fine_txt_above); | 
|  | 1369       } | 
|  | 1370 | 
|  | 1371       //calculate how much horizontal space we want to draw this | 
|  | 1372       //first add the padding at the left and right since that's always there | 
|  | 1373       this.summed_width += this.pad_left + this.pad_right; | 
|  | 1374       //add on the space for the y-axis label | 
|  | 1375       this.summed_width += this.y_label_height + this.y_label_spacer; | 
|  | 1376       //add on the space for the y-axis | 
|  | 1377       this.summed_width += this.y_num_width + this.y_tic_width; | 
|  | 1378       //add on the space for the stacks | 
|  | 1379       this.summed_width += (this.stack_pad_left + this.stack_width) * logo_columns; | 
|  | 1380       //add on the padding after the stacks (an offset from the fine text) | 
|  | 1381       this.summed_width += this.stacks_pad_right; | 
|  | 1382 | 
|  | 1383       //calculate scaling factors | 
|  | 1384       this.scale_y = this.canvas_height / this.summed_height; | 
|  | 1385       this.scale_x = this.canvas_width / this.summed_width; | 
|  | 1386 | 
|  | 1387       //maintain aspect ratio | 
|  | 1388       if (this.scale_y > this.scale_x) { | 
|  | 1389         this.scale_y = this.scale_x; | 
|  | 1390       } else { | 
|  | 1391         this.scale_x = this.scale_y; | 
|  | 1392       } | 
|  | 1393 | 
|  | 1394 | 
|  | 1395     } | 
|  | 1396 | 
|  | 1397     //====================================================================== | 
|  | 1398     // end LogoMetrics object | 
|  | 1399     //====================================================================== | 
|  | 1400 | 
|  | 1401 | 
|  | 1402     //found this trick at http://talideon.com/weblog/2005/02/detecting-broken-images-js.cfm | 
|  | 1403     function image_ok(img) { | 
|  | 1404       // During the onload event, IE correctly identifies any images that | 
|  | 1405       // weren't downloaded as not complete. Others should too. Gecko-based | 
|  | 1406       // browsers act like NS4 in that they report this incorrectly. | 
|  | 1407       if (!img.complete) { | 
|  | 1408         return false; | 
|  | 1409       } | 
|  | 1410       // However, they do have two very useful properties: naturalWidth and | 
|  | 1411       // naturalHeight. These give the true size of the image. If it failed | 
|  | 1412       // to load, either of these should be zero. | 
|  | 1413       if (typeof img.naturalWidth != "undefined" && img.naturalWidth == 0) { | 
|  | 1414         return false; | 
|  | 1415       } | 
|  | 1416       // No other way of checking: assume it's ok. | 
|  | 1417       return true; | 
|  | 1418     } | 
|  | 1419 | 
|  | 1420     function supports_text(ctx) { | 
|  | 1421       if (!ctx.fillText) return false; | 
|  | 1422       if (!ctx.measureText) return false; | 
|  | 1423       return true; | 
|  | 1424     } | 
|  | 1425 | 
|  | 1426     //draws the scale, returns the width | 
|  | 1427     function draw_scale(ctx, metrics, alphabet_ic) { | 
|  | 1428       var tic_height = metrics.stack_height / alphabet_ic; | 
|  | 1429       ctx.save(); | 
|  | 1430       ctx.lineWidth = 1.5; | 
|  | 1431       ctx.translate(metrics.y_label_height, metrics.y_num_height/2); | 
|  | 1432       //draw the axis label | 
|  | 1433       ctx.save(); | 
|  | 1434       ctx.font = metrics.y_label_font; | 
|  | 1435       ctx.translate(0, metrics.stack_height/2); | 
|  | 1436       ctx.save(); | 
|  | 1437       ctx.rotate(-(Math.PI / 2)); | 
|  | 1438       ctx.textAlign = "center"; | 
|  | 1439       ctx.fillText("bits", 0, 0); | 
|  | 1440       ctx.restore(); | 
|  | 1441       ctx.restore(); | 
|  | 1442 | 
|  | 1443       ctx.translate(metrics.y_label_spacer + metrics.y_num_width, 0); | 
|  | 1444 | 
|  | 1445       //draw the axis tics | 
|  | 1446       ctx.save(); | 
|  | 1447       ctx.translate(0, metrics.stack_height); | 
|  | 1448       ctx.font = metrics.y_num_font; | 
|  | 1449       ctx.textAlign = "right"; | 
|  | 1450       ctx.textBaseline = "middle"; | 
|  | 1451       for (var i = 0; i <= alphabet_ic; i++) { | 
|  | 1452         //draw the number | 
|  | 1453         ctx.fillText("" + i, 0, 0); | 
|  | 1454         //draw the tic | 
|  | 1455         ctx.beginPath(); | 
|  | 1456         ctx.moveTo(0, 0); | 
|  | 1457         ctx.lineTo(metrics.y_tic_width, 0); | 
|  | 1458         ctx.stroke(); | 
|  | 1459         //prepare for next tic | 
|  | 1460         ctx.translate(0, -tic_height); | 
|  | 1461       } | 
|  | 1462       ctx.restore(); | 
|  | 1463 | 
|  | 1464       ctx.translate(metrics.y_tic_width, 0); | 
|  | 1465 | 
|  | 1466       ctx.beginPath(); | 
|  | 1467       ctx.moveTo(0, 0); | 
|  | 1468       ctx.lineTo(0, metrics.stack_height); | 
|  | 1469       ctx.stroke(); | 
|  | 1470 | 
|  | 1471       ctx.restore(); | 
|  | 1472     } | 
|  | 1473 | 
|  | 1474     function draw_stack_num(ctx, metrics, row_index) { | 
|  | 1475       ctx.save(); | 
|  | 1476       ctx.font = metrics.x_num_font; | 
|  | 1477       ctx.translate(metrics.stack_width / 2, metrics.stack_height + metrics.x_num_above); | 
|  | 1478       ctx.save(); | 
|  | 1479       ctx.rotate(-(Math.PI / 2)); | 
|  | 1480       ctx.textBaseline = "middle" | 
|  | 1481       ctx.textAlign = "right" | 
|  | 1482       ctx.fillText("" + (row_index + 1), 0, 0); | 
|  | 1483       ctx.restore(); | 
|  | 1484       ctx.restore(); | 
|  | 1485     } | 
|  | 1486 | 
|  | 1487     function draw_stack(ctx, metrics, symbols, raster) { | 
|  | 1488       var preferred_pad = 0; | 
|  | 1489       var sym_min = 5; | 
|  | 1490 | 
|  | 1491       ctx.save();//1 | 
|  | 1492       ctx.translate(0, metrics.stack_height); | 
|  | 1493       for (var i in symbols) { | 
|  | 1494         //exclude inherited properties and undefined properties | 
|  | 1495         if (!symbols.hasOwnProperty(i) || symbols[i] === undefined) continue; | 
|  | 1496 | 
|  | 1497         var sym = symbols[i]; | 
|  | 1498         var sym_height = metrics.stack_height * sym.get_scale(); | 
|  | 1499 | 
|  | 1500         var pad = preferred_pad; | 
|  | 1501         if (sym_height - pad < sym_min) { | 
|  | 1502           pad = Math.min(pad, Math.max(0, sym_height - sym_min)); | 
|  | 1503         } | 
|  | 1504         sym_height -= pad; | 
|  | 1505 | 
|  | 1506         //translate to the correct position | 
|  | 1507         ctx.translate(0, -(pad/2 + sym_height)); | 
|  | 1508         //draw | 
|  | 1509         raster.draw(ctx, sym.get_symbol(), 0, 0, metrics.stack_width, sym_height); | 
|  | 1510         //translate past the padding | 
|  | 1511         ctx.translate(0, -(pad/2)); | 
|  | 1512       } | 
|  | 1513       ctx.restore();//1 | 
|  | 1514     } | 
|  | 1515 | 
|  | 1516     //draws a stack of symbols | 
|  | 1517     function draw_stack_old(ctx, metrics, symbols) { | 
|  | 1518       var lpad = 2; | 
|  | 1519       var sym_min = 5; | 
|  | 1520       var pos = metrics.stack_height; | 
|  | 1521       for (var i in symbols) { | 
|  | 1522         //exclude inherited properties and undefined properties | 
|  | 1523         if (!symbols.hasOwnProperty(i) || symbols[i] === undefined) continue; | 
|  | 1524 | 
|  | 1525         var sym = symbols[i]; | 
|  | 1526         var sym_height = metrics.stack_height*sym.get_scale(); | 
|  | 1527         var letter = metrics.get_letter_metrics(sym.get_symbol()); | 
|  | 1528         //attempting to draw something smaller than a pixel causes display corruption | 
|  | 1529         if (sym_height >= 1) { | 
|  | 1530           //it's better to see the letter than to pad it | 
|  | 1531           var pad = lpad; | 
|  | 1532           if (sym_height - pad < sym_min) { | 
|  | 1533             pad = Math.min(pad, Math.max(0, sym_height - sym_min)); | 
|  | 1534           } | 
|  | 1535           //move to the correct drawing position | 
|  | 1536           ctx.save();//s1 | 
|  | 1537           ctx.translate(0, pos); | 
|  | 1538           //create a clipping rectangle to ensure the letter doesn't overlap when it's distorted | 
|  | 1539           ctx.save();//s2 | 
|  | 1540           //ctx.beginPath(); //disabled clipping because after the improvements in the text metrics it looks better without | 
|  | 1541           //ctx.moveTo(-metrics.stack_width/2,0); | 
|  | 1542           //ctx.lineTo(metrics.stack_width/2, 0); | 
|  | 1543           //ctx.lineTo(metrics.stack_width/2, -sym_height); | 
|  | 1544           //ctx.lineTo(-metrics.stack_width/2, -sym_height); | 
|  | 1545           //ctx.lineTo(-metrics.stack_width/2,0); | 
|  | 1546           //ctx.clip(); | 
|  | 1547           //now draw | 
|  | 1548           ctx.translate(0, -(pad/2)); | 
|  | 1549           ctx.translate(0, -letter.get_descent(sym_height - pad)); | 
|  | 1550           ctx.fillStyle = sym.get_colour(); | 
|  | 1551           ctx.textAlign = "center"; | 
|  | 1552           ctx.save();//s3 | 
|  | 1553           ctx.scale(letter.wscale, letter.get_hscale(sym_height - pad)); | 
|  | 1554           ctx.fillText(sym.get_symbol(), 0, 0); | 
|  | 1555           ctx.restore();//s3 | 
|  | 1556 | 
|  | 1557           ctx.restore();//s2 | 
|  | 1558           ctx.restore();//s1 | 
|  | 1559         } | 
|  | 1560 | 
|  | 1561         pos = pos - sym_height; | 
|  | 1562       } | 
|  | 1563     } | 
|  | 1564 | 
|  | 1565     function draw_dashed_line(ctx, pattern, start, x1, y1, x2, y2) { | 
|  | 1566         var x, y, len, i; | 
|  | 1567         var dx = x2 - x1; | 
|  | 1568         var dy = y2 - y1; | 
|  | 1569         var tlen = Math.pow(dx*dx + dy*dy, 0.5); | 
|  | 1570         var theta = Math.atan2(dy,dx); | 
|  | 1571         var mulx = Math.cos(theta); | 
|  | 1572         var muly = Math.sin(theta); | 
|  | 1573         var lx = []; | 
|  | 1574         var ly = []; | 
|  | 1575         for (i = 0; i < pattern; ++i) { | 
|  | 1576           lx.push(pattern[i] * mulx); | 
|  | 1577           ly.push(pattern[i] * muly); | 
|  | 1578         } | 
|  | 1579         i = start; | 
|  | 1580         x = x1; | 
|  | 1581         y = y1; | 
|  | 1582         len = 0; | 
|  | 1583         ctx.beginPath(); | 
|  | 1584         while (len + pattern[i] < tlen) { | 
|  | 1585           ctx.moveTo(x, y); | 
|  | 1586           x += lx[i]; | 
|  | 1587           y += ly[i]; | 
|  | 1588           ctx.lineTo(x, y); | 
|  | 1589           len += pattern[i]; | 
|  | 1590           i = (i + 1) % pattern.length; | 
|  | 1591           x += lx[i]; | 
|  | 1592           y += ly[i]; | 
|  | 1593           len += pattern[i]; | 
|  | 1594           i = (i + 1) % pattern.length; | 
|  | 1595         } | 
|  | 1596         if (len < tlen) { | 
|  | 1597           ctx.moveTo(x, y); | 
|  | 1598           x += mulx * (tlen - len); | 
|  | 1599           y += muly * (tlen - len); | 
|  | 1600           ctx.lineTo(x, y); | 
|  | 1601         } | 
|  | 1602         ctx.stroke(); | 
|  | 1603     } | 
|  | 1604 | 
|  | 1605     function draw_trim_background(ctx, metrics, pspm, offset) { | 
|  | 1606       var lwidth = metrics.stack_width * pspm.get_left_trim(); | 
|  | 1607       var rwidth = metrics.stack_width * pspm.get_right_trim(); | 
|  | 1608       var mwidth = metrics.stack_width * pspm.get_motif_length(); | 
|  | 1609       var rstart = mwidth - rwidth; | 
|  | 1610       ctx.save();//s8 | 
|  | 1611       ctx.translate(offset * metrics.stack_width, 0); | 
|  | 1612       ctx.fillStyle = "rgb(240, 240, 240)"; | 
|  | 1613       if (pspm.get_left_trim() > 0) ctx.fillRect(0, 0, lwidth, metrics.stack_height); | 
|  | 1614       if (pspm.get_right_trim() > 0) ctx.fillRect(rstart, 0, rwidth, metrics.stack_height); | 
|  | 1615       ctx.fillStyle = "rgb(51, 51, 51)"; | 
|  | 1616       if (pspm.get_left_trim() > 0) draw_dashed_line(ctx, [3], 0, lwidth-0.5, 0, lwidth-0.5,  metrics.stack_height); | 
|  | 1617       if (pspm.get_right_trim() > 0) draw_dashed_line(ctx, [3], 0, rstart+0.5, 0, rstart+0.5,  metrics.stack_height); | 
|  | 1618       ctx.restore();//s8 | 
|  | 1619     } | 
|  | 1620 | 
|  | 1621     function draw_logo_on_canvas(logo, canvas, show_names, scale) { | 
|  | 1622       var draw_name = (typeof show_names == "boolean" ? show_names : (logo.get_rows() > 1)); | 
|  | 1623       var cwidth = canvas.width; | 
|  | 1624       var cheight = canvas.height; | 
|  | 1625       //need a minimum 46 x 120 canvas to draw the font size checks on | 
|  | 1626       if (canvas.width < 46) canvas.width = 46; | 
|  | 1627       if (canvas.height < 120) canvas.height = 120; | 
|  | 1628       var ctx = canvas.getContext('2d'); | 
|  | 1629       //assume that the user wants the canvas scaled equally so calculate what the best width for this image should be | 
|  | 1630       var metrics = new LogoMetrics(ctx, canvas.width, canvas.height, logo.get_columns(), logo.get_rows(), draw_name); | 
|  | 1631       ctx.save();//s1 | 
|  | 1632       if (typeof scale == "number") { | 
|  | 1633         //resize the canvas to fit the scaled logo | 
|  | 1634         cwidth = metrics.summed_width * scale; | 
|  | 1635         cheight = metrics.summed_height * scale; | 
|  | 1636       } else { | 
|  | 1637         if (cwidth == 0 && cheight == 0) { | 
|  | 1638           throw "CANVAS_MUST_HAVE_DIMENSIONS"; | 
|  | 1639         } else if (cwidth == 0) { | 
|  | 1640           scale = cheight / metrics.summed_height; | 
|  | 1641           cwidth = metrics.summed_width * scale; | 
|  | 1642         } else if (cheight == 0) { | 
|  | 1643           scale = cwidth / metrics.summed_width; | 
|  | 1644           cheight = metrics.summed_height * scale; | 
|  | 1645         } else { | 
|  | 1646           scale = Math.min(cwidth / metrics.summed_width, cheight / metrics.summed_height); | 
|  | 1647         } | 
|  | 1648       } | 
|  | 1649       var raster = new RasterizedAlphabet(logo.alphabet, metrics.stack_font, metrics.stack_width * scale * 2); | 
|  | 1650       if (cwidth != canvas.width || cheight != canvas.height) { | 
|  | 1651         canvas.width = cwidth; | 
|  | 1652         canvas.height = cheight; | 
|  | 1653         //as the canvas has been resized the context is now out of date | 
|  | 1654         ctx = canvas.getContext('2d'); | 
|  | 1655       } | 
|  | 1656       ctx.scale(scale, scale); | 
|  | 1657       ctx.save();//s2 | 
|  | 1658       ctx.save();//s7 | 
|  | 1659       //create margin | 
|  | 1660       ctx.translate(metrics.pad_left, metrics.pad_top); | 
|  | 1661       for (var pspm_i = 0; pspm_i < logo.get_rows(); ++pspm_i) { | 
|  | 1662         var pspm = logo.get_pspm(pspm_i); | 
|  | 1663         var offset = logo.get_offset(pspm_i); | 
|  | 1664         //optionally draw name if this isn't the last row or is the only row | 
|  | 1665         if (draw_name && (logo.get_rows() == 1 || pspm_i != (logo.get_rows()-1))) { | 
|  | 1666           ctx.save();//s4 | 
|  | 1667           ctx.translate(metrics.summed_width/2, metrics.name_height); | 
|  | 1668           ctx.font = metrics.name_font; | 
|  | 1669           ctx.textAlign = "center"; | 
|  | 1670           ctx.fillText(pspm.name, 0, 0); | 
|  | 1671           ctx.restore();//s4 | 
|  | 1672           ctx.translate(0, metrics.name_height + Math.min(0, metrics.name_spacer - metrics.y_num_height/2)); | 
|  | 1673         } | 
|  | 1674         //draw scale | 
|  | 1675         draw_scale(ctx, metrics, logo.alphabet.get_ic()); | 
|  | 1676         ctx.save();//s5 | 
|  | 1677         //translate across past the scale | 
|  | 1678         ctx.translate(metrics.y_label_height + metrics.y_label_spacer + | 
|  | 1679             metrics.y_num_width + metrics.y_tic_width, 0); | 
|  | 1680         //draw the trimming background | 
|  | 1681         if (pspm.get_left_trim() > 0 || pspm.get_right_trim() > 0) { | 
|  | 1682           draw_trim_background(ctx, metrics, pspm, offset); | 
|  | 1683         } | 
|  | 1684         //draw letters | 
|  | 1685         ctx.translate(0, metrics.y_num_height / 2); | 
|  | 1686         for (var col_index = 0; col_index < logo.get_columns(); col_index++) { | 
|  | 1687           ctx.translate(metrics.stack_pad_left,0); | 
|  | 1688           if (col_index >= offset && col_index < (offset + pspm.get_motif_length())) { | 
|  | 1689             var motif_position = col_index - offset; | 
|  | 1690             draw_stack_num(ctx, metrics, motif_position); | 
|  | 1691             draw_stack(ctx, metrics, pspm.get_stack(motif_position, logo.alphabet), raster); | 
|  | 1692           } | 
|  | 1693           ctx.translate(metrics.stack_width, 0); | 
|  | 1694         } | 
|  | 1695         ctx.restore();//s5 | 
|  | 1696         ////optionally draw name if this is the last row but isn't the only row | 
|  | 1697         if (draw_name && (logo.get_rows() != 1 && pspm_i == (logo.get_rows()-1))) { | 
|  | 1698           //translate vertically past the stack and axis's | 
|  | 1699           ctx.translate(0, metrics.y_num_height/2 + metrics.stack_height + | 
|  | 1700               Math.max(metrics.y_num_height/2, metrics.x_num_above + metrics.x_num_width + metrics.name_spacer)); | 
|  | 1701 | 
|  | 1702           ctx.save();//s6 | 
|  | 1703           ctx.translate(metrics.summed_width/2, metrics.name_height); | 
|  | 1704           ctx.font = metrics.name_font; | 
|  | 1705           ctx.textAlign = "center"; | 
|  | 1706           ctx.fillText(pspm.name, 0, 0); | 
|  | 1707           ctx.restore();//s6 | 
|  | 1708           ctx.translate(0, metrics.name_height); | 
|  | 1709         } else { | 
|  | 1710           //translate vertically past the stack and axis's | 
|  | 1711           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)); | 
|  | 1712         } | 
|  | 1713         //if not the last row then add middle padding | 
|  | 1714         if (pspm_i != (logo.get_rows() -1)) { | 
|  | 1715           ctx.translate(0, metrics.pad_middle); | 
|  | 1716         } | 
|  | 1717       } | 
|  | 1718       ctx.restore();//s7 | 
|  | 1719       ctx.translate(metrics.summed_width - metrics.pad_right, metrics.summed_height - metrics.pad_bottom); | 
|  | 1720       ctx.font = metrics.fine_txt_font; | 
|  | 1721       ctx.textAlign = "right"; | 
|  | 1722       ctx.fillText(logo.fine_text, 0,0); | 
|  | 1723       ctx.restore();//s2 | 
|  | 1724       ctx.restore();//s1 | 
|  | 1725     } | 
|  | 1726 | 
|  | 1727     function create_canvas(c_width, c_height, c_id, c_title, c_display) { | 
|  | 1728       var canvas = document.createElement("canvas"); | 
|  | 1729       //check for canvas support before attempting anything | 
|  | 1730       if (!canvas.getContext) return null; | 
|  | 1731       var ctx = canvas.getContext('2d'); | 
|  | 1732       //check for html5 text drawing support | 
|  | 1733       if (!supports_text(ctx)) return null; | 
|  | 1734       //size the canvas | 
|  | 1735       canvas.width = c_width; | 
|  | 1736       canvas.height = c_height; | 
|  | 1737       canvas.id = c_id; | 
|  | 1738       canvas.title = c_title; | 
|  | 1739       canvas.style.display = c_display; | 
|  | 1740       return canvas; | 
|  | 1741     } | 
|  | 1742 | 
|  | 1743     function logo_1(alphabet, fine_text, pspm) { | 
|  | 1744       var logo = new Logo(alphabet, fine_text); | 
|  | 1745       logo.add_pspm(pspm); | 
|  | 1746       return logo; | 
|  | 1747     } | 
|  | 1748 | 
|  | 1749     function logo_2(alphabet, fine_text, target, query, query_offset) { | 
|  | 1750       var logo = new Logo(alphabet, fine_text); | 
|  | 1751       if (query_offset < 0) { | 
|  | 1752         logo.add_pspm(target, -query_offset); | 
|  | 1753         logo.add_pspm(query); | 
|  | 1754       } else { | 
|  | 1755         logo.add_pspm(target); | 
|  | 1756         logo.add_pspm(query, query_offset); | 
|  | 1757       } | 
|  | 1758       return logo; | 
|  | 1759     } | 
|  | 1760 | 
|  | 1761     /* | 
|  | 1762      * Specifies an alternate source for an image. | 
|  | 1763      * If the image with the image_id specified has | 
|  | 1764      * not loaded then a generated logo will be used | 
|  | 1765      * to replace it. | 
|  | 1766      * | 
|  | 1767      * Note that the image must either have dimensions | 
|  | 1768      * or a scale must be set. | 
|  | 1769      */ | 
|  | 1770     function alternate_logo(logo, image_id, scale) { | 
|  | 1771       var image = document.getElementById(image_id); | 
|  | 1772       if (!image) { | 
|  | 1773         alert("Can't find specified image id (" +  image_id + ")"); | 
|  | 1774         return; | 
|  | 1775       } | 
|  | 1776       //if the image has loaded then there is no reason to use the canvas | 
|  | 1777       if (image_ok(image)) return; | 
|  | 1778       //the image has failed to load so replace it with a canvas if we can. | 
|  | 1779       var canvas = create_canvas(image.width, image.height, image_id, image.title, image.style.display); | 
|  | 1780       if (canvas == null) return; | 
|  | 1781       //draw the logo on the canvas | 
|  | 1782       draw_logo_on_canvas(logo, canvas, undefined, scale); | 
|  | 1783       //replace the image with the canvas | 
|  | 1784       image.parentNode.replaceChild(canvas, image); | 
|  | 1785     } | 
|  | 1786 | 
|  | 1787     /* | 
|  | 1788      * Specifes that the element with the specified id | 
|  | 1789      * should be replaced with a generated logo. | 
|  | 1790      */ | 
|  | 1791     function replace_logo(logo, replace_id, scale, title_txt, display_style) { | 
|  | 1792       var element = document.getElementById(replace_id); | 
|  | 1793       if (!replace_id) { | 
|  | 1794         alert("Can't find specified id (" + replace_id + ")"); | 
|  | 1795         return; | 
|  | 1796       } | 
|  | 1797       //found the element! | 
|  | 1798       var canvas = create_canvas(50, 120, replace_id, title_txt, display_style); | 
|  | 1799       if (canvas == null) return; | 
|  | 1800       //draw the logo on the canvas | 
|  | 1801       draw_logo_on_canvas(logo, canvas, undefined, scale); | 
|  | 1802       //replace the element with the canvas | 
|  | 1803       element.parentNode.replaceChild(canvas, element); | 
|  | 1804     } | 
|  | 1805 | 
|  | 1806     /* | 
|  | 1807      * Fast string trimming implementation found at | 
|  | 1808      * http://blog.stevenlevithan.com/archives/faster-trim-javascript | 
|  | 1809      * | 
|  | 1810      * Note that regex is good at removing leading space but | 
|  | 1811      * bad at removing trailing space as it has to first go through | 
|  | 1812      * the whole string. | 
|  | 1813      */ | 
|  | 1814     function trim (str) { | 
|  | 1815       str = str.replace(/^\s\s*/, ''); | 
|  | 1816       var ws = /\s/, i = str.length; | 
|  | 1817       while (ws.test(str.charAt(--i))); | 
|  | 1818       return str.slice(0, i + 1); | 
|  | 1819     } | 
|  | 1820     /* END INCLUDED FILE "motif_logo.js" */ | 
|  | 1821 | 
|  | 1822 | 
|  | 1823 | 
|  | 1824     /* START INCLUDED FILE "dreme-to-html.js" */ | 
|  | 1825       var expansion_lookup = []; | 
|  | 1826 | 
|  | 1827       /* | 
|  | 1828        * show_hidden | 
|  | 1829        * | 
|  | 1830        * Looks for specially named elements and switches to the shown view | 
|  | 1831        */ | 
|  | 1832       function show_hidden(prefix) { | 
|  | 1833         document.getElementById(prefix + '_activator').style.display = 'none'; | 
|  | 1834         document.getElementById(prefix + '_deactivator').style.display = 'block'; | 
|  | 1835         document.getElementById(prefix + '_data').style.display = 'block'; | 
|  | 1836       } | 
|  | 1837       /* | 
|  | 1838        * hide_shown | 
|  | 1839        * | 
|  | 1840        * Looks for specially named elements and switches to the hidden view | 
|  | 1841        */ | 
|  | 1842       function hide_shown(prefix) { | 
|  | 1843         document.getElementById(prefix + '_activator').style.display = 'block'; | 
|  | 1844         document.getElementById(prefix + '_deactivator').style.display = 'none'; | 
|  | 1845         document.getElementById(prefix + '_data').style.display = 'none'; | 
|  | 1846       } | 
|  | 1847 | 
|  | 1848       function click_download_tab(tab) { | 
|  | 1849         document.getElementById("download_tab_num").value = tab; | 
|  | 1850         for (var i = 1; i <= 3; i++) { | 
|  | 1851           document.getElementById('download_tab_'+i).className = "tab" + (i==tab ? " activeTab" : ""); | 
|  | 1852           document.getElementById('download_pnl_'+i).style.display = (i==tab ? "block" : "none"); | 
|  | 1853         } | 
|  | 1854         document.getElementById('download_button').style.visibility = (tab==3 ? "visible" : "hidden"); | 
|  | 1855       } | 
|  | 1856 | 
|  | 1857 | 
|  | 1858       /* | 
|  | 1859        * searches child nodes in depth first order and returns the | 
|  | 1860        * first it finds with the className specified. | 
|  | 1861        */ | 
|  | 1862       function find_child_element_by_class(node, className) { | 
|  | 1863         var patt = new RegExp("\\b" + className + "\\b"); | 
|  | 1864 | 
|  | 1865         if (node.nodeType == Node.ELEMENT_NODE && | 
|  | 1866             patt.test(node.className)) { | 
|  | 1867           return node; | 
|  | 1868         } else { | 
|  | 1869           var result = null; | 
|  | 1870           for (var i = 0; i < node.childNodes.length; i++) { | 
|  | 1871             result = find_child_element_by_class(node.childNodes[i], className); | 
|  | 1872             if (result != null) break; | 
|  | 1873           } | 
|  | 1874           return result; | 
|  | 1875         } | 
|  | 1876       } | 
|  | 1877 | 
|  | 1878       function find_parent_element_by_class(node, className) { | 
|  | 1879         var patt = new RegExp("\\b" + className + "\\b"); | 
|  | 1880         if (node.nodeType == Node.ELEMENT_NODE && | 
|  | 1881             patt.test(node.className)) { | 
|  | 1882           return node; | 
|  | 1883         } else if (node.parentNode != null) { | 
|  | 1884           return find_parent_element_by_class(node.parentNode, className); | 
|  | 1885         } | 
|  | 1886         return null; | 
|  | 1887       } | 
|  | 1888 | 
|  | 1889       /* | 
|  | 1890        * expand | 
|  | 1891        * | 
|  | 1892        * Expand the extra data section for a motif. | 
|  | 1893        */ | 
|  | 1894       function expand(num) { | 
|  | 1895         // get motif data | 
|  | 1896         var motif_info = motif_seqs[num]; | 
|  | 1897         var motif_id = motif_info[0]; | 
|  | 1898         var seq = motif_info[1]; | 
|  | 1899         var rcseq = motif_info[2]; | 
|  | 1900         var length = motif_info[3]; | 
|  | 1901         var nsites = motif_info[4]; | 
|  | 1902         var p_hits = motif_info[5]; | 
|  | 1903         var n_hits = motif_info[6]; | 
|  | 1904         var pvalue = motif_info[7]; | 
|  | 1905         var evalue = motif_info[8]; | 
|  | 1906         var uevalue = motif_info[9]; | 
|  | 1907         var matches = motif_info[10]; | 
|  | 1908         // find the location to insert the expanded motif data | 
|  | 1909         var table = document.getElementById('dreme_motifs'); | 
|  | 1910         var motif_row = document.getElementById('motif_row_' + num); | 
|  | 1911         var exp_row = table.insertRow(motif_row.rowIndex + 1); | 
|  | 1912         exp_row.id = 'exp_row_' + num; | 
|  | 1913         var cell = exp_row.insertCell(0); | 
|  | 1914         cell.colSpan = 9; | 
|  | 1915         // create the DOM to insert | 
|  | 1916         var exp = document.getElementById('expanded_motif').firstChild.cloneNode(true); | 
|  | 1917         // update fields | 
|  | 1918         set_content_to_text(find_child_element_by_class(exp, 'name'), seq); | 
|  | 1919         set_content_to_text(find_child_element_by_class(exp, 'num'), num); | 
|  | 1920         var img = find_child_element_by_class(exp, 'img_nc'); | 
|  | 1921         img.src = motif_id + "nc_" + seq + ".png"; | 
|  | 1922         var imgrc = find_child_element_by_class(exp, 'img_rc'); | 
|  | 1923         imgrc.src = motif_id + "rc_" + rcseq + ".png"; | 
|  | 1924         // fill in the details | 
|  | 1925         var details = find_child_element_by_class(exp, 'details'); | 
|  | 1926         set_content_to_text(find_child_element_by_class(details, 'positives'), p_hits); | 
|  | 1927         set_content_to_text(find_child_element_by_class(details, 'negatives'), n_hits); | 
|  | 1928         set_content_to_text(find_child_element_by_class(details, 'pvalue'), pvalue); | 
|  | 1929         set_content_to_text(find_child_element_by_class(details, 'evalue'), evalue); | 
|  | 1930         set_content_to_text(find_child_element_by_class(details, 'uevalue'), uevalue); | 
|  | 1931 | 
|  | 1932         // fill in match table | 
|  | 1933         var match_row = find_child_element_by_class(exp, 'match'); | 
|  | 1934         var tbody = match_row.parentNode; | 
|  | 1935         for (var i = 0; i < matches.length; i++) { | 
|  | 1936           var match = matches[i]; | 
|  | 1937           var cseq = match[0]; | 
|  | 1938           var cpos = match[1]; | 
|  | 1939           var cneg = match[2]; | 
|  | 1940           var cpval = match[3].toExponential(1); | 
|  | 1941           var ceval = match[4].toExponential(1); | 
|  | 1942           var row = match_row.cloneNode(true); | 
|  | 1943           var td_cseq = find_child_element_by_class(row, 'dnaseq'); | 
|  | 1944           set_content_to_text(td_cseq, cseq); | 
|  | 1945           colour_dna_seq(td_cseq); | 
|  | 1946           set_content_to_text(find_child_element_by_class(row, 'positives'), cpos); | 
|  | 1947           set_content_to_text(find_child_element_by_class(row, 'negatives'), cneg); | 
|  | 1948           set_content_to_text(find_child_element_by_class(row, 'pvalue'), cpval); | 
|  | 1949           set_content_to_text(find_child_element_by_class(row, 'evalue'), ceval); | 
|  | 1950           tbody.appendChild(row); | 
|  | 1951         } | 
|  | 1952         tbody.removeChild(match_row); | 
|  | 1953         // append the expanded information | 
|  | 1954         cell.appendChild(exp); | 
|  | 1955         // hide the old row | 
|  | 1956         motif_row.style.display = 'none'; | 
|  | 1957         update_headers(); | 
|  | 1958       } | 
|  | 1959 | 
|  | 1960       function expanded_num(elem) { | 
|  | 1961         var exp = find_parent_element_by_class(elem, 'expanded_motif'); | 
|  | 1962         var num = parseInt(nodes_text(text_nodes(find_child_element_by_class(exp, 'num')))); | 
|  | 1963         return num; | 
|  | 1964       } | 
|  | 1965 | 
|  | 1966       function contract(contained_node) { | 
|  | 1967         var table = document.getElementById('dreme_motifs'); | 
|  | 1968         var num = expanded_num(contained_node); | 
|  | 1969         var motif_row = document.getElementById('motif_row_' + num); | 
|  | 1970         var exp_row = document.getElementById('exp_row_' + num); | 
|  | 1971 | 
|  | 1972         motif_row.style.display = 'table-row'; | 
|  | 1973         table.deleteRow(exp_row.rowIndex); | 
|  | 1974         update_headers(); | 
|  | 1975       } | 
|  | 1976 | 
|  | 1977       function update_headers() { | 
|  | 1978         var motif_row_patt = new RegExp("\\bmotif_row\\b"); | 
|  | 1979         var motif_head_patt = new RegExp("\\bmotif_head\\b"); | 
|  | 1980         var table = document.getElementById('dreme_motifs'); | 
|  | 1981         var header = table.tHead.getElementsByTagName('tr')[0]; | 
|  | 1982         header.style.display = 'none'; | 
|  | 1983         var trs = table.tBodies[0].getElementsByTagName('tr'); | 
|  | 1984         var needHeader = true; | 
|  | 1985         for (var i = 0; i < trs.length; i++) { | 
|  | 1986           var row = trs[i]; | 
|  | 1987           if (row.style.display == 'none') continue; | 
|  | 1988           if (motif_row_patt.test(row.className)) { | 
|  | 1989             if (needHeader) { | 
|  | 1990               var dupHeader = header.cloneNode(true); | 
|  | 1991               dupHeader.style.display = 'table-row'; | 
|  | 1992               row.parentNode.insertBefore(dupHeader, row); | 
|  | 1993               needHeader = false; | 
|  | 1994               i++; | 
|  | 1995             } | 
|  | 1996           } else if (motif_head_patt.test(row.className)) { | 
|  | 1997             table.deleteRow(row.rowIndex); | 
|  | 1998             i--; | 
|  | 1999           } else { | 
|  | 2000             needHeader = true; | 
|  | 2001           } | 
|  | 2002         } | 
|  | 2003       } | 
|  | 2004 | 
|  | 2005       function set_content_to_text(ele, text) { | 
|  | 2006         while(ele.hasChildNodes()) { | 
|  | 2007           ele.removeChild(ele.firstChild); | 
|  | 2008         } | 
|  | 2009         ele.appendChild(document.createTextNode(text)); | 
|  | 2010       } | 
|  | 2011 | 
|  | 2012       function both_setup(pos) { | 
|  | 2013         // get the total number of motifs | 
|  | 2014         var nmotifs = parseInt(document.getElementById('nmotifs').value, 10); | 
|  | 2015         // set the motif that we're submitting | 
|  | 2016         document.getElementById('submit_motif').value = (pos == 0 ? 'all' : pos); | 
|  | 2017         document.getElementById('send_to_selector').style.display = (pos == 0 ? 'none' : 'block'); | 
|  | 2018         document.getElementById('send_to_title_1').style.display = (pos == 0 ? 'none' : 'block'); | 
|  | 2019         document.getElementById('send_to_title_2').style.display = (pos == 0 ? 'block' : 'none'); | 
|  | 2020 | 
|  | 2021         if (pos != 0) { | 
|  | 2022           // get the information for the position | 
|  | 2023           var motif_seq = motif_seqs[pos]; | 
|  | 2024           var motif_id = motif_seq[0]; | 
|  | 2025           var seq = motif_seq[1]; | 
|  | 2026           var rcseq = motif_seq[2]; | 
|  | 2027           // set the motif number | 
|  | 2028           // set the titles of both popups | 
|  | 2029           set_content_to_text(document.getElementById('send_to_name'), seq); | 
|  | 2030           set_content_to_text(document.getElementById('download_name'), seq); | 
|  | 2031           // set the images | 
|  | 2032           var nc_img = "" + motif_id + "nc_" + seq + ".png"; | 
|  | 2033           var rc_img = "" + motif_id + "rc_" + rcseq + ".png"; | 
|  | 2034           var img; | 
|  | 2035           img = document.getElementById('send_to_img'); | 
|  | 2036           img.src = nc_img; | 
|  | 2037           img.style.display = "inline"; | 
|  | 2038           img = document.getElementById('send_to_rcimg'); | 
|  | 2039           img.src = rc_img; | 
|  | 2040           img.style.display = "inline"; | 
|  | 2041           img = document.getElementById('download_img'); | 
|  | 2042           img.src = nc_img; | 
|  | 2043           img.style.display = "inline"; | 
|  | 2044           img = document.getElementById('download_rcimg'); | 
|  | 2045           img.src = rc_img; | 
|  | 2046           img.style.display = "inline"; | 
|  | 2047           // hide the canvas | 
|  | 2048           document.getElementById('send_to_can').style.display = "none"; | 
|  | 2049           document.getElementById('send_to_rccan').style.display = "none"; | 
|  | 2050           document.getElementById('download_can').style.display = "none"; | 
|  | 2051           document.getElementById('download_rccan').style.display = "none"; | 
|  | 2052           // get some motif details | 
|  | 2053           var pspm_text = document.getElementById("pspm"+ pos).value; | 
|  | 2054           var pspm = new Pspm(pspm_text); | 
|  | 2055           var alpha = new Alphabet(document.getElementById("alphabet").value, | 
|  | 2056               document.getElementById("bgfreq").value); | 
|  | 2057           document.getElementById('download_pspm').value = pspm.as_pspm(); | 
|  | 2058           document.getElementById('download_pssm').value = pspm.as_pssm(alpha); | 
|  | 2059           // set the width and height defaults | 
|  | 2060           document.getElementById('logo_width').value = pspm.get_motif_length(); | 
|  | 2061           document.getElementById('logo_height').value = 7.5; | 
|  | 2062           // hide and show the arrows | 
|  | 2063           var prevclass = (pos == 1 ? "navarrow inactive" : "navarrow"); | 
|  | 2064           var nextclass = (pos == nmotifs ? "navarrow inactive" : "navarrow"); | 
|  | 2065           document.getElementById('prev_arrow_1').className = prevclass; | 
|  | 2066           document.getElementById('prev_arrow_2').className = prevclass; | 
|  | 2067           document.getElementById('next_arrow_1').className = nextclass; | 
|  | 2068           document.getElementById('next_arrow_2').className = nextclass; | 
|  | 2069           set_content_to_text(document.getElementById('pop_num_1'), pos); | 
|  | 2070           set_content_to_text(document.getElementById('pop_num_2'), pos); | 
|  | 2071         } | 
|  | 2072       } | 
|  | 2073 | 
|  | 2074       function both_change(inc) { | 
|  | 2075         var motif_num = parseInt(document.getElementById('submit_motif').value, 10); | 
|  | 2076         var nmotifs = parseInt(document.getElementById('nmotifs').value, 10); | 
|  | 2077         var orig = motif_num; | 
|  | 2078         motif_num += inc; | 
|  | 2079         if (motif_num > nmotifs) motif_num = nmotifs; | 
|  | 2080         else if (motif_num < 1) motif_num = 1; | 
|  | 2081         if (orig != motif_num) both_setup(motif_num); | 
|  | 2082       } | 
|  | 2083 | 
|  | 2084       function both_hide() { | 
|  | 2085         document.getElementById('grey_out_page').style.display = 'none'; | 
|  | 2086         document.getElementById('download').style.display = 'none'; | 
|  | 2087         document.getElementById('send_to').style.display = 'none'; | 
|  | 2088       } | 
|  | 2089 | 
|  | 2090       /* | 
|  | 2091        * lookup the information on a motif and prepare the | 
|  | 2092        * popup for sending it to another program | 
|  | 2093        */ | 
|  | 2094       function send_to_popup(pos) { | 
|  | 2095         both_setup(pos); | 
|  | 2096         var program = find_child_element_by_class(document.getElementById('programs'), 'selected').id; | 
|  | 2097         var task = highlight_submit_task(null, submit_programs[program]); | 
|  | 2098         highlight_submit_program(program, submit_tasks[task]); | 
|  | 2099         update_submit_text(task, program); | 
|  | 2100         // show the send to page | 
|  | 2101         var grey_out = document.getElementById('grey_out_page'); | 
|  | 2102         grey_out.style.display = 'block'; | 
|  | 2103         var send_to_pop = document.getElementById('send_to'); | 
|  | 2104         send_to_pop.style.display = 'block'; | 
|  | 2105       } | 
|  | 2106 | 
|  | 2107       function send_to_popup2(elem) { | 
|  | 2108         send_to_popup(expanded_num(elem)); | 
|  | 2109       } | 
|  | 2110 | 
|  | 2111       function send_to_submit() { | 
|  | 2112         var program = find_child_element_by_class(document.getElementById('programs'), 'selected').id; | 
|  | 2113         // set the hidden fields on the form | 
|  | 2114         document.getElementById('submit_program').value = program; | 
|  | 2115         // send the form | 
|  | 2116         document.getElementById('submit_form').submit(); | 
|  | 2117         both_hide(); | 
|  | 2118       } | 
|  | 2119 | 
|  | 2120       function download_popup(pos) { | 
|  | 2121         both_setup(pos); | 
|  | 2122         click_download_tab(document.getElementById("download_tab_num").value); | 
|  | 2123         document.getElementById('submit_program').value = "LOGO"; | 
|  | 2124         // show the download page | 
|  | 2125         var grey_out = document.getElementById('grey_out_page'); | 
|  | 2126         grey_out.style.display = 'block'; | 
|  | 2127         var download_pop = document.getElementById('download'); | 
|  | 2128         download_pop.style.display = 'block'; | 
|  | 2129       } | 
|  | 2130 | 
|  | 2131       function download_popup2(elem) { | 
|  | 2132         download_popup(expanded_num(elem)); | 
|  | 2133       } | 
|  | 2134 | 
|  | 2135       function download_submit() { | 
|  | 2136         var format = document.getElementById('logo_format').value; | 
|  | 2137         var orient = document.getElementById('logo_rc').value; | 
|  | 2138         var ssc = document.getElementById('logo_ssc').value; | 
|  | 2139         var width = document.getElementById('logo_width').value; | 
|  | 2140         var height = document.getElementById('logo_height').value; | 
|  | 2141         document.getElementById('submit_format').value = format; | 
|  | 2142         document.getElementById('submit_rc').value = orient; | 
|  | 2143         document.getElementById('submit_ssc').value = ssc; | 
|  | 2144         document.getElementById('submit_width').value = width; | 
|  | 2145         document.getElementById('submit_height').value = height; | 
|  | 2146         document.getElementById('submit_form').submit(); | 
|  | 2147         both_hide(); | 
|  | 2148       } | 
|  | 2149 | 
|  | 2150       function FixLogoTask(num, rc) { | 
|  | 2151         this.num = num; | 
|  | 2152         this.rc = rc; | 
|  | 2153         this.run = FixLogoTask_run; | 
|  | 2154       } | 
|  | 2155 | 
|  | 2156       function FixLogoTask_run() { | 
|  | 2157         var pspm_text = document.getElementById("pspm" + this.num).value; | 
|  | 2158         var alpha = new Alphabet("ACGT"); | 
|  | 2159         var pspm = new Pspm(pspm_text); | 
|  | 2160         if (this.rc) pspm = pspm.reverse_complement(alpha); | 
|  | 2161         var imgid = "small_" + (this.rc ? "rc_" : "") + "logo_" + this.num; | 
|  | 2162 | 
|  | 2163         var image = document.getElementById(imgid); | 
|  | 2164 | 
|  | 2165         var canvas = create_canvas(pspm.get_motif_length() *15, 50, image.id, | 
|  | 2166             image.title, image.style.display); | 
|  | 2167         if (canvas == null) return; | 
|  | 2168 | 
|  | 2169         var logo = logo_1(alpha, "DREME", pspm); | 
|  | 2170         draw_logo_on_canvas(logo, canvas); | 
|  | 2171         image.parentNode.replaceChild(canvas, image); | 
|  | 2172       } | 
|  | 2173 | 
|  | 2174       function fix_popup_logo(image, canvasid, rc) { | 
|  | 2175         var motif_num = parseInt(document.getElementById('submit_motif').value, 10); | 
|  | 2176         var pspm_text = document.getElementById("pspm" + motif_num).value; | 
|  | 2177         var alpha = new Alphabet("ACGT"); | 
|  | 2178         var pspm = new Pspm(pspm_text); | 
|  | 2179         if (rc) pspm = pspm.reverse_complement(alpha); | 
|  | 2180         image.style.display = "none"; | 
|  | 2181         //check for canvas support before attempting anything | 
|  | 2182         var canvas = document.getElementById(canvasid); | 
|  | 2183         if (!canvas.getContext) return; | 
|  | 2184         if (!supports_text(canvas.getContext('2d'))) return; | 
|  | 2185         canvas.height = 90; | 
|  | 2186         canvas.width = 170; | 
|  | 2187         canvas.style.display = "inline"; | 
|  | 2188         var logo = logo_1(alpha, "DREME", pspm); | 
|  | 2189         draw_logo_on_canvas(logo, canvas, false); | 
|  | 2190       } | 
|  | 2191 | 
|  | 2192       function fix_expanded_logo(image, rc) { | 
|  | 2193         var motif_num = expanded_num(image); | 
|  | 2194         var pspm_text = document.getElementById("pspm" + motif_num).value; | 
|  | 2195         var alpha = new Alphabet("ACGT"); | 
|  | 2196         var pspm = new Pspm(pspm_text); | 
|  | 2197         if (rc) pspm = pspm.reverse_complement(alpha); | 
|  | 2198         //check for canvas support before attempting anything | 
|  | 2199         var canvas = document.createElement('canvas'); | 
|  | 2200         if (!canvas.getContext) return; | 
|  | 2201         if (!supports_text(canvas.getContext('2d'))) return; | 
|  | 2202         canvas.height = 150; | 
|  | 2203         canvas.width = 0; | 
|  | 2204         draw_logo_on_canvas(logo_1(alpha, "DREME", pspm), canvas, false); | 
|  | 2205         image.parentNode.replaceChild(canvas, image); | 
|  | 2206       } | 
|  | 2207 | 
|  | 2208       function text_nodes(container) { | 
|  | 2209         var textNodes = []; | 
|  | 2210         var stack = [container]; | 
|  | 2211         // depth first search to maintain ordering when flattened | 
|  | 2212         while (stack.length > 0) { | 
|  | 2213           var node = stack.pop(); | 
|  | 2214           if (node.nodeType == Node.TEXT_NODE) { | 
|  | 2215             textNodes.push(node); | 
|  | 2216           } else { | 
|  | 2217             for (var i = node.childNodes.length-1; i >= 0; i--) { | 
|  | 2218               stack.push(node.childNodes[i]); | 
|  | 2219             } | 
|  | 2220           } | 
|  | 2221         } | 
|  | 2222         return textNodes; | 
|  | 2223       } | 
|  | 2224 | 
|  | 2225       function node_text(node) { | 
|  | 2226         if (node === undefined) { | 
|  | 2227           return ''; | 
|  | 2228         } else if (node.textContent) { | 
|  | 2229           return node.textContent; | 
|  | 2230         } else if (node.innerText) { | 
|  | 2231           return node.innerText; | 
|  | 2232         } else { | 
|  | 2233           return ''; | 
|  | 2234         } | 
|  | 2235       } | 
|  | 2236 | 
|  | 2237       function nodes_text(nodes, separator) { | 
|  | 2238         if (separator === undefined) separator = ''; | 
|  | 2239         var text = ''; | 
|  | 2240         if (nodes.length > 0) { | 
|  | 2241           text += node_text(nodes[0]); | 
|  | 2242         } | 
|  | 2243         for (var i = 1; i < nodes.length; i++) { | 
|  | 2244           text += separator + node_text(nodes[i]); | 
|  | 2245         } | 
|  | 2246         return text; | 
|  | 2247       } | 
|  | 2248 | 
|  | 2249       function colour_dna_seq(container) { | 
|  | 2250         var textnodes = text_nodes(container); | 
|  | 2251         for (var i = 0; i < textnodes.length; i++) { | 
|  | 2252           var node = textnodes[i]; | 
|  | 2253           container.replaceChild(create_dna_seq(node_text(node)), node); | 
|  | 2254         } | 
|  | 2255       } | 
|  | 2256 | 
|  | 2257       function create_dna_seq(seq) { | 
|  | 2258         var out = document.createElement('span'); | 
|  | 2259         var last = 0; | 
|  | 2260         for (var i = 0; i < seq.length; i++) { | 
|  | 2261           var letter = seq.charAt(i); | 
|  | 2262           if (letter == 'A' || letter == 'C' || letter == 'G' || letter == 'T') { | 
|  | 2263             if (last < i) { | 
|  | 2264               out.appendChild(document.createTextNode(seq.substring(last, i))); | 
|  | 2265             } | 
|  | 2266             var coloured_letter = document.createElement('span'); | 
|  | 2267             coloured_letter.className = "dna_" + letter; | 
|  | 2268             coloured_letter.appendChild(document.createTextNode(letter)); | 
|  | 2269             out.appendChild(coloured_letter); | 
|  | 2270             last = i + 1; | 
|  | 2271           } | 
|  | 2272         } | 
|  | 2273         if (last < seq.length) { | 
|  | 2274           out.appendChild(document.createTextNode(seq.substring(last))); | 
|  | 2275         } | 
|  | 2276         return out; | 
|  | 2277       } | 
|  | 2278 | 
|  | 2279       function sort_table(colEle, compare_function) { | 
|  | 2280         //find the parent of colEle that is either a td or th | 
|  | 2281         var cell = colEle; | 
|  | 2282         while (true) { | 
|  | 2283           if (cell == null) return; | 
|  | 2284           if (cell.nodeType == Node.ELEMENT_NODE && | 
|  | 2285               (cell.tagName.toLowerCase() == "td" || cell.tagName.toLowerCase() == "th")) { | 
|  | 2286             break; | 
|  | 2287           } | 
|  | 2288           cell = cell.parentNode; | 
|  | 2289         } | 
|  | 2290         //find the parent of cell that is a tr | 
|  | 2291         var row = cell; | 
|  | 2292         while (true) { | 
|  | 2293           if (row == null) return; | 
|  | 2294           if (row.nodeType == Node.ELEMENT_NODE && row.tagName.toLowerCase() == "tr") { | 
|  | 2295             break; | 
|  | 2296           } | 
|  | 2297           row = row.parentNode; | 
|  | 2298         } | 
|  | 2299         //find the parent of row that is a table | 
|  | 2300         var table = row; | 
|  | 2301         while (true) { | 
|  | 2302           if (table == null) return; | 
|  | 2303           if (table.nodeType == Node.ELEMENT_NODE && table.tagName.toLowerCase() == "table") { | 
|  | 2304             break; | 
|  | 2305           } | 
|  | 2306           table = table.parentNode; | 
|  | 2307         } | 
|  | 2308         var column_index = cell.cellIndex; | 
|  | 2309         // do a bubble sort, because the tables are so small it doesn't matter | 
|  | 2310         var change; | 
|  | 2311         var trs = table.tBodies[0].getElementsByTagName('tr'); | 
|  | 2312         var already_sorted = true; | 
|  | 2313         var reverse = false; | 
|  | 2314         while (true) { | 
|  | 2315           do { | 
|  | 2316             change = false; | 
|  | 2317             for (var i = 0; i < trs.length -1; i++) { | 
|  | 2318               var v1 = nodes_text(text_nodes(trs[i].cells[column_index])); | 
|  | 2319               var v2 = nodes_text(text_nodes(trs[i+1].cells[column_index])); | 
|  | 2320               if (reverse) { | 
|  | 2321                 var tmp = v1; | 
|  | 2322                 v1 = v2; | 
|  | 2323                 v2 = tmp; | 
|  | 2324               } | 
|  | 2325               if (compare_function(v1, v2) > 0) { | 
|  | 2326                 exchange(trs[i], trs[i+1], table); | 
|  | 2327                 change = true; | 
|  | 2328                 already_sorted = false; | 
|  | 2329                 trs = table.tBodies[0].getElementsByTagName('tr'); | 
|  | 2330               } | 
|  | 2331             } | 
|  | 2332           } while (change); | 
|  | 2333           if (reverse) break;// we've sorted twice so exit | 
|  | 2334           if (!already_sorted) break;// sort did something so exit | 
|  | 2335           // when it's sorted one way already then sort the opposite way | 
|  | 2336           reverse = true; | 
|  | 2337         } | 
|  | 2338         update_sort_arrows(row, column_index, reverse); | 
|  | 2339       } | 
|  | 2340 | 
|  | 2341       function update_sort_arrows(row, column_index, reverse) { | 
|  | 2342         var ascending = "\u25BC"; | 
|  | 2343         var descending = "\u25B2"; | 
|  | 2344         var dir = (reverse ? descending : ascending); | 
|  | 2345         for (var i = 0; i < row.cells.length; i++) { | 
|  | 2346           var arrow = find_child_element_by_class(row.cells[i], "sort_dir"); | 
|  | 2347           if (arrow == null) continue; | 
|  | 2348           if (i == column_index) { | 
|  | 2349             set_content_to_text(arrow, dir); | 
|  | 2350           } else { | 
|  | 2351             set_content_to_text(arrow, ""); | 
|  | 2352           } | 
|  | 2353         } | 
|  | 2354       } | 
|  | 2355 | 
|  | 2356       function exchange(oRowI, oRowJ, oTable) { | 
|  | 2357         var i = oRowI.rowIndex; | 
|  | 2358         var j = oRowJ.rowIndex; | 
|  | 2359          if (i == j+1) { | 
|  | 2360           oTable.tBodies[0].insertBefore(oRowI, oRowJ); | 
|  | 2361         } if (j == i+1) { | 
|  | 2362           oTable.tBodies[0].insertBefore(oRowJ, oRowI); | 
|  | 2363         } else { | 
|  | 2364             var tmpNode = oTable.tBodies[0].replaceChild(oRowI, oRowJ); | 
|  | 2365             if(typeof(oRowI) != "undefined") { | 
|  | 2366               oTable.tBodies[0].insertBefore(tmpNode, oRowI); | 
|  | 2367             } else { | 
|  | 2368               oTable.appendChild(tmpNode); | 
|  | 2369             } | 
|  | 2370         } | 
|  | 2371       } | 
|  | 2372 | 
|  | 2373       function compare_numbers(v1, v2) { | 
|  | 2374         var f1 = parseFloat(v1); | 
|  | 2375         var f2 = parseFloat(v2); | 
|  | 2376         if (f1 < f2) { | 
|  | 2377           return -1; | 
|  | 2378         } else if (f1 > f2) { | 
|  | 2379           return 1; | 
|  | 2380         } else { | 
|  | 2381           return 0; | 
|  | 2382         } | 
|  | 2383       } | 
|  | 2384 | 
|  | 2385       function compare_counts(v1, v2) { | 
|  | 2386         var re = /(\d+)\/\d+/; | 
|  | 2387         var m1 = re.exec(v1); | 
|  | 2388         var m2 = re.exec(v2); | 
|  | 2389         if (m1 == null && m2 == null) return 0; | 
|  | 2390         if (m1 == null) return -1; | 
|  | 2391         if (m2 == null) return 1; | 
|  | 2392         return compare_numbers(m1[1], m2[1]); | 
|  | 2393       } | 
|  | 2394 | 
|  | 2395       function compare_strings(v1, v2) { | 
|  | 2396         return v1.localeCompare(v2); | 
|  | 2397       } | 
|  | 2398       /* | 
|  | 2399        * help | 
|  | 2400        * | 
|  | 2401        * Moves around help pop-ups so they appear | 
|  | 2402        * below an activator. | 
|  | 2403        */ | 
|  | 2404       function help(activator, popup_id) { | 
|  | 2405         if (help.popup === undefined) { | 
|  | 2406           help.popup = null; | 
|  | 2407         } | 
|  | 2408         if (help.activator === undefined) { | 
|  | 2409           help.activator = null; | 
|  | 2410         } | 
|  | 2411 | 
|  | 2412         if (typeof(activator) == 'undefined') { // no activator so hide | 
|  | 2413           help.popup.style.display = 'none'; | 
|  | 2414           help.popup = null; | 
|  | 2415           return; | 
|  | 2416         } | 
|  | 2417         var pop = document.getElementById(popup_id); | 
|  | 2418         if (pop == help.popup) { | 
|  | 2419           if (activator == help.activator) { | 
|  | 2420             //hide popup (as we've already shown it for the current help button) | 
|  | 2421             help.popup.style.display = 'none'; | 
|  | 2422             help.popup = null; | 
|  | 2423             return; // toggling complete! | 
|  | 2424           } | 
|  | 2425         } else if (help.popup != null) { | 
|  | 2426           //activating different popup so hide current one | 
|  | 2427           help.popup.style.display = 'none'; | 
|  | 2428         } | 
|  | 2429         help.popup = pop; | 
|  | 2430         help.activator = activator; | 
|  | 2431 | 
|  | 2432         //must make the popup visible to measure it or it has zero width | 
|  | 2433         pop.style.display = 'block'; | 
|  | 2434         var xy = get_elem_xy(activator); | 
|  | 2435         var padding = 10; | 
|  | 2436         var edge_padding = 15; | 
|  | 2437         var scroll_padding = 15; | 
|  | 2438 | 
|  | 2439         var pop_left = (xy[0] + (activator.offsetWidth / 2)  - (pop.offsetWidth / 2)); | 
|  | 2440         var pop_top = (xy[1] + activator.offsetHeight + padding); | 
|  | 2441 | 
|  | 2442         // ensure the box is not past the top or left of the page | 
|  | 2443         if (pop_left < 0) pop_left = edge_padding; | 
|  | 2444         if (pop_top < 0) pop_top = edge_padding; | 
|  | 2445         // ensure the box does not cause horizontal scroll bars | 
|  | 2446         var page_width = null; | 
|  | 2447         if (window.innerWidth) { | 
|  | 2448           page_width = window.innerWidth; | 
|  | 2449         } else if (document.body) { | 
|  | 2450           page_width = document.body.clientWidth; | 
|  | 2451         } | 
|  | 2452         if (page_width) { | 
|  | 2453           if (pop_left + pop.offsetWidth > page_width) { | 
|  | 2454             pop_left = page_width - pop.offsetWidth - edge_padding - scroll_padding; //account for scrollbars | 
|  | 2455           } | 
|  | 2456         } | 
|  | 2457 | 
|  | 2458         pop.style.left = pop_left + "px"; | 
|  | 2459         pop.style.top = pop_top + "px"; | 
|  | 2460       } | 
|  | 2461 | 
|  | 2462       var submit_tasks = []; | 
|  | 2463       submit_tasks['search_motifs'] = ['TOMTOM']; | 
|  | 2464       submit_tasks['search_sequences'] = ['FIMO']; | 
|  | 2465       submit_tasks['rank_sequences'] = ['MAST']; | 
|  | 2466       submit_tasks['predict_go'] = ['GOMO']; | 
|  | 2467       submit_tasks['infer_tf'] = ['SPAMO']; | 
|  | 2468       var submit_programs = []; | 
|  | 2469       submit_programs['TOMTOM'] = ['search_motifs']; | 
|  | 2470       submit_programs['FIMO'] = ['search_sequences']; | 
|  | 2471       submit_programs['MAST'] = ['rank_sequences']; | 
|  | 2472       submit_programs['GOMO'] = ['predict_go']; | 
|  | 2473       submit_programs['SPAMO'] = ['infer_tf']; | 
|  | 2474       var submit_descriptions = []; | 
|  | 2475       submit_descriptions['TOMTOM'] = "Find similar motifs in published " + | 
|  | 2476           "libraries or a library you supply."; | 
|  | 2477       submit_descriptions['FIMO'] = "Find motif occurences in sequence data."; | 
|  | 2478       submit_descriptions['MAST'] = "Rank sequences by affinity to groups " + | 
|  | 2479           "of motifs."; | 
|  | 2480       submit_descriptions['GOMO'] = "Identify possible roles (Gene Ontology " + | 
|  | 2481           "terms) for motifs."; | 
|  | 2482       submit_descriptions['SPAMO'] = "Find other motifs that are enriched at " + | 
|  | 2483           "specific close spacings which might imply the existance of a complex."; | 
|  | 2484 | 
|  | 2485 | 
|  | 2486       function click_submit_task(ele) { | 
|  | 2487         var task = ele.id; | 
|  | 2488         var program = highlight_submit_program(null, submit_tasks[task]); | 
|  | 2489         highlight_submit_task(task, submit_programs[program]); | 
|  | 2490         update_submit_text(task, program); | 
|  | 2491       } | 
|  | 2492 | 
|  | 2493       function click_submit_program(ele) { | 
|  | 2494         var program = ele.id; | 
|  | 2495         var task = highlight_submit_task(null, submit_programs[program]); | 
|  | 2496         highlight_submit_program(program, submit_tasks[task]); | 
|  | 2497         update_submit_text(task, program); | 
|  | 2498       } | 
|  | 2499 | 
|  | 2500       function update_submit_text(task, program) { | 
|  | 2501         var task_ele = document.getElementById(task); | 
|  | 2502         var program_ele = document.getElementById(program); | 
|  | 2503         set_content_to_text(document.getElementById('program_action'), | 
|  | 2504             nodes_text(text_nodes(task_ele))); | 
|  | 2505         set_content_to_text(document.getElementById('program_name'), | 
|  | 2506             nodes_text(text_nodes(program_ele))); | 
|  | 2507         set_content_to_text(document.getElementById('program_desc'), | 
|  | 2508             submit_descriptions[program]); | 
|  | 2509       } | 
|  | 2510 | 
|  | 2511       function highlight_submit_task(select, highlights) { | 
|  | 2512         var tasks_ul = document.getElementById('tasks'); | 
|  | 2513         var all_tasks = tasks_ul.getElementsByTagName('li'); | 
|  | 2514         var li; | 
|  | 2515         var originally_selected = null; | 
|  | 2516         // deselect everything in the tasks list | 
|  | 2517         for (var i = 0; i < all_tasks.length; i++) { | 
|  | 2518           li = all_tasks[i]; | 
|  | 2519           if (li.className == "selected") { | 
|  | 2520             originally_selected = li; | 
|  | 2521           } | 
|  | 2522           li.className = ""; | 
|  | 2523         } | 
|  | 2524         // highlight everything in the highlights list | 
|  | 2525         for (var i = 0; i < highlights.length; i++) { | 
|  | 2526           var li = document.getElementById(highlights[i]); | 
|  | 2527           li.className = "active"; | 
|  | 2528         } | 
|  | 2529         // check if we're setting the selected item specifically | 
|  | 2530         if (select != null) { | 
|  | 2531           li = document.getElementById(select); | 
|  | 2532           li.className = "selected"; | 
|  | 2533           return select; | 
|  | 2534         } else { | 
|  | 2535           // if the originally selected item is allowed then keep it | 
|  | 2536           // otherwise move to the first element of the highlight list | 
|  | 2537           if (originally_selected != null && | 
|  | 2538               originally_selected.className == "active") { | 
|  | 2539             originally_selected.className = "selected"; | 
|  | 2540             return originally_selected.id; | 
|  | 2541           } else if (highlights.length > 0) { | 
|  | 2542             li = document.getElementById(highlights[0]); | 
|  | 2543             li.className = "selected"; | 
|  | 2544             return highlights[0]; | 
|  | 2545           } | 
|  | 2546           return null; | 
|  | 2547         } | 
|  | 2548       } | 
|  | 2549 | 
|  | 2550 | 
|  | 2551       function highlight_submit_program(select, highlights) { | 
|  | 2552         var programs_ul = document.getElementById('programs'); | 
|  | 2553         var all_programs = programs_ul.getElementsByTagName('li'); | 
|  | 2554         var li; | 
|  | 2555         var originally_selected = null; | 
|  | 2556         // deselect everything in the programs list | 
|  | 2557         for (var i = 0; i < all_programs.length; i++) { | 
|  | 2558           li = all_programs[i]; | 
|  | 2559           if (li.className == "selected") { | 
|  | 2560             originally_selected = li; | 
|  | 2561           } | 
|  | 2562           li.className = ""; | 
|  | 2563         } | 
|  | 2564         // highlight everything in the highlights list | 
|  | 2565         for (var i = 0; i < highlights.length; i++) { | 
|  | 2566           var li = document.getElementById(highlights[i]); | 
|  | 2567           li.className = "active"; | 
|  | 2568         } | 
|  | 2569         // check if we're setting the selected item specifically | 
|  | 2570         if (select != null) { | 
|  | 2571           li = document.getElementById(select); | 
|  | 2572           li.className = "selected"; | 
|  | 2573           return select; | 
|  | 2574         } else { | 
|  | 2575           // if the originally selected item is allowed then keep it | 
|  | 2576           // otherwise move to the first element of the highlight list | 
|  | 2577           if (originally_selected != null && | 
|  | 2578               originally_selected.className == "active") { | 
|  | 2579             originally_selected.className = "selected"; | 
|  | 2580             return originally_selected.id; | 
|  | 2581           } else if (highlights.length > 0) { | 
|  | 2582             li = document.getElementById(highlights[0]); | 
|  | 2583             li.className = "selected"; | 
|  | 2584             return highlights[0]; | 
|  | 2585           } | 
|  | 2586           return null; | 
|  | 2587         } | 
|  | 2588       } | 
|  | 2589     /* END INCLUDED FILE "dreme-to-html.js" */ | 
|  | 2590 | 
|  | 2591   </script> | 
|  | 2592 </head> | 
|  | 2593 <body> | 
|  | 2594 <form id="submit_form" method="post" action="http://Sharplab-G4-1.local/meme/cgi-bin/meme_request.cgi" target="_blank"> | 
|  | 2595 <!--+++++++++++++++START DATA+++++++++++++++--> | 
|  | 2596 <input type="hidden" name="version" value="MEME version 4.7.0"> | 
|  | 2597 <input type="hidden" name="alphabet" id="alphabet" value="ACGT"> | 
|  | 2598 <input type="hidden" name="strands" value="+ -"> | 
|  | 2599 <input type="hidden" name="bgsrc" value="dataset"> | 
|  | 2600 <input type="hidden" name="bgfreq" id="bgfreq" value="A 0.243 C 0.270 G 0.243 T 0.243"> | 
|  | 2601 <input type="hidden" name="name" value="test"> | 
|  | 2602 <input type="hidden" name="nmotifs" id="nmotifs" value="0"> | 
|  | 2603 <!--+++++++++++++++FINISHED DATA++++++++++++--> | 
|  | 2604 <input type="hidden" name="program" id="submit_program" value="TOMTOM"><input type="hidden" name="motif" id="submit_motif" value="all"><input type="hidden" name="logoformat" id="submit_format" value="png"><input type="hidden" name="logorc" id="submit_rc" value="false"><input type="hidden" name="logossc" id="submit_ssc" value="false"><input type="hidden" name="logowidth" id="submit_width" value=""><input type="hidden" name="logoheight" id="submit_height" value="7.5"> | 
|  | 2605 </form> | 
|  | 2606 <div class="pop_content" id="pop_motifs_name"> | 
|  | 2607 <p> | 
|  | 2608         The name of the motif uses the IUPAC codes for nucleotides which has | 
|  | 2609         a different letter to represent each of the 15 possible combinations. | 
|  | 2610       </p> | 
|  | 2611 <p> | 
|  | 2612         The name is itself a representation of the motif though the position | 
|  | 2613         weight matrix is not directly equalivant as it is generated from the | 
|  | 2614         sites found that matched the letters given in the name. | 
|  | 2615       </p> | 
|  | 2616 <p><a href="http://meme.nbcr.net/meme/doc/alphabets.html"> | 
|  | 2617         Read more about the MEME suite's use of the IUPAC alphabets. | 
|  | 2618         </a></p> | 
|  | 2619 <div style="float:right; bottom:0px;">[<a href="javascript:help()">close</a> ]</div> | 
|  | 2620 </div> | 
|  | 2621 <div class="pop_content" id="pop_motifs_logo"> | 
|  | 2622 <p>The logo of the motif.</p> | 
|  | 2623 <div style="float:right; bottom:0px;">[<a href="javascript:help()">close</a> ]</div> | 
|  | 2624 </div> | 
|  | 2625 <div class="pop_content" id="pop_motifs_rc_logo"> | 
|  | 2626 <p>The logo of the reverse complement motif.</p> | 
|  | 2627 <div style="float:right; bottom:0px;">[<a href="javascript:help()">close</a> ]</div> | 
|  | 2628 </div> | 
|  | 2629 <div class="pop_content" id="pop_motifs_evalue"> | 
|  | 2630 <p>The E-value is the enrichment p-value times the number of candidate | 
|  | 2631         motifs tested.</p> | 
|  | 2632 <p>The enrichment p-value is calculated using the Fisher Exact Test for | 
|  | 2633         enrichment of the motif in the positive sequences.</p> | 
|  | 2634 <p>Note that the counts used in the Fisher Exact Test are made after | 
|  | 2635         erasing sites that match previously found motifs.</p> | 
|  | 2636 <div style="float:right; bottom:0px;">[<a href="javascript:help()">close</a> ]</div> | 
|  | 2637 </div> | 
|  | 2638 <div class="pop_content" id="pop_motifs_uevalue"> | 
|  | 2639 <p>The E-value of the motif calculated without erasing the sites of | 
|  | 2640         previously found motifs.</p> | 
|  | 2641 <div style="float:right; bottom:0px;">[<a href="javascript:help()">close</a> ]</div> | 
|  | 2642 </div> | 
|  | 2643 <div class="pop_content" id="pop_more"> | 
|  | 2644 <p>Show more information on the motif.</p> | 
|  | 2645 <div style="float:right; bottom:0px;">[<a href="javascript:help()">close</a> ]</div> | 
|  | 2646 </div> | 
|  | 2647 <div class="pop_content" id="pop_submit"> | 
|  | 2648 <p>Submit your motif to another MEME Suite program.</p> | 
|  | 2649 <h5>Supported Programs</h5> | 
|  | 2650 <dl> | 
|  | 2651 <dt>Tomtom</dt> | 
|  | 2652 <dd>Tomtom is a tool for searching for similar known motifs. | 
|  | 2653           [<a href="http://meme.nbcr.net/meme/tomtom-intro.html">manual</a>]</dd> | 
|  | 2654 <dt>MAST</dt> | 
|  | 2655 <dd>MAST is a tool for searching biological sequence databases for | 
|  | 2656           sequences that contain one or more of a group of known motifs. | 
|  | 2657           [<a href="http://meme.nbcr.net/meme/mast-intro.html">manual</a>]</dd> | 
|  | 2658 <dt>FIMO</dt> | 
|  | 2659 <dd>FIMO is a tool for searching biological sequence databases for | 
|  | 2660           sequences that contain one or more known motifs. | 
|  | 2661           [<a href="http://meme.nbcr.net/meme/fimo-intro.html">manual</a>]</dd> | 
|  | 2662 <dt>GOMO</dt> | 
|  | 2663 <dd>GOMO is a tool for identifying possible roles (Gene Ontology | 
|  | 2664           terms) for DNA binding motifs. | 
|  | 2665           [<a href="http://meme.nbcr.net/meme/gomo-intro.html">manual</a>]</dd> | 
|  | 2666 <dt>SpaMo</dt> | 
|  | 2667 <dd>SpaMo is a tool for inferring possible transcription factor | 
|  | 2668           complexes by finding motifs with enriched spacings. | 
|  | 2669           [<a href="http://meme.nbcr.net/meme/spamo-intro.html">manual</a>]</dd> | 
|  | 2670 </dl> | 
|  | 2671 <div style="float:right; bottom:0px;">[<a href="javascript:help()">close</a> ]</div> | 
|  | 2672 </div> | 
|  | 2673 <div class="pop_content" id="pop_download"> | 
|  | 2674 <p>Download your motif as a position weight matrix or a custom logo.</p> | 
|  | 2675 <div style="float:right; bottom:0px;">[<a href="javascript:help()">close</a> ]</div> | 
|  | 2676 </div> | 
|  | 2677 <div class="pop_content" id="pop_motif_positives"> | 
|  | 2678 <p># positive sequences matching the motif / # positive sequences.</p> | 
|  | 2679 <p>Note these counts are made after erasing sites that match previously | 
|  | 2680         found motifs.</p> | 
|  | 2681 <div style="float:right; bottom:0px;">[<a href="javascript:help()">close</a> ]</div> | 
|  | 2682 </div> | 
|  | 2683 <div class="pop_content" id="pop_motif_negatives"> | 
|  | 2684 <p># negative sequences matching the motif / # negative sequences.</p> | 
|  | 2685 <p>Note these counts are made after erasing sites that match previously | 
|  | 2686         found motifs.</p> | 
|  | 2687 <div style="float:right; bottom:0px;">[<a href="javascript:help()">close</a> ]</div> | 
|  | 2688 </div> | 
|  | 2689 <div class="pop_content" id="pop_motif_pvalue"> | 
|  | 2690 <p>The p-value of the Fisher Exact Test for enrichment of the motif in | 
|  | 2691         the positive sequences.</p> | 
|  | 2692 <p>Note that the counts used in the Fisher Exact Test are made after | 
|  | 2693         erasing sites that match previously found motifs.</p> | 
|  | 2694 <div style="float:right; bottom:0px;">[<a href="javascript:help()">close</a> ]</div> | 
|  | 2695 </div> | 
|  | 2696 <div class="pop_content" id="pop_motif_evalue"> | 
|  | 2697 <p>The E-value is the motif p-value times the number of candidate motifs | 
|  | 2698         tested.</p> | 
|  | 2699 <p>Note that the p-value was calculated with counts made after | 
|  | 2700         erasing sites that match previously found motifs.</p> | 
|  | 2701 <div style="float:right; bottom:0px;">[<a href="javascript:help()">close</a> ]</div> | 
|  | 2702 </div> | 
|  | 2703 <div class="pop_content" id="pop_motif_uevalue"> | 
|  | 2704 <p>The E-value of the motif calculated without erasing the sites of | 
|  | 2705         previously found motifs.</p> | 
|  | 2706 <div style="float:right; bottom:0px;">[<a href="javascript:help()">close</a> ]</div> | 
|  | 2707 </div> | 
|  | 2708 <div class="pop_content" id="pop_match_word"> | 
|  | 2709 <p>All words matching the motif whose uncorrected p-value is less than | 
|  | 2710         0.01.</p> | 
|  | 2711 <div style="float:right; bottom:0px;">[<a href="javascript:help()">close</a> ]</div> | 
|  | 2712 </div> | 
|  | 2713 <div class="pop_content" id="pop_match_pos"> | 
|  | 2714 <p># positive sequences with matches to the word / # positive sequences.</p> | 
|  | 2715 <p>Note these counts are made after erasing sites that match previously | 
|  | 2716         found motifs.</p> | 
|  | 2717 <div style="float:right; bottom:0px;">[<a href="javascript:help()">close</a> ]</div> | 
|  | 2718 </div> | 
|  | 2719 <div class="pop_content" id="pop_match_neg"> | 
|  | 2720 <p># negative sequences with matches to the word / # negative sequences.</p> | 
|  | 2721 <p>Note these counts are made after erasing sites that match previously | 
|  | 2722         found motifs.</p> | 
|  | 2723 <div style="float:right; bottom:0px;">[<a href="javascript:help()">close</a> ]</div> | 
|  | 2724 </div> | 
|  | 2725 <div class="pop_content" id="pop_match_pval"> | 
|  | 2726 <p>The p-value of the Fisher Exact Test for enrichment of the word in | 
|  | 2727         the positive sequences.</p> | 
|  | 2728 <p>Note that the counts used in the Fisher Exact Test are made after | 
|  | 2729         erasing sites that match previously found motifs.</p> | 
|  | 2730 <div style="float:right; bottom:0px;">[<a href="javascript:help()">close</a> ]</div> | 
|  | 2731 </div> | 
|  | 2732 <div class="pop_content" id="pop_match_eval"> | 
|  | 2733 <p>The word p-value times the number of candidates tested.</p> | 
|  | 2734 <p>Note that the p-value was calculated with counts made after | 
|  | 2735         erasing sites that match previously found motifs.</p> | 
|  | 2736 <div style="float:right; bottom:0px;">[<a href="javascript:help()">close</a> ]</div> | 
|  | 2737 </div> | 
|  | 2738 <div id="expanded_motif" style="display:none"><div class="box expanded_motif" style="margin-bottom:5px;"> | 
|  | 2739 <div> | 
|  | 2740 <div style="float:left"><h2 class="mainh" style="margin:0; padding:0;"> | 
|  | 2741 <span class="num"></span>. | 
|  | 2742               <span class="name"></span> | 
|  | 2743 </h2></div> | 
|  | 2744 <div style="float:right; "><div class="close" onclick="contract(this);" title="Show less information.">↥</div></div> | 
|  | 2745 <div style="clear:both"></div> | 
|  | 2746 </div> | 
|  | 2747 <div style="padding:0 5px;"> | 
|  | 2748 <div style="float:left;"> | 
|  | 2749 <img class="img_nc" onerror="fix_expanded_logo(this, false)"><img class="img_rc" onerror="fix_expanded_logo(this, true)"> | 
|  | 2750 </div> | 
|  | 2751 <div style="float:right; height:100px;"> | 
|  | 2752 <div onclick="send_to_popup2(this);" class="actionbutton" title="Submit this motif to another MEME Suite program."> | 
|  | 2753 <div style="float:left; margin-right:1em;">Submit</div> | 
|  | 2754 <div style="float:right">⇢</div> | 
|  | 2755 <div style="clear:both;"></div> | 
|  | 2756 </div> | 
|  | 2757 <div onclick="download_popup2(this);" class="actionbutton" title="Download this motif as a position weight matrix or a custom logo."> | 
|  | 2758 <div style="float:left; margin-right:1em;">Download</div> | 
|  | 2759 <div style="float:right">⟱</div> | 
|  | 2760 <div style="clear:both;"></div> | 
|  | 2761 </div> | 
|  | 2762 </div> | 
|  | 2763 <div style="clear:both;"></div> | 
|  | 2764 </div> | 
|  | 2765 <h4>Details</h4> | 
|  | 2766 <table class="details"> | 
|  | 2767 <thead><tr> | 
|  | 2768 <th>Positives <div class="help2" onclick="help(this,'pop_motif_positives')">?</div> | 
|  | 2769 </th> | 
|  | 2770 <th>Negatives <div class="help2" onclick="help(this,'pop_motif_negatives')">?</div> | 
|  | 2771 </th> | 
|  | 2772 <th>P-value <div class="help2" onclick="help(this,'pop_motif_pvalue')">?</div> | 
|  | 2773 </th> | 
|  | 2774 <th>E-value <div class="help2" onclick="help(this,'pop_motif_evalue')">?</div> | 
|  | 2775 </th> | 
|  | 2776 <th>Unerased E-value <div class="help2" onclick="help(this,'pop_motif_uevalue')">?</div> | 
|  | 2777 </th> | 
|  | 2778 </tr></thead> | 
|  | 2779 <tbody><tr> | 
|  | 2780 <td> | 
|  | 2781 <span class="positives"></span>/3</td> | 
|  | 2782 <td> | 
|  | 2783 <span class="negatives"></span>/3</td> | 
|  | 2784 <td class="pvalue"></td> | 
|  | 2785 <td class="evalue"></td> | 
|  | 2786 <td class="uevalue"></td> | 
|  | 2787 </tr></tbody> | 
|  | 2788 </table> | 
|  | 2789 <h4>Enriched Matching Words</h4> | 
|  | 2790 <table> | 
|  | 2791 <thead><tr> | 
|  | 2792 <th> | 
|  | 2793 <a href="javascript:;" onclick="sort_table(this, compare_strings)"><span class="sort_dir"></span>Word</a> | 
|  | 2794                 <div class="help2" onclick="help(this,'pop_match_word')">?</div> | 
|  | 2795 </th> | 
|  | 2796 <th> | 
|  | 2797 <a href="javascript:;" onclick="sort_table(this, compare_counts)"><span class="sort_dir"></span>Positives</a> | 
|  | 2798                 <div class="help2" onclick="help(this,'pop_match_pos')">?</div> | 
|  | 2799 </th> | 
|  | 2800 <th> | 
|  | 2801 <a href="javascript:;" onclick="sort_table(this, compare_counts)"><span class="sort_dir"></span>Negatives</a> | 
|  | 2802                 <div class="help2" onclick="help(this,'pop_match_neg')">?</div> | 
|  | 2803 </th> | 
|  | 2804 <th> | 
|  | 2805 <a href="javascript:;" onclick="sort_table(this, compare_numbers)"><span class="sort_dir"></span>P-value</a> | 
|  | 2806                 <div class="help2" onclick="help(this,'pop_match_pval')">?</div> | 
|  | 2807 </th> | 
|  | 2808 <th> | 
|  | 2809 <a href="javascript:;" onclick="sort_table(this, compare_numbers)"><span class="sort_dir">▼</span>E-value</a> | 
|  | 2810                 <div class="help2" onclick="help(this,'pop_match_eval')">?</div> | 
|  | 2811 </th> | 
|  | 2812 </tr></thead> | 
|  | 2813 <tbody><tr class="match"> | 
|  | 2814 <td class="dnaseq"></td> | 
|  | 2815 <td> | 
|  | 2816 <span class="positives"></span>/3</td> | 
|  | 2817 <td> | 
|  | 2818 <span class="negatives"></span>/3</td> | 
|  | 2819 <td class="pvalue"></td> | 
|  | 2820 <td class="evalue"></td> | 
|  | 2821 </tr></tbody> | 
|  | 2822 </table> | 
|  | 2823 </div></div> | 
|  | 2824 <div id="grey_out_page" class="grey_background" style="display:none;"></div> | 
|  | 2825 <div class="popup_wrapper"><div id="send_to" class="popup" style="top:-150px; display:none"> | 
|  | 2826 <div> | 
|  | 2827 <div style="float:left" id="send_to_title_1"><h2 class="mainh compact">Submit "<span id="send_to_name"></span>"</h2></div> | 
|  | 2828 <div style="float:left" id="send_to_title_2"><h2 class="mainh compact">Submit All Motifs</h2></div> | 
|  | 2829 <div style="float:right; "><div class="close" onclick="both_hide();">x</div></div> | 
|  | 2830 <div style="clear:both"></div> | 
|  | 2831 </div> | 
|  | 2832 <div style="padding:0 5px 5px 5px;"> | 
|  | 2833 <div id="send_to_selector" style="height:100px;"> | 
|  | 2834 <img id="send_to_img" height="90" style="max-width:170px;" onerror="fix_popup_logo(this, 'send_to_can', false)"><canvas id="send_to_can" width="10" height="100" style="display:none;"></canvas><img id="send_to_rcimg" height="90" style="max-width:170px;" onerror="fix_popup_logo(this, 'send_to_rccan', true);"><canvas id="send_to_rccan" width="10" height="100" style="display:none"></canvas><div style="float:right;"> | 
|  | 2835 <a id="prev_arrow_2" href="javascript:both_change(-1)" class="navarrow">⇧</a><div id="pop_num_2" class="navnum"></div> | 
|  | 2836 <a id="next_arrow_2" href="javascript:both_change(1)" class="navarrow">⇩</a> | 
|  | 2837 </div> | 
|  | 2838 </div> | 
|  | 2839 <form> | 
|  | 2840 <div style=""> | 
|  | 2841 <div style="float:left;"> | 
|  | 2842 <h4 class="compact">Select what you want to do</h4> | 
|  | 2843 <div class="programs_scroll"><ul id="tasks" class="programs"> | 
|  | 2844 <li id="search_motifs" onclick="click_submit_task(this)" class="selected">Search Motifs</li> | 
|  | 2845 <li id="search_sequences" onclick="click_submit_task(this)">Search Sequences</li> | 
|  | 2846 <li id="rank_sequences" onclick="click_submit_task(this)">Rank Sequences</li> | 
|  | 2847 <li id="predict_go" onclick="click_submit_task(this)">Predict Gene Ontology terms</li> | 
|  | 2848 <li id="infer_tf" onclick="click_submit_task(this)">Infer TF Complexes</li> | 
|  | 2849 </ul></div> | 
|  | 2850 </div> | 
|  | 2851 <div style="float:right;"> | 
|  | 2852 <h4 class="compact">Select a program</h4> | 
|  | 2853 <div class="programs_scroll"><ul id="programs" class="programs"> | 
|  | 2854 <li id="TOMTOM" onclick="click_submit_program(this)" class="selected">Tomtom</li> | 
|  | 2855 <li id="FIMO" onclick="click_submit_program(this)">FIMO</li> | 
|  | 2856 <li id="MAST" onclick="click_submit_program(this)">MAST</li> | 
|  | 2857 <li id="GOMO" onclick="click_submit_program(this)">GOMO</li> | 
|  | 2858 <li id="SPAMO" onclick="click_submit_program(this)">SpaMo</li> | 
|  | 2859 </ul></div> | 
|  | 2860 </div> | 
|  | 2861 <div style="font-weight:bold; display:inline-block; text-align:center; width:60px; height:100px; line-height:100px">Or</div> | 
|  | 2862 <div style="clear:both;"></div> | 
|  | 2863 </div> | 
|  | 2864 <h4> | 
|  | 2865 <span id="program_action">Search Motifs</span> with <span id="program_name">Tomtom</span> | 
|  | 2866 </h4> | 
|  | 2867 <p><span id="program_desc">Find similar motifs in published | 
|  | 2868                 libraries or a library you supply.</span></p> | 
|  | 2869 <div style="margin-top:10px; height: 2em;"> | 
|  | 2870 <div style="float:left;"><input type="button" value="Send" onclick="javascript:send_to_submit()"></div> | 
|  | 2871 <div style="float:right;"><input type="button" value="Cancel" onclick="javascript:both_hide()"></div> | 
|  | 2872 </div> | 
|  | 2873 </form> | 
|  | 2874 </div> | 
|  | 2875 </div></div> | 
|  | 2876 <div class="popup_wrapper"><div id="download" class="popup" style="top:-150px; display:none"> | 
|  | 2877 <div> | 
|  | 2878 <div style="float:left"><h2 class="mainh" style="margin:0; padding:0;">Download "<span id="download_name"></span>"</h2></div> | 
|  | 2879 <div style="float:right; "><div class="close" onclick="both_hide();">x</div></div> | 
|  | 2880 <div style="clear:both"></div> | 
|  | 2881 </div> | 
|  | 2882 <div style="padding:0 5px 5px 5px;"> | 
|  | 2883 <div style="height:100px"> | 
|  | 2884 <img id="download_img" height="90" style="max-width:170px;" onerror="fix_popup_logo(this, 'download_can', false)"><canvas id="download_can" width="10" height="100" style="display:none;"></canvas><img id="download_rcimg" height="90" style="max-width:170px;" onerror="fix_popup_logo(this, 'download_rccan', true)"><canvas id="download_rccan" width="10" height="100" style="display:none;"></canvas><div style="float:right;"> | 
|  | 2885 <a id="prev_arrow_1" href="javascript:both_change(-1)" class="navarrow">⇧</a><div id="pop_num_1" class="navnum"></div> | 
|  | 2886 <a id="next_arrow_1" href="javascript:both_change(1)" class="navarrow">⇩</a> | 
|  | 2887 </div> | 
|  | 2888 </div> | 
|  | 2889 <form> | 
|  | 2890 <input type="hidden" id="download_tab_num" value="1"><div style="padding:5px 0;"> | 
|  | 2891 <div class="tabArea top"> | 
|  | 2892 <a id="download_tab_1" href="javascript:click_download_tab(1)" class="tab activeTab">PSPM Format</a><a id="download_tab_2" href="javascript:click_download_tab(2)" class="tab">PSSM Format</a><a id="download_tab_3" href="javascript:click_download_tab(3)" class="tab">Logo</a> | 
|  | 2893 </div> | 
|  | 2894 <div class="tabMain"> | 
|  | 2895 <div id="download_pnl_1"><textarea id="download_pspm" style="width:99%" rows="10" readonly></textarea></div> | 
|  | 2896 <div id="download_pnl_2"><textarea id="download_pssm" style="width:99%" rows="10" readonly></textarea></div> | 
|  | 2897 <div id="download_pnl_3"><table> | 
|  | 2898 <tr> | 
|  | 2899 <td><label for="logo_format">Format:</label></td> | 
|  | 2900 <td><select id="logo_format"><option value="png">PNG (for web)</option> | 
|  | 2901 <option value="eps">EPS (for publication)</option></select></td> | 
|  | 2902 </tr> | 
|  | 2903 <tr> | 
|  | 2904 <td><label for="logo_rc">Orientation:</label></td> | 
|  | 2905 <td><select id="logo_rc"><option value="false">Normal</option> | 
|  | 2906 <option value="true">Reverse Complement</option></select></td> | 
|  | 2907 </tr> | 
|  | 2908 <tr> | 
|  | 2909 <td><label for="logo_ssc">Small Sample Correction:</label></td> | 
|  | 2910 <td><select id="logo_ssc"><option value="false">Off</option> | 
|  | 2911 <option value="true">On</option></select></td> | 
|  | 2912 </tr> | 
|  | 2913 <tr> | 
|  | 2914 <td><label for="logo_width">Width:</label></td> | 
|  | 2915 <td> | 
|  | 2916 <input type="text" id="logo_width" size="4"> cm | 
|  | 2917                       </td> | 
|  | 2918 </tr> | 
|  | 2919 <tr> | 
|  | 2920 <td><label for="logo_height">Height:</label></td> | 
|  | 2921 <td> | 
|  | 2922 <input type="text" id="logo_height" size="4"> cm | 
|  | 2923                       </td> | 
|  | 2924 </tr> | 
|  | 2925 </table></div> | 
|  | 2926 <div style="margin-top:10px;"> | 
|  | 2927 <div style="float:left;"><input type="button" id="download_button" value="Download" style="visibility:hidden;" onclick="javascript:download_submit()"></div> | 
|  | 2928 <div style="float:right;"><input type="button" value="Cancel" onclick="javascript:both_hide()"></div> | 
|  | 2929 <div style="clear:both;"></div> | 
|  | 2930 </div> | 
|  | 2931 </div> | 
|  | 2932 </div> | 
|  | 2933 </form> | 
|  | 2934 </div> | 
|  | 2935 </div></div> | 
|  | 2936 <a name="top"></a><div class="pad1"> | 
|  | 2937 <h1><img src="http://Sharplab-G4-1.local/meme/doc/images/dreme_logo.png" alt="Discriminative Regular Expression Motif Elicitation (DREME)"></h1> | 
|  | 2938 <p class="spaced"> | 
|  | 2939         For further information on how to interpret these results or to get a | 
|  | 2940         copy of the MEME software please access | 
|  | 2941         <a href="http://meme.nbcr.net/">http://meme.nbcr.net</a>. | 
|  | 2942       </p> | 
|  | 2943 <p> | 
|  | 2944         If you use DREME in your research please cite the following paper:<br><span class="citation"> | 
|  | 2945           Timothy L. Bailey, "DREME: Motif discovery in transcription factor ChIP-seq data", <i>Bioinformatics</i>, <b>27</b>(12):1653-1659, 2011. | 
|  | 2946         </span></p> | 
|  | 2947 </div> | 
|  | 2948 <div class="pad2"> | 
|  | 2949 <a class="jump" href="#description">Description</a>  |  <a class="jump" href="#motifs">Discovered motifs</a>  |  <a class="jump" href="#program">Program information</a> | 
|  | 2950 </div> | 
|  | 2951 <a name="description"></a><table width="100%" border="0" cellspacing="1" cellpadding="4" bgcolor="#FFFFFF"><tr> | 
|  | 2952 <td><h2 class="mainh">Description</h2></td> | 
|  | 2953 <td align="right" valign="bottom"> | 
|  | 2954 <a href="#motifs">Next</a> <a href="#top">Top</a> | 
|  | 2955 </td> | 
|  | 2956 </tr></table> | 
|  | 2957 <div class="box"><p>xxxx</p></div> | 
|  | 2958 <a name="motifs"></a><table width="100%" border="0" cellspacing="1" cellpadding="4" bgcolor="#FFFFFF"><tr> | 
|  | 2959 <td><h2 class="mainh">Discovered Motifs</h2></td> | 
|  | 2960 <td align="right" valign="bottom"> | 
|  | 2961 <a href="#description">Previous</a> <a href="#program">Next</a> <a href="#top">Top</a> | 
|  | 2962 </td> | 
|  | 2963 </tr></table> | 
|  | 2964 <div class="box"> | 
|  | 2965 <p><b>Click on the ↧</b> under the <b>More</b> column to show more | 
|  | 2966         information about the motif.<br><b>Click on the ⇢</b> under the <b>Submit</b> column to send the | 
|  | 2967         motif to another MEME suite program. Eg. Tomtom<br><b>Click on the ⟱</b> under the <b>Download</b> column to get | 
|  | 2968         the position weight matrix of a motif or to download the logo image with | 
|  | 2969         your chosen options. | 
|  | 2970       </p> | 
|  | 2971 <table id="dreme_motifs" class="dreme_motifs"> | 
|  | 2972 <thead><tr class="motif_head"> | 
|  | 2973 <td> </td> | 
|  | 2974 <th>Motif <div class="help2" onclick="help(this,'pop_motifs_name')">?</div> | 
|  | 2975 </th> | 
|  | 2976 <th>Logo <div class="help2" onclick="help(this,'pop_motifs_logo')">?</div> | 
|  | 2977 </th> | 
|  | 2978 <th>RC Logo <div class="help2" onclick="help(this,'pop_motifs_rc_logo')">?</div> | 
|  | 2979 </th> | 
|  | 2980 <th>E-value <div class="help2" onclick="help(this,'pop_motifs_evalue')">?</div> | 
|  | 2981 </th> | 
|  | 2982 <th>Unerased E-value <div class="help2" onclick="help(this,'pop_motifs_uevalue')">?</div> | 
|  | 2983 </th> | 
|  | 2984 <th>More <div class="help2" onclick="help(this,'pop_more')">?</div> | 
|  | 2985 </th> | 
|  | 2986 <th>Submit <div class="help2" onclick="help(this,'pop_submit')">?</div> | 
|  | 2987 </th> | 
|  | 2988 <th>Download <div class="help2" onclick="help(this,'pop_download')">?</div> | 
|  | 2989 </th> | 
|  | 2990 </tr></thead> | 
|  | 2991 <tbody></tbody> | 
|  | 2992 <tfoot><tr class="rule"> | 
|  | 2993 <td> </td> | 
|  | 2994 <td> </td> | 
|  | 2995 <td> </td> | 
|  | 2996 <td> </td> | 
|  | 2997 <td> </td> | 
|  | 2998 <td> </td> | 
|  | 2999 <td> </td> | 
|  | 3000 <td> </td> | 
|  | 3001 <td> </td> | 
|  | 3002 </tr></tfoot> | 
|  | 3003 </table> | 
|  | 3004 <div style="float:left"><div onclick="send_to_popup(0);" class="actionbutton" title="Submit all motifs to another program."> | 
|  | 3005 <div style="float:left; margin-right:1em;">Submit All</div> | 
|  | 3006 <div style="float:right">⇢</div> | 
|  | 3007 <div style="clear:both;"></div> | 
|  | 3008 </div></div> | 
|  | 3009 <div style="clear:both;"></div> | 
|  | 3010 </div> | 
|  | 3011 <a name="program"></a><div class="bar"> | 
|  | 3012 <div style="text-align:right;"> | 
|  | 3013 <a href="#motifs">Previous</a> <a href="#top">Top</a> | 
|  | 3014 </div> | 
|  | 3015 <div class="subsection"> | 
|  | 3016 <a name="version"></a><h5>DREME version</h5>4.7.0 (Release date: Wed Sep 28 17:30:10 EST 2011) | 
|  | 3017       </div> | 
|  | 3018 <div class="subsection"> | 
|  | 3019 <a name="reference"></a><h5>Reference</h5> | 
|  | 3020 <span class="citation"> | 
|  | 3021           Timothy L. Bailey, "DREME: Motif discovery in transcription factor ChIP-seq data", <i>Bioinformatics</i>, <b>27</b>(12):1653-1659, 2011. | 
|  | 3022         </span> | 
|  | 3023 </div> | 
|  | 3024 <div class="subsection"> | 
|  | 3025 <a name="command"></a><h5>Command line summary</h5> | 
|  | 3026 <textarea rows="1" style="width:100%;" readonly>dreme -p test.fa -desc xxxx</textarea><br>Result calculation took 0.01 seconds<br> | 
|  | 3027 </div> | 
|  | 3028 <a href="javascript:show_hidden('model')" id="model_activator">show model parameters...</a><div class="subsection" id="model_data" style="display:none;"> | 
|  | 3029 <h5>Model parameters</h5> | 
|  | 3030 <textarea style="width:100%;" rows="10" readonly> | 
|  | 3031 positives             = name: "test", count: "3", file: "test.fa", last_mod_date: "Sat Dec 10 12:52:18 EST 2011" | 
|  | 3032 negatives             = name: "shuffled positive sequences", count: "3", from: "shuffled" | 
|  | 3033 background            = type: "dna", A: "0.243", C: "0.270", G: "0.243", T: "0.243", from: "dataset" | 
|  | 3034 stop                  = evalue: "0.05" | 
|  | 3035 ngen                  = 100 | 
|  | 3036 add_pv_thresh         = 0.01 | 
|  | 3037 seed                  = 1 | 
|  | 3038 host                  = SHARPLAB.MIT.EDU | 
|  | 3039 when                  = Sun Dec 11 09:26:43 EST 2011 | 
|  | 3040 </textarea> | 
|  | 3041 </div> | 
|  | 3042 <a href="javascript:hide_shown('model')" style="display:none;" id="model_deactivator">hide model parameters...</a> | 
|  | 3043 </div> | 
|  | 3044 </body> | 
|  | 3045 </html> |