-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathinput.html
More file actions
executable file
·666 lines (652 loc) · 31.6 KB
/
Copy pathinput.html
File metadata and controls
executable file
·666 lines (652 loc) · 31.6 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
<!Doctype html>
<html>
<head>
<meta charset="UTF-8" />
<title>Champuru</title>
<link rel="stylesheet" href="style.css"/>
</head>
<body>
<a href="https://github.com/eeg-ebe/Champuru">
<svg width="80" height="80" viewBox="0 0 250 250" style="fill:white; color:black; z-index: 51; position: absolute; top: 0; right: 0; border: 0;" aria-hidden="true"><path d="M0,0 L115,115 L130,115 L142,142 L250,250 L250,0 Z"></path><path d="M128.3,109.0 C113.8,99.7 119.0,89.6 119.0,89.6 C122.0,82.7 120.5,78.6 120.5,78.6 C119.2,72.0 123.4,76.3 123.4,76.3 C127.3,80.9 125.5,87.3 125.5,87.3 C122.9,97.6 130.6,101.9 134.4,103.2" fill="currentColor" style="transform-origin: 130px 106px;" class="octo-arm"></path><path d="M115.0,115.0 C114.9,115.1 118.7,116.5 119.8,115.4 L133.7,101.6 C136.9,99.2 139.9,98.4 142.2,98.6 C133.8,88.0 127.5,74.4 143.8,58.0 C148.5,53.4 154.0,51.2 159.7,51.0 C160.3,49.4 163.2,43.6 171.4,40.1 C171.4,40.1 176.1,42.5 178.8,56.2 C183.1,58.6 187.2,61.8 190.9,65.4 C194.5,69.0 197.7,73.2 200.1,77.6 C213.8,80.2 216.3,84.9 216.3,84.9 C212.7,93.1 206.9,96.0 205.4,96.6 C205.1,102.4 203.0,107.8 198.3,112.5 C181.9,128.9 168.3,122.5 157.7,114.1 C157.9,116.9 156.7,120.9 152.7,124.9 L141.0,136.5 C139.8,137.7 141.6,141.9 141.8,141.8 Z" fill="currentColor" class="octo-body"></path>
</svg>
</a>
<div class="contentdiv">
<h1>Champuru 2</h1>
<p id="cite">Flot (2007) <strong>Champuru 1.0: a computer software for unraveling mixtures of two DNA sequences of unequal lengths.</strong> <em>Molecular Ecology Notes</em> <strong>7</strong> (6), 974-977 [<a href="http://dx.doi.org/10.1111/j.1471-8286.2007.01857.x">link</a>]</p>
<p id="cite"> Spöri & Flot (2024) <strong>Champuru 2: Improved scoring of alignments and a user-friendly graphical interface.</strong> <em>bioRxiv</em>
[<a href="https://doi.org/10.48550/arXiv.2405.06032">link</a>]</p>
<div class="navigation">
<a href="index.html">Back to startpage</a>
<a href="faq.html">FAQ</a>
<a href="tutorial.html">Tutorial</a>
<a href="mailto: jflot@ulb.be">E-mail the author</a>
</div>
<h2></h2>
<div class="importanttips">
Champuru makes it possible to determine the haplotypes of heterozygous individuals without cloning, simply by analyzing the patterns of double peaks in the forward and reverse chromatograms.
</div>
<br>
<table style="margin: 0 auto;">
<tr class="option">
<td>Forward sequence:</td>
<td> </td>
<td><input id="forward" type="text" name="forward" style="width: 400px" autocomplete="off"/></td>
</tr>
<tr class="description">
<td colspan="3">
<p>The forward sequence (IUPAC one-letter code) of the heterozygous individual.</p>
</td>
</tr>
<tr class="option">
<td>Reverse sequence:</td>
<td> </td>
<td><input id="reverse" type="text" name="reverse" style="width: 400px" autocomplete="off"/></td>
</tr>
<tr class="description">
<td colspan="3">
<p>The reverse sequence (IUPAC one-letter code) of the heterozygous individual.<br>
<button onclick="reverse()">Reverse-complement</button>
</p>
</td>
</tr>
<tr class="option">
<td>Score calculation:</td>
<td> </td>
<td>
<select id="score" autocomplete="off">
<option value="0">Overlap-corrected score</option>
<option value="1" selected="selected">Overlap and ambiguity-corrected score</option>
<option value="2">Longest uninterrupted overlap score</option>
</select>
</td>
</tr>
<tr class="description">
<td colspan="3">
<p>Which score calculation method to use. Currently the following methods are implemented:</p>
<table class="descTable">
<tr class="even">
<td valign="top">Overlap-corrected score</td><td valign="top">The score correction method described in the Champuru 1.0 paper
(namely, computing the number of compatible positions
in the alignment minus one fourth of the length of the overlap between the two sequences,
to correct for the fact that two random nucleotides have a 0.25 probability of matching
just by chance).</td>
</tr>
<tr class="odd">
<td valign="top">Overlap and ambiguity-corrected score</td><td valign="top">A modification of the score calculation method described in the Champuru 1.0 paper.
This modified score corrects for the fact that ambiguous characters (e.g. W) can match multiple other characters (e.g. A, T).
Preliminary results suggests that this score calculation method works better when the reconstructed consensus sequences contain a lot of ambiguities.
However this score correction method seems to work less good on short input sequences.
</td>
</tr>
<tr class="even">
<td valign="top">Longest uninterrupted overlap score</td><td valign="top">Takes the longest number of consecutive matching nucleotides as score.</td>
</tr>
</table>
</td>
</tr>
<tr class="option">
<td>Analyze further offset pairs:</td>
<td> </td>
<td><input type="checkbox" id="searchForAlternativeSolutions" autocomplete="off"></td>
</tr>
<tr class="description">
<td colspan="3">
<p>When this checkbox is clicked, Champuru not only uses the best offset pair for sequence reconstruction but it also runs the
sequence reconstruction algorithm for further offset pairs. This makes it possible to check for other possible offset pairs (in some rare cases, there are multiple possible solutions for the given input.
This can take some time, which is why this checkbox is not checked by default.</p>
</td>
</tr>
<tr class="option">
<td>Bonferroni correction:</td>
<td> </td>
<td><input type="checkbox" id="statisticCorrection" autocomplete="off" checked="checked"></td>
</tr>
<tr class="description">
<td colspan="3">
<p>Whether to perform a Bonferroni correction for all calculated p-values.</p>
</td>
</tr>
</table>
<span class="middle">
<button onclick="calculate()">Calculate</button>
<button onclick="resetForm()">Reset form</button>
</span>
<p><br></p>
<div id="resultArea" style="display: none">
</div>
<p><br></p>
<div id="exampleSection">
<div class="noindent">
To get a quick feeling of how Champuru works, use the following data:<br>
Forward sequence: <span class="sequence" id="example1forward">ATSYKRMKY</span><br>
Reverse sequence: <span class="sequence" id="example1reverse">WWKCTGAST</span><br>
<button href="#" onclick="load(1)">Copy data to input fields</button><br>
</div>
<br>
<div class="noindent">
This example may be used in order to explain how Champuru can resolve ambiguities in the consensus sequences (Step 3):<br>
Forward sequence: <span class="sequence" id="example2forward">CTRAATTCAAATCACACTCGCGAAAWYMWKRAA</span><br>
Reverse sequence: <span class="sequence" id="example2reverse">YWRAWTYMAAWYMMMMYYSSSRAAATCATGAA</span><br>
<button href="#" onclick="load(2)">Copy data to input fields</button><br>
</div>
<br>
<div class="noindent">
A more complex example with lots of ambiguities in the consensus sequence:<br>
Forward sequence: <span class="sequence" id="example3forward">AAATSSYKRWTYMMMMMRSSRMSGSCCYWRSMWWMCCSRRGGRWYSGRARR</span><br>
Reverse sequence: <span class="sequence" id="example3reverse">MRMTGMTKMWYMMMRCRRCGRCSSYMSYAKMMYMSMSGRRKSRKMRGRRKA</span><br>
<button href="#" onclick="load(3)">Copy data to input fields</button><br>
</div>
<br>
<div class="noindent">
The following example has multiple solutions (for offset pairs 5,1 and 4,2):<br>
Forward sequence: <span class="sequence" id="example4forward">SYKRWTYMMMMMRSSRMSGSCCYWRSMWWMCCSRRGGRWYSGRAR</span><br>
Reverse sequence: <span class="sequence" id="example4reverse">MRMTGMTKMWYMMMRCRRCGRCSSYMSYAKMMYMSMSGRRKSRKMRGRRKA</span><br>
<button href="#" onclick="load(4)">Copy data to input fields</button><br>
</div>
<br>
<div class="noindent">
And here is a 'real-life' example (original chromatograms: <a href="ExampleForward.ab1">Forward</a> and <a href="ExampleReverse.ab1">Reverse</a>):<br>
Forward sequence: <span class="sequence" id="example5forward">ATCGTGGGCGGCCGGCCCTGCCACAGACGGGGTTGTCACCCTCTGCGACGTGCCGTTCCAAGCAACTTAGGCAGGGCCCCTCCGCCTAGAAAGTGCTTCTCGCAACTACAACTCGCCGATGCAGGCATCGGAGATTTCAAATTTGAGCTCTTCCCGCTTCACTCGCCGTTACTGGGGGAATCCTTGTTAGTTTCTTTTCCTCCGCTTATTAATATGCTTAAATTCAGCGGGTAGCCTTGCCTGATCTGAGGTCTGGAAGGCGATTCCTTTTTTCCTTTGAGATGCCGCCACCGCTACCCGGCGGCAGCAGAAAAAAGAATCGAATGGAGAAAGATTTGTTCCGTCAAAGCGATAGAGCCGTGGCCGTTTGGGGTACATTGTTCTATGATCCCCGCGCGACACCGGATGTCGCTTGGCGGATCTTTCTCCCTGAATTTCAAGGGACGCGGTAAACCGACCGGTCGGGCCGAGCAGCACCAGGGCTGGCTAGCTAGCGCACGACCGGTCATCTCGACCGCGACCCTCAACGCCGCACGAACCCGTTCACGGCGGGCGCGYSYCSSSSCCMYMYSCKMYASASRSGGRSMMSRSGSRSRCGCGCRCRCGSRKWYKCRCRMKRKRKRTKTKWRWAKASACWCWSASASASAYRYKCYYSKGRGARMMCMMRAGMGCSMYWTKYGYKYWMARAKWYKMKRWKWYWCWSWRWWYTCYGCWWYTCACWCTWYWTMTCRSMMTCKMKCTGA</span><br>
Reverse sequence: <span class="sequence" id="example5reverse">GTGCRMTMTCAACACMCSASTCTCGMRACRCATMKYGKGSGSSSSSSSCYSYSMCASASRSGGKKKTSWCMCYCTSYGMSRYGYSSYKYYMMRMRMMWYWKRSRSRGSSCCYCYSCSYMKARARWGYKYYTCKCRMMWMYAMMWCKCSSMKRYRSRSRYMKSRGAKWTYWMAWWTKWGMKCTYYYCSCKYYWCWCKCSSYKWYWSKGGGRRWMYYYKTKWKWKTYTYTTYYYCYSCKYWTWWWWATRYKYWWAWWYWSMGSGKRKMSYYKYSYSWKMTSWGRKSTSKRRRRSGMKWYYYYTTTTYYYYTKWGAKRYSSCSMCMSCKMYMCSSSGSSRSMRSARAAAARARWMKMRWRKRGARARAKWTKTKYYSYSWMARMGMKAKAGMSSYGKSSSYKTKKGGKRYAYWKTKYTMTRWKMYCCSCGCGMSACMSSRKRTSKCKYKKSGSRKMTYTYTCYCYSWRWWTYWMRRGRSRCGSKRWAMMSMSMSSKSKSGSSSMGMRSMRCMMSRGSKSKSKMKMKMKMGCRCRMSMSSKSWYMTCKMSMSCGMSMCYCWMMRCSSCRCRMRMMCSYKYWCRSSGSGSGCGCGTCCCGGCCCCATCCGCTACAGACGGGGACCAGGCGGACGCGCGCACGCGGATTCGCACGATGGATGTTTGAATAGACACTCAGACAGACATGCTCCTGGGAGAACCCAAGAGCGCCATTTGCGTTCAAAGATTCGATGATTCACTGAAT</span><br>
<button href="#" onclick="load(5)">Copy data to input fields</button><br>
</div>
<br>
</div>
<div id="hiddenDiv" style="display: none"></div>
<div class="navigation">
<a href="index.html">Back to startpage</a>
<a href="faq.html">FAQ</a>
<a href="tutorial.html">Tutorial</a>
<a href="mailto: jflot@ulb.be">E-mail the author</a>
</div>
</div>
<script>
String.prototype.replaceAt = function(index, replacement) {
return this.substring(0, index) + replacement + this.substring(index + replacement.length);
}
var reverseLookup = {
'A' : 'T', 'T' : 'A', 'G' : 'C', 'C' : 'G',
'R' : 'Y', 'Y' : 'R', 'M' : 'K', 'K' : 'M',
'W' : 'W', 'S' : 'S', 'V' : 'B', 'B' : 'V',
'H' : 'D', 'D' : 'H', 'N' : 'N'
};
function checkInput(s) {
for (var i = 0; i < s.length; i++) {
var character = s[i];
var lookup = reverseLookup[character];
if (lookup == "" || lookup == undefined) {
return character;
}
}
return null;
}
function calculate() {
var fwd = document.getElementById('forward').value.trim().toUpperCase();
var rev = document.getElementById('reverse').value.trim().toUpperCase();
var score = parseInt(document.getElementById('score').value);
if (fwd == "") {
alert("Missing forward sequence input!");
return;
}
if (rev == "") {
alert("Missing reverse sequence input!");
return;
}
if (fwd.length + rev.length <= 3) {
alert("Sequences to short!");
return;
}
var unknown1 = checkInput(fwd);
if (unknown1 != null) {
alert("Unknown base (" + unknown1 + ") in forward sequence!");
return;
}
var unknown2 = checkInput(rev);
if (unknown2 != null) {
alert("Unknown base (" + unknown2 + ") in reverse sequence!");
return;
}
var searchForAlternativeSolutions = document.getElementById("searchForAlternativeSolutions").checked;
var statisticCorrection = document.getElementById("statisticCorrection").checked;
var resultArea = document.getElementById("resultArea");
resultArea.innerText = "Calculating ... Please wait ... Results will appear here!";
resultArea.style.display = "block";
document.getElementById('exampleSection').style.display = "none";
var worker = new Worker("champuru.js");
worker.addEventListener("message", function(e) {
data = e.data;
resultArea.innerHTML = data.result;
worker.terminate();
});
worker.postMessage({"fwd" : fwd, "rev" : rev, "score" : score, "i" : 0, "j" : 0, "useOffsets" : false, "searchForAlternativeSolutions" : searchForAlternativeSolutions, "statisticCorrection" : statisticCorrection});
}
function askForOffset(title, fwd, rev) {
var input = prompt(title);
if (input == null || input == undefined) return NaN; // Cancel button
var i = parseInt(input.trim());
if (isNaN(i)) {
alert("Invalid input!");
return NaN;
}
if (!(-fwd.length + 1 <= i && i < rev.length)) {
alert("Invalid offset for input sequences!");
return NaN;
}
return i;
}
function rerunAnalysisWithDifferentOffsets(fwd, rev, method) {
var i = askForOffset("Please enter first offset:", fwd, rev);
if (isNaN(i)) return;
var j = askForOffset("Please enter second offset:", fwd, rev);
if (isNaN(j)) return;
rerunAnalysisWithDifferentOffsets2(fwd, rev, method, i, j);
}
function rerunAnalysisWithDifferentOffsets2(fwd, rev, method, i, j) {
rerunAnalysisWithDifferentOffsets3(fwd, rev, method, i, j, false);
}
function rerunAnalysisWithDifferentOffsets3(fwd, rev, method, i, j, alternativeSolutions) {
var worker = new Worker("champuru.js");
worker.addEventListener("message", function(e) {
data = e.data;
resultArea.innerHTML = data.result;
worker.terminate();
});
worker.postMessage({"fwd" : fwd, "rev" : rev, "score" : method, "i" : i, "j" : j, "useOffsets" : true, "searchForAlternativeSolutions" : alternativeSolutions});
}
function resetForm() {
document.getElementById('forward').value = '';
document.getElementById('reverse').value = '';
document.getElementById('score').value = 1;
document.getElementById('resultArea').style.display = "none";
document.getElementById('exampleSection').style.display = "block";
}
function load(i) {
document.getElementById('forward').value = document.getElementById('example' + i + 'forward').innerText;
document.getElementById('reverse').value = document.getElementById('example' + i + 'reverse').innerText;
if (i == 4) {
document.getElementById('searchForAlternativeSolutions').checked = true;
} else {
document.getElementById('searchForAlternativeSolutions').checked = false;
}
}
function reverse() {
var s = document.getElementById('reverse').value;
s = s.trim().toUpperCase();
if (s == "") {
alert("Please specify the sequence to reverse in the 'Reverse sequence' field.");
return;
}
var result = s.split("").reverse();
for (var i = 0; i < result.length; i++) {
var character = result[i];
result[i] = reverseLookup[character];
if (result[i] == "" || result[i] == undefined) {
alert("Illegal character '" + character + "' detected in 'Reverse sequence'!");
return;
}
}
result = result.join("");
document.getElementById('reverse').value = result;
}
function addColorsIfUnderscore(s) {
var result = [];
for (var i = 0; i < s.length; i++) {
if (s[i] == "_") {
result.push("<span class='bgred'>_</span>");
} else {
result.push(s[i]);
}
}
return result.join("");
}
function colorConsensusByIncompatiblePositions() {
var txt1 = document.getElementById('consensus1').innerText;
var txt2 = document.getElementById('consensus2').innerText;
document.getElementById('consensus1').innerHTML = addColorsIfUnderscore(txt1);
document.getElementById('consensus2').innerHTML = addColorsIfUnderscore(txt2);
}
function addColorsIfAmb(s) {
var result = [];
for (var i = 0; i < s.length; i++) {
if (s[i] == "_" || s[i] == "A" || s[i] == "C" || s[i] == "T" || s[i] == "G" || s[i] == "a" || s[i] == "c" || s[i] == "t" || s[i] == "g") {
result.push(s[i]);
} else {
if (s[i] == s[i].toUpperCase()) {
result.push("<span class='bgred'>" + s[i] + "</span>");
} else {
result.push("<span class='bgyellow'>" + s[i] + "</span>");
}
}
}
return result.join("");
}
function changePosition(i, c, name, positions, green) {
var greenX = green.split(",");
var newNN = prompt("Changing nucleotide at position " + (i + 1) + " from '" + c + "' to:");
if (newNN == null || newNN == "") { // Cancel or no input
return;
}
newNN = newNN.toUpperCase();
if (newNN.length != 1 || reverseLookup[newNN] == undefined) {
alert("Illegal input!");
return;
}
// ok, change
var string = document.getElementById(name).value.trim();
string = string.replaceAt(i, newNN);
document.getElementById(name).value = string;
// recolor
greenX.push("" + i);
positions = positions.split(",");
for (var ii = 0; ii < positions.length; ii++) {
positions[ii] = parseInt(positions[ii]);
}
if (name == "forward") {
var txt1i = document.getElementById('input1').innerText;
document.getElementById('input1').innerHTML = addColorsForPositions(txt1i, positions, true, "forward", greenX.join(","));
} else if (name == "reverse") {
var txt2i = document.getElementById('input2').innerText;
document.getElementById('input2').innerHTML = addColorsForPositions(txt2i, positions, true, "reverse", greenX.join(","));
}
}
function isInGreen(ii, green) {
var greenX = green.split(",");
for (var i = 0; i < greenX.length; i++) {
var part = parseInt(greenX[i]);
if (!isNaN(part) && ii == part) {
return true;
}
}
return false;
}
function addColorsForPositions(s, positions, addLinks, name, green="") {
var result = [];
for (var i = 0; i < s.length; i++) {
var correctedPosition = i + 1;
if (positions.includes(correctedPosition)) {
if (s[i] == s[i].toUpperCase()) {
var toAdd = s[i];
if (addLinks) {
toAdd = "<a onclick='changePosition(" + i + ", \"" + s[i] + "\", \"" + name + "\", \"" + positions.join(",") + "\", \"" + green + "\")'>" + toAdd + "</a>";
}
result.push("<span class='" + ((isInGreen(i, green)) ? "bggreen" : "bgred") + "'>" + toAdd + "</span>");
} else {
result.push("<span class='bgyellow'>" + s[i] + "</span>");
}
} else {
result.push(s[i]);
}
}
return result.join("");
}
function colorConsensusByAmbPositions() {
var txt1 = document.getElementById('consensus1').innerText;
var txt2 = document.getElementById('consensus2').innerText;
document.getElementById('consensus1').innerHTML = addColorsIfAmb(txt1);
document.getElementById('consensus2').innerHTML = addColorsIfAmb(txt2);
}
function removeColor() {
var txt1 = document.getElementById('consensus1').innerText.trim();
var txt2 = document.getElementById('consensus2').innerText.trim();
document.getElementById('consensus1').innerText = txt1;
document.getElementById('consensus2').innerText = txt2;
}
function colorFinalByAmbPositions() {
var txt1 = document.getElementById('reconstructed1').innerText;
var txt2 = document.getElementById('reconstructed2').innerText;
document.getElementById('reconstructed1').innerHTML = addColorsIfAmb(txt1);
document.getElementById('reconstructed2').innerHTML = addColorsIfAmb(txt2);
}
function colorFinalByPositions(i1, i2, p1, p2) {
var i1s = i1.split(",");
for (var i = 0; i < i1s.length; i++) {
i1s[i] = parseInt(i1s[i]);
}
var i2s = i2.split(",");
for (var i = 0; i < i2s.length; i++) {
i2s[i] = parseInt(i2s[i]);
}
var p1s = p1.split(",");
for (var i = 0; i < p1s.length; i++) {
p1s[i] = parseInt(p1s[i]);
}
var p2s = p2.split(",");
for (var i = 0; i < p2s.length; i++) {
p2s[i] = parseInt(p2s[i]);
}
var txt1i = document.getElementById('input1').innerText;
var txt2i = document.getElementById('input2').innerText;
document.getElementById('input1').innerHTML = addColorsForPositions(txt1i, i1s, true, "forward");
document.getElementById('input2').innerHTML = addColorsForPositions(txt2i, i2s, true, "reverse");
var txt1 = document.getElementById('reconstructed1').innerText;
var txt2 = document.getElementById('reconstructed2').innerText;
document.getElementById('reconstructed1').innerHTML = addColorsForPositions(txt1, p1s, false);
document.getElementById('reconstructed2').innerHTML = addColorsForPositions(txt2, p2s, false);
}
function colorProblems() {
var txt1 = document.getElementById('reconstructed1').innerText;
var txt2 = document.getElementById('reconstructed2').innerText;
document.getElementById('reconstructed1').innerHTML = addColorsIfUnderscore(txt1);
document.getElementById('reconstructed2').innerHTML = addColorsIfUnderscore(txt2);
}
function colorAmbPos() {
var txt1 = document.getElementById('reconstructed1').innerText;
var txt2 = document.getElementById('reconstructed2').innerText;
document.getElementById('reconstructed1').innerHTML = addColorsIfAmb(txt1);
document.getElementById('reconstructed2').innerHTML = addColorsIfAmb(txt2);
}
function removeColorFinal() {
var txt1i = document.getElementById('input1').innerText.trim();
var txt2i = document.getElementById('input2').innerText.trim();
document.getElementById('input1').innerText = txt1i;
document.getElementById('input2').innerText = txt2i;
var txt1 = document.getElementById('reconstructed1').innerText.trim();
var txt2 = document.getElementById('reconstructed2').innerText.trim();
document.getElementById('reconstructed1').innerText = txt1;
document.getElementById('reconstructed2').innerText = txt2;
}
function showMore() {
var i = 1, j = 0;
var endReached = false;
while (true) {
var ele = document.getElementById('scoreTableLine' + i);
if (ele == null) {
endReached = true;
break;
}
if (ele.classList.contains("hiddenLine")) {
ele.classList.remove("hiddenLine");
j++;
}
if (j >= 5) {
var ele2 = document.getElementById('scoreTableLine' + (i + 1));
if (ele2 == null) {
endReached = true;
}
break;
}
i++;
}
if (endReached) {
document.getElementById("showMoreButton").style.display = "none";
} else {
document.getElementById("showMoreButton").style.display = "initial";
}
document.getElementById("showLessButton").style.display = "initial";
}
function showLess() {
var i = 1;
while (true) {
var ele = document.getElementById('scoreTableLine' + i);
if (ele == null || ele.classList.contains("hiddenLine")) {
for (var j = 1; j <= 5; j++) {
if (i - j >= 1) {
var ele2 = document.getElementById('scoreTableLine' + (i - j));
ele2.classList.add("hiddenLine");
}
}
break;
}
i++;
}
document.getElementById("showMoreButton").style.display = "initial";
var ele = document.getElementById('scoreTableLine1');
if (ele == null || ele.classList.contains("hiddenLine")) {
document.getElementById("showLessButton").style.display = "none";
} else {
document.getElementById("showLessButton").style.display = "initial";
}
}
function downloadPlot(id) {
var content = document.getElementById(id).outerHTML;
var b64 = window.btoa(content);
var link = "<a id='downloadLink' href-lang='image/svg+xm' href='data:image/svg+xm;base64,\n" + b64 + "' title='plot.svg' style='display:none' download='plot.svg'>Download</a>";
document.getElementById("hiddenDiv").innerHTML = link;
document.getElementById('downloadLink').click();
}
function downloadFasta(full) {
var txt1 = document.getElementById('reconstructed1').innerText;
var txt2 = document.getElementById('reconstructed2').innerText;
if (!full) {
txt1 = txt1.replace(/[a-z]/g, '');
txt2 = txt2.replace(/[a-z]/g, '');
}
var content = [];
content.push(">first");
content.push(txt1);
content.push(">second");
content.push(txt2);
var b64 = window.btoa(content.join('\n'));
var link = "<a id='downloadLink' href-lang='text/fasta' href='data:text/fasta;base64,\n" + b64 + "' title='result.fasta' style='display:none' download='result.fasta'>Download</a>";
document.getElementById("hiddenDiv").innerHTML = link;
document.getElementById('downloadLink').click();
}
function download() {
downloadFasta(true);
}
function highlight(id, score) {
var circle = document.getElementById(id);
var x = circle.getAttribute("cx");
var y = circle.getAttribute("cy");
var svg = document.getElementById("scorePlot");
var newElement = document.createElementNS("http://www.w3.org/2000/svg", "circle");
newElement.setAttribute("id", "addedCircle");
newElement.setAttribute("cx", x);
newElement.setAttribute("cy", y);
newElement.setAttribute("stroke", "red");
newElement.setAttribute("stroke-width", "2");
newElement.setAttribute("fill", "none");
newElement.setAttribute("r", "5");
svg.appendChild(newElement);
var x = 0, y = 0, width = 0, height = 0;
for (var i = 0; i < 28; i++) {
var box = document.getElementById("histBox" + i);
if (box != null) {
var from = box.getAttribute("from");
var to = box.getAttribute("to");
if (from <= score && score < to) {
x = parseInt(box.getAttribute("x")) - 2;
y = parseInt(box.getAttribute("y")) - 2;
width = parseInt(box.getAttribute("width")) + 4;
height = parseInt(box.getAttribute("height")) + 4;
break;
}
}
}
if (x != 0 && y != 0 && width != 0 && height != 0) {
console.log("x: " + x + " y: " + y + " w: " + width + " h: " + height);
var svg2 = document.getElementById("scorePlotHist");
var newElement2 = document.createElementNS("http://www.w3.org/2000/svg", "rect");
newElement2.setAttribute("id", "addedBox");
newElement2.setAttribute("x", x);
newElement2.setAttribute("y", y);
newElement2.setAttribute("width", width);
newElement2.setAttribute("height", height);
newElement2.setAttribute("stroke", "red");
newElement2.setAttribute("stroke-width", "2");
newElement2.setAttribute("fill", "none");
svg2.appendChild(newElement2);
}
}
function removeHighlight(id) {
var svg = document.getElementById("scorePlot");
var circle = document.getElementById("addedCircle");
svg.removeChild(circle);
var svg2 = document.getElementById("scorePlotHist");
var box = document.getElementById("addedBox");
if (box != null) {
svg2.removeChild(box);
}
}
function phighlight(id, score) {
var circle = document.getElementById(id);
var x = circle.getAttribute("cx");
var y = circle.getAttribute("cy");
var svg = document.getElementById("scorePlot");
var newElement = document.createElementNS("http://www.w3.org/2000/svg", "circle");
newElement.setAttribute("id", "paddedCircle_" + id);
newElement.setAttribute("cx", x);
newElement.setAttribute("cy", y);
newElement.setAttribute("stroke", "red");
newElement.setAttribute("stroke-width", "2");
newElement.setAttribute("fill", "none");
newElement.setAttribute("r", "5");
svg.appendChild(newElement);
var x = 0, y = 0, width = 0, height = 0;
for (var i = 0; i < 28; i++) {
var box = document.getElementById("histBox" + i);
if (box != null) {
var from = box.getAttribute("from");
var to = box.getAttribute("to");
if (from <= score && score < to) {
x = parseInt(box.getAttribute("x")) - 2;
y = parseInt(box.getAttribute("y")) - 2;
width = parseInt(box.getAttribute("width")) + 4;
height = parseInt(box.getAttribute("height")) + 4;
break;
}
}
}
if (x != 0 && y != 0 && width != 0 && height != 0) {
console.log("x: " + x + " y: " + y + " w: " + width + " h: " + height);
var svg2 = document.getElementById("scorePlotHist");
var newElement2 = document.createElementNS("http://www.w3.org/2000/svg", "rect");
newElement2.setAttribute("id", "paddedBox_" + id);
newElement2.setAttribute("x", x);
newElement2.setAttribute("y", y);
newElement2.setAttribute("width", width);
newElement2.setAttribute("height", height);
newElement2.setAttribute("stroke", "red");
newElement2.setAttribute("stroke-width", "2");
newElement2.setAttribute("fill", "none");
svg2.appendChild(newElement2);
}
}
function premoveHighlight(id) {
var svg = document.getElementById("scorePlot");
var circle = document.getElementById("paddedCircle_" + id);
svg.removeChild(circle);
var svg2 = document.getElementById("scorePlotHist");
var box = document.getElementById("paddedBox_" + id);
if (box != null) {
svg2.removeChild(box);
}
}
function toggle_phighlight(checkbox, id, score) {
if(checkbox.checked == true){
phighlight(id, score);
} else {
premoveHighlight(id);
}
}
function toClipboard(id, everything=true) {
var text = document.getElementById(id).innerText;
if (!everything) {
text = text.replace(/[a-z]/g, '');
}
navigator.clipboard.writeText(text);
return false;
}
</script>
</body>
</html>