Mercurial > repos > xuebing > sharplabtool
comparison tools/mytools/dreme_out/dreme.html @ 0:9071e359b9a3
Uploaded
author | xuebing |
---|---|
date | Fri, 09 Mar 2012 19:37:19 -0500 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
-1:000000000000 | 0:9071e359b9a3 |
---|---|
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> |